1
\$\begingroup\$

Imagine you have a call center with three levels of employees: respondent, manager, and director. An incoming telephone call must be first allocated to a respondent who is free. If the respondent can’t handle the call, he or she must escalate the call to a manager. If the manager is not free or not able to handle it, then the call should be escalated to a director. Design the classes and data structures for this problem. Implement a method dispatchCall() which assigns a call to the first available employee.

package design;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;

public class CallCenter {
    Employee[] employees;
    int size = 100;
    Map<Employee,PhoneCall> callMap = new TreeMap<Employee, PhoneCall>(new Comparator<Employee>() {
        @Override
        public int compare(Employee o1, Employee o2) {
            return 0;
        }
    });
    Queue<PhoneCall> calls ;
    PriorityQueue<Employee> dispatchQueue;
    CallCenter(){
      employees = new Employee[size];
      calls = new LinkedBlockingQueue<PhoneCall>();
      dispatchQueue = new PriorityQueue<Employee>(new Comparator<Employee>() {
          @Override
          public int compare(Employee o1, Employee o2) {
              if(o1.id > o2.id) return -1;
              else if(o1.id < o2.id) return 1;
              else return 0;
          }
      });
        for(int i = 0;i<size;i++){
            if(i==0 || i==1){
                employees[i] = new Director(i);
            }
            else if(i>=2 && i<=6){
                employees[i] = new Manager(i);
            }else{
                employees[i] = new Respondent(i);
            }
            dispatchQueue.offer(employees[i]);
        }
    }

    public void dispatchCall(PhoneCall p){
        if(dispatchQueue.isEmpty()){
            calls.offer(p);
        }else{
            callMap.put(dispatchQueue.poll(), p);
        }
    }

    public void endCall(Employee emp){
        if(callMap.containsKey(emp)){
            callMap.remove(emp);
            dispatchQueue.offer(emp);
        }
    }


    public void processCallsQueue(){
        while(!calls.isEmpty()){
            if(dispatchQueue.isEmpty())break;
            else dispatchCall(calls.poll());
        }
    }

    public  Employee getRandomEmployee(){
        Random rn = new Random();
        int randomPosition = rn.nextInt(100);
        return employees[randomPosition];

    }



}

class PhoneCall{
    int id;
    String location;
    String number;

    PhoneCall(){
        Random rand = new Random();
        id = rand.nextInt();
        location = "US";
        number = new BigInteger(130,rand).toString();
    }
}

class Employee{
    int id;
    String designation;
    int priority; //priority is the call priority 1. Respondent, 2. Manager , 3. Director

    Employee(){

    }
    Employee(int id){
        this.id = id;
    }

}

class Manager extends Employee{

    Manager(int id){
        super(id);
        designation = "MANAGER";
        priority = 2;
    }
}

class Director extends Employee{

    Director(int id){
        super(id);
        designation = "DIRECTOR";
        priority = 3;
    }
}

class Respondent extends Employee{

    Respondent(int id){
        super(id);
        designation="RESPONDENT";
        priority=1;
    }
}

Is this design too shallow to be done in an interview? Any feedback on the design is greatly appreciated.

\$\endgroup\$
  • \$\begingroup\$ Can the down-voter please provide the reason? It will be helpful too. \$\endgroup\$ – thalaivva Jun 9 '16 at 15:28
2
\$\begingroup\$
    Employee[] employees;
    int size = 100;

Arrays are efficient but not flexible. I would think that you'd prefer the flexibility of something like a List instead.

It's not clear why size is 100.

Object fields should generally be private. Other scopes can be valid, but you should have a specific reason for using them. Which should be commented somewhere.

        public int compare(Employee o1, Employee o2) {
            return 0;
        }

If you don't care about order, why use a TreeMap?

If you're doing something clever, please put a comment in the code that explains why you would want to make every employee equal.

You have two Comparator<Employee> objects defined anonymously. If you have one named class, you can just pass objects of that. You won't need to keep redefining compare methods each time.

            }
            else if(i>=2 && i<=6){
                employees[i] = new Manager(i);
            }else{

You use two different styles for } and else. Please pick one. I'd prefer } else on the same line, but consistency of either would be better than mixing multiple styles.

    public void dispatchCall(PhoneCall p){
        if(dispatchQueue.isEmpty()){
            calls.offer(p);
        }else{
            callMap.put(dispatchQueue.poll(), p);
        }
    }

The problem descriptions says

Implement a method dispatchCall() which assigns a call to the first available employee.

But this method doesn't do that. It dispatches a call to an employee if one is available. Or it puts the call in a queue if not.

My reading is that dispatchCall should block until an employee is available.

        if(callMap.containsKey(emp)){
            callMap.remove(emp);
            dispatchQueue.offer(emp);
        }

Given the way that remove works, you can just say:

        if (callMap.remove(emp) != null) {
            dispatchQueue.offer(emp);
        }

It's unclear if the compiler will optimize both into the same byte code.

        while(!calls.isEmpty()){
            if(dispatchQueue.isEmpty())break;
            else dispatchCall(calls.poll());
        }

I would find this easier to read as

        while (!calls.isEmpty() && !dispatchQueue.isEmpty()) {
            dispatchCall(calls.poll());
        }

It took a couple readings before I followed the previous logic.

    public  Employee getRandomEmployee(){

You never use this method.

        Random rn = new Random();

Rather than create a new Random object on each method call, you should create one for the entire program. Perhaps as static field on CallCenter.

If the respondent can’t handle the call, he or she must escalate the call to a manager. If the manager is not free or not able to handle it, then the call should be escalated to a director.

You rely purely on id ordering to do this. So what happens if you add a new director? You'd have to reassign the id values for the managers and respondents. Same thing if you promote someone.

Worse, you don't document this behavior. So if the person evaluating the code doesn't realize this, they'll fail you on that requirement.

    String designation;

Rather than make the designation a String, it would make more sense for it to be an enum. A typo in a string is a runtime issue. A typo in an enum will be caught at compile time.

    int priority; //priority is the call priority 1. Respondent, 2. Manager , 3. Director

This just holds an alternate form of designation. You set but never use either of them. Why have them?

Evaluating

If I were evaluating you on this, I would mark you down for not following the instructions. I don't necessarily find it too shallow so much as not focused enough. You put extra effort into creating unnecessary fields, e.g. all those in PhoneCall. But you don't actually implement the basics.

This code feels sort of half-implemented. It's like you had a bunch of ideas that you started but didn't finish. Code should be purposeful. If you decide not to use something, remove it rather than leave it half done.

You also don't do any testing. It's not clear to me how to run this code. To really evaluate it, I'd have to write my own tests from scratch. Writing your own tests would not only make it easier for me to test, it would make it more likely that you would catch errors before sending the code.

\$\endgroup\$
  • \$\begingroup\$ Hi @mdfst13 , thanks for your comments. For the dispatchCall(), the description says assign it to first available employee. I am keeping a PriorityQueue of employees that are available to receive a call. The Priority Queue is ordered such that respondents get first priority then manager, then director (as per description) . It also provides so that if a on-call respondent is done with the call, the employee gets added back to the dispatch priority queue. So as long as there is atleast 1 respondenet available, manager & director won't have to attend the call. \$\endgroup\$ – thalaivva Jun 9 '16 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.