// CS U213 Spring 2008 // Lecture 8: January 28, 2007 /* ;; A Boss is (make-sup String String Number [Listof Employee]) (define-struct sup (name unit tasks peons)) ;; A Worker is (make-worker String Number)) (define-struct worker (name tasks)) ;; An Employee is one of ;; -- Boss ;; -- Worker ;; A [Listof Employee] is one of ;; -- empty ;; -- (cons Employee [Listof Employee]) +-----------+ | Emp |<-----------------------------+ +-----------+ | | | | +-----------+ | | | | | /_\ | | | +-----------------------------------+ | | | | +----------------+ +------------------+ | | Worker | | Boss | | +----------------+ +------------------+ | |String name | | String name | | |int tasks | | String unit | | +----------------+ | int tasks | | +--------+ ListofEmp peons | | | +------------------+ | | | v | +--------------+ | | ListofEmp |<------------------------+--+ +--------------+ | | +--------------+ | | | | | | | | /_\ | | | | | +--------------------------------+ | | v v | | +-----------------+ +-------------------+ | | | MTListofEmp | | ConsListofEmp | | | +-----------------+ +-------------------+ | | +-----------------+ | Emp first +---+ | | ListofEmp rest +------+ +-------------------+ */ // to represent an employee of a company interface Emp { // count all Employees int countAll(); // is there a boss with the given name? boolean isBoss(String name); // produce a list of all subordinates of this boss ListofEmp allUnit(); } // to represent an employee with no subordinates class Worker implements Emp { String name; int tasks; Worker(String name, int tasks){ this.name = name; this.tasks = tasks; } /* TEMPLATE: FIELDS: ... this.name ... -- String ... this.tasks ... -- int METHODS: ... this.countAll() ... -- int ... this.isBoss(String) ... -- boolean ... this.allUnit() ... -- ListofEmp */ // count all Employees int countAll() { return 1; } // is there a boss with the given name? boolean isBoss(String name){ return false; } // produce a list of all subordinates of this boss ListofEmp allUnit(){ return new ConsListofEmp(this, new MTListofEmp()); } } // to represent an employee in charge of a unit, // with a list of all subordinates class Boss implements Emp { String name; String unit; int tasks; ListofEmp peons; Boss(String name, String unit, int tasks, ListofEmp peons){ this.name = name; this.unit = unit; this.tasks = tasks; this.peons = peons; } /* TEMPLATE: FIELDS: ... this.name ... -- String ... this.unit ... -- String ... this.tasks ... -- int ... this.peons ... -- ListofEmp METHODS: ... this.countAll() ... -- int ... this.isBoss(String) ... -- boolean ... this.allUnit() ... -- ListofEmp METHODS FOR FIELDS: ... this.peons.countAll() ... -- int ... this.peons.containsBoss(String) ... -- boolean ... this.peons.allUnit() ... -- ListofEmp */ // count all Employees int countAll(){ return 1 + this.peons.countAll(); } // produce a list of all subordinates of this boss ListofEmp allUnit(){ return new ConsListofEmp(this, this.peons.allUnit()); } // is there a boss with the given name? boolean isBoss(String name){ if (name.equals(this.name)){ return true; } else{ return this.peons.containsBoss(name); } } } // to represent a list of all employees interface ListofEmp { // count all employees in the list int countAll(); // is there a boss with the given name? boolean containsBoss(String name); // produce a list of all subordinates in this list of employees ListofEmp allUnit(); // append the given list to this nonempty list ListofEmp append(ListofEmp that); } // to represent an empty list of all employees class MTListofEmp implements ListofEmp { MTListofEmp() {} // count all employees in the list int countAll(){ return 0; } // is there a boss with the given name? boolean containsBoss(String name){ return false; } // produce a list of all subordinates in this empty list of employees ListofEmp allUnit(){ return this; } // append the given list to this empty list ListofEmp append(ListofEmp that){ return that; } } // to represent a list of all employees class ConsListofEmp implements ListofEmp { Emp first; ListofEmp rest; ConsListofEmp(Emp first, ListofEmp rest){ this.first = first; this.rest = rest; } /* TEMPLATE: FIELDS: ... this.first ... -- Emp ... this.rest ... -- ListofEmp METHODS: ... this.countAll() ... -- int ... this.containsBoss(String) ... -- boolean ... this.allUnit() ... -- ListofEmp ... this.append(ListofEmp) ... -- ListofEmp METHODS FOR FIELDS: ... this.rest.countAll() ... -- int ... this.rest.containsBoss(String) ... -- boolean ... this.rest.allUnit() ... -- ListofEmp ... this.rest.append(ListofEmp) ... -- ListofEmp */ // count all employees in the list int countAll() { return this.first.countAll() + this.rest.countAll(); } // is there a boss with the given name? boolean containsBoss(String name){ return this.first.isBoss(name) || this.rest.containsBoss(name); } // produce a list of all subordinates in this nonempty list of employees ListofEmp allUnit(){ return this.first.allUnit().append(this.rest.allUnit()); } // append the given list to this nonempty list ListofEmp append(ListofEmp that){ return new ConsListofEmp(this.first, this.rest.append(that)); } } // examples/tests for the classes to represent a company employee hierarchy class Examples { Examples() {} Emp wkA = new Worker("A",3); Emp wkB = new Worker("B",5); Emp wkC = new Worker("C",6); Emp wkD = new Worker("D",4); Emp wkE = new Worker("E",5); Emp wkF = new Worker("F",2); Emp wkG = new Worker("G",8); Emp wkH = new Worker("H",6); ListofEmp mtlist = new MTListofEmp(); ListofEmp grpAlist = new ConsListofEmp(this.wkC,this.mtlist); Emp mike = new Boss("Mike", "Group A", 10, this.grpAlist); ListofEmp secAlist = new ConsListofEmp(this.mike, new ConsListofEmp(this.wkD, new ConsListofEmp(this.wkE,this.mtlist))); Emp jack = new Boss("Jack", "Section A", 25, this.secAlist); ListofEmp secBlist = new ConsListofEmp(this.wkF, new ConsListofEmp(this.wkG, this.mtlist)); Emp jenn = new Boss("Jenn", "Section B", 15, this.secBlist); ListofEmp secClist = new ConsListofEmp(this.wkH,this.mtlist); Emp pat = new Boss("Pat", "Section C", 20, this.secClist); ListofEmp secDlist = new ConsListofEmp(this.wkB, this.mtlist); Emp pete = new Boss("Pete", "Section D", 10, this.secDlist); ListofEmp operList = new ConsListofEmp(this.jack, new ConsListofEmp(this.jenn, new ConsListofEmp(this.pat, this.mtlist))); Emp dave = new Boss("Dave","Operations", 70, this.operList); ListofEmp financeList = new ConsListofEmp(this.wkA, new ConsListofEmp(this.pete, this.mtlist)); Emp anne = new Boss("Anne", "Finance", 20, this.financeList); ListofEmp ceoList = new ConsListofEmp(this.dave, new ConsListofEmp(this.anne,this.mtlist)); Emp meg = new Boss("Meg","CEO", 100, this.ceoList); //test the method countAll for the employee hierarchy boolean t1 = check this.secAlist.countAll() expect 4; boolean t2 = check this.mtlist.countAll() expect 0; boolean t3 = check this.financeList.countAll() expect 3; //test the method isBoss for the employee hierarchy boolean testBoss(){ return (check this.dave.isBoss("Mike") expect true) && (check this.dave.isBoss("Pete") expect false) && (check this.dave.isBoss("D") expect false) && (check this.dave.isBoss("Jake") expect false); } //test the method allUnit for the employee hierarchy boolean testAllUnit(){ return (check this.wkA.allUnit() expect new ConsListofEmp(this.wkA, this.mtlist)) && (check this.mike.allUnit() expect new ConsListofEmp(this.mike, new ConsListofEmp(this.wkC, this.mtlist))) && (check this.jack.allUnit() expect new ConsListofEmp(this.jack, new ConsListofEmp(this.mike, new ConsListofEmp(this.wkC, new ConsListofEmp(this.wkD, new ConsListofEmp(this.wkE, this.mtlist)))))) && (check this.meg.allUnit() expect new ConsListofEmp(this.meg, new ConsListofEmp(this.dave, new ConsListofEmp(this.jack, new ConsListofEmp(this.mike, new ConsListofEmp(this.wkC, new ConsListofEmp(this.wkD, new ConsListofEmp(this.wkE, new ConsListofEmp(this.jenn, new ConsListofEmp(this.wkF, new ConsListofEmp(this.wkG, new ConsListofEmp(this.pat, new ConsListofEmp(this.wkH, new ConsListofEmp(this.anne, new ConsListofEmp(this.wkA, new ConsListofEmp(this.pete, new ConsListofEmp(this.wkB, this.mtlist))))))))))))))))); } } /* With the preceding examples draw a company structure diagram. Try to capture all the information from the examples in your diagram. +------+ | Meg | | CEO | | 100| +--+---+ | +-----------------+-----------------------------+ | | | | +------------+ +---+-----+ | Dave | | Anne | | Operations | | Finance | | 70| | 20| +------+-----+ +-----+---+ | | | | +-----------+-------------------+------------+ +---+----+ | | | | | +-----------+ +-----+-----+ +----+------+ +----+ +----+------+ | Jack | | Jenn | | Pat | | A | | Pete | | Section A | | Section B | | Section C | | 3| | Section D | | 25| | 15| | 20| +----+ | 10| +----+------+ +----+------+ +----+------+ +----+------+ | | | | | | | | | | | +--+--+ +--+--------+-------+ +--+----+ +----+ | B | | | | | | | H | | 5| +---------+ +----+ +----+ +----+ +----+ | 6| +-----+ | Mike | | D | | E | | F | | G | +----+ | Group A | | 4| | 2| | 8| | 6| | 10| +----+ +----+ +----+ +----+ +--+------+ | | +----+ | C | | 6| +----+ Some questions that you might want to answer for our company example are: (a) How many subordinates does a Boss have? (b) How many tasks does a Boss delegate to subordinates? (c) How many direct tasks does a Boss undertake? (d) How many level of subordinates does a Boss have? We can design methods that can answer these questions. We'll start with (a) from the list above. 1) Problem analysis: We need to count all the subordinates. Only Boss has subordinates. 2) Purpose Statement and Header // count all subordinates int countSubs(){ ... } 3) Examples: anne.countSubs() => 3 dave.countSubs() => 10 4) Template int countSubs() { ... this.name ... // string ... this.unit ... // string ... this.tasks ... // int ... this.peons ... // ListofEmp } We need to count all subordinates. So we are interested in this.peons. We need to count all the elements in a ListofEmp. But a ListofEmp can contain Workers or Bosses again. WE NEED A HELPER FUNCTION THAT COUNTS THE SUBORDINATES INSIDE A ListofEmp. We'll call our helper function countAll. So again from step 1 1) Problem statement Count all the subordinates 2) Purpose statement and Header Add to ListofEmp, MTListofEmp, ConsListofEmp. We also need to add this to Emp, Worker and Boss. Since the elements of the list are all Emps and we need to find each of their subordinates, each Emp has to be able to report back its total number of subordinates. // count all elements in the list workers // bosses and their subordinates. int countAll(){ ... } 3) Examples: secAlist.countAll() => 4 mtList.countAll() => 0 financeList.countAll() => 3 4) Template MTListofEmp : int countAll() { ... } ConsListofEmp : int countAll() { ... this.first ... //Emp ... this.rest ... //ListofEmp ... this.rest.countAll() ... // int } 5) Method Body MTListofEmp : int countAll() { return 0; } ConsListofEmp : int countAll() { return this.first.countAll() + this.rest.countAll(); } Worker: int countAll(){ return 1; } Boss: int countAll(){ return 1 + this.countSubs();} 5) Method Body int countSubs() { return this.peons.countAll(); } We'll write a table with a interface/class as a column. In each column we will write the methods that we designed Emp | Worker | Boss | | // count all employees | int countAll(){ | // how many subordinates int countAll(); | return 1; } | int countSubs(){ | | this.peons.countAll();} | | | | int countAll(){ | | return 1 + this.countSubs(); | | } -----------------------+----------------------+------------------------------------- ListofEmp | MTListofEmp | ConsListofEmp //count all peons and | int countAll(){ | int countAll() { //Bosses | return 0; | return first.countAll() + int countAll() | } | rest.countAll(); | | } | | | | | |