Call Center
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 respondenet 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 assins a call to the first available employee.
Handle Ambiguity
- How many respondent, manager and director in this call center?
- How to determine if they can handle the call or not?
- How to handle calls if there's no one who's free to pick up?
Core Objects and Their Relationships
Employee Class
All three ranks of employees have different work to be done, so those specific functions are profil specific. We should keep those things within their respective class.
There are a few things which are common to all of them, like address, name, job title, and age. These things can be kept in one class and can be extended or inherited by others.
Employee is a super class for the Director, Manager and Respondent classes. It is implemented as an abstract class since there should be no reason to instantiate an Employee type directly.
enum class Rank {
Respondent,
Manager,
Director
};
class Employee {
public:
virtual Rank getRank();
/* Start the conversation */
virtual void receiveCall(Call call);
/* the issue is resolved, finish the call */
virtual void callCompleted();
/* the issue has not been resolved, escalate the call and assign a new call to the employer */
virtual void escalateAndReassign();
/* assign a new call to the employee, if the employee is free */
virtual bool assignNewCall();
/* returns whether or not the employee is free */
virtual bool isFree();
protected:
int age;
string firstName;
string lastName;
string title;
string address;
string gender;
Rank rank;
};
class Respondent: Employee {
public:
Respondent() {
rank = Rank::Respondent;
}
};
class Manager: Employee {
public:
Manager() {
rank = Rank::Manager;
}
};
class Director: Employee {
public:
Director() {
rank = Rank::Director;
}
};
Call
Call represents a call from a user. A call has a minimum rank and is assigned to the first employee who can handle it.
class Call {
public:
Call(Caller *_caller) {
caller = _caller;
rank = Rank::Respondent;
};
int getRank();
Caller* getCaller();
Employee* getHandler();
void setRant(Rank rank);
void setHandler(Employee *handler);
Rank incrementRank();
void disconnect();
void reply(string message);
private:
/* minimum rank who can handle this call */
Rank rank;
/* the person who is calling */
Caller* caller;
/* the employee who is handling */
Employee* handler;
};
CallRouter
Finally there should be one CallRouter class which would route the calls to the correct person.
class CallRoute {
public:
CallRoute();
private:
/* Initialize 10 respondents, 4 managers, and 2 directors. */
int numOfRespondents = 10;
int numOfManagers = 4;
int numOfDirectors = 2;
/* List of employees, by level.
* employeeLevels[0] = respondents
* employeeLevels[l] = managers
* employeeLevels[2] = directors
*/
vector<Employee> levelOfEmployees;
/* Queue for incoming calls */
vector<queue<Call>> callQueues;
/* Gets the first available employee who can handle this call. */
Employee* getHandlerForCall(Call call);
/* Routes the call to an available employee, or saves in a queue if no employee is available. */
void dispatchCall(Caller *caller);
/* Routes the call to an available employee, or saves in a queue if no employee is available. */
void dispatchCall(Call call) {
Employee *handler = getHandlerForCall(call);
if (handler) {
handler->receiveCall(call);
call.setHandler(handler);
} else {
/* Place the call into corresponding call queue according to its rank. */
call.reply("Please wait for free employee to reply");
callQueues[call.getRank()].push(call);
}
};
/* An employee got free. Look for a waiting call that employee can serve.
* Return true if we assigned a call, false otherwise. */
bool assignCall(Call call);
};