# OOPS



s\_ood [https://www.educative.io/collection/page/5668639101419520/5692201761767424/5636470266134528](https://www.educative.io/collection/page/5668639101419520/5692201761767424/5636470266134528)

[https://www.careercup.com/question?id=64946](https://www.careercup.com/question?id=64946)

[https://www.geeksforgeeks.org/design-an-online-book-reader-system/](https://www.geeksforgeeks.org/design-an-online-book-reader-system/) [https://www.geeksforgeeks.org/design-movie-ticket-booking-system-like-bookmyshow/](https://www.geeksforgeeks.org/design-movie-ticket-booking-system-like-bookmyshow/)

{% embed url="https://medium.com/@narengowda/bookmyshow-system-design-e268fefb56f5" %}





```
package com.gs.corejava.oopsModeling;

/**
 * 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.
 * 
 * @author momalhotra
 * 
 */
public class CallCenterModellingTest {
	public static void main(String[] args) {
		CallManagement callManagement = new CallManagement();
		callManagement.callCustomerCare();
	}
}

enum EmployeeType {
	RESPONDENT, MANAGER, DIRECTOR,
}

abstract class Employee {
	private long empId;
	private String name;
	private boolean isFree;
	private EmployeeType employeeType;

	/**
	 * @param empId
	 * @param name
	 * @param employeeType
	 */
	public Employee(long empId, String name, EmployeeType employeeType) {
		super();
		this.empId = empId;
		this.name = name;
		this.employeeType = employeeType;
	}

	/**
	 * @param empId
	 * @param name
	 * @param isFree
	 * @param employeeType
	 */
	public Employee(long empId, String name, boolean isFree,
			EmployeeType employeeType) {
		super();
		this.empId = empId;
		this.name = name;
		this.isFree = isFree;
		this.employeeType = employeeType;
	}

	/**
	 * @return the empId
	 */
	public long getEmpId() {
		return empId;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the employeeType
	 */
	public EmployeeType getEmployeeType() {
		return employeeType;
	}

	/**
	 * @param employeeType
	 *            the employeeType to set
	 */
	public void setEmployeeType(EmployeeType employeeType) {
		this.employeeType = employeeType;
	}

	/**
	 * @return the isFree
	 */
	public boolean isFree() {
		return isFree;
	}

	/**
	 * @param isFree
	 *            the isFree to set
	 */
	public void setFree(boolean isFree) {
		this.isFree = isFree;
	}

}

interface CallDispatcher {
	public void dispatchCaLL();
}

class Respondent extends Employee implements CallDispatcher {

	public Respondent(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.RESPONDENT);
	}

	@Override
	public void dispatchCaLL() {
		System.out.println("Call responded by " + getEmployeeType() + " "
				+ getEmpId());
	}

}

class Manager extends Employee implements CallDispatcher {

	public Manager(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.MANAGER);
	}

	@Override
	public void dispatchCaLL() {
		System.out.println("Call responded by " + getEmployeeType() + " "
				+ getEmpId());
	}

}

class Director extends Employee implements CallDispatcher {

	public Director(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.DIRECTOR);
	}

	@Override
	public void dispatchCaLL() {
		System.out.println("Call responded by " + getEmployeeType() + " "
				+ getEmpId());
	}

}

class CallManagement {

	private Employee[] repondents;
	private Employee[] managers;
	private Employee[] directors;

	public CallManagement() {
		Employee respondent1 = new Respondent(1, "respondent1", false);
		Employee respondent2 = new Respondent(2, "respondent2", false);
		Employee respondent3 = new Respondent(3, "respondent3", false);
		Employee respondent4 = new Respondent(4, "respondent4", false);

		repondents = new Employee[4];

		repondents[0] = respondent1;
		repondents[1] = respondent2;
		repondents[2] = respondent3;
		repondents[3] = respondent4;

		Employee manager1 = new Manager(5, "manager1", false);
		Employee manager2 = new Manager(6, "manager2", false);

		managers = new Employee[2];

		managers[0] = manager1;
		managers[1] = manager2;

		Employee director1 = new Director(7, "director1", true);

		directors = new Employee[1];

		directors[0] = director1;

	}

	public void callCustomerCare() {
		boolean callDispatched = false;
		for (Employee emp : repondents) {
			Respondent respondent = (Respondent) emp;
			if (respondent.isFree()) {
				respondent.dispatchCaLL();
				callDispatched = true;
				break;
			}
		}
		if (!callDispatched) {
			for (Employee emp : managers) {
				Manager manager = (Manager) emp;
				if (manager.isFree()) {
					manager.dispatchCaLL();
					callDispatched = true;
					break;
				}
			}
		}
		if (!callDispatched) {
			for (Employee emp : directors) {
				Director director = (Director) emp;
				if (director.isFree()) {
					director.dispatchCaLL();
					callDispatched = true;
					break;
				}
			}
		}

	}
}
```

```
-------------------------CASE 2----------------

package com.gs.corejava.oopsModeling;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 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.
 * 
 * @author momalhotra
 * 
 */
public class CallCenterModellingTest {
	public static void main(String[] args) {

		List<Call> calls = new ArrayList<Call>(15);
		CallManagement callManagement = new CallManagement();
		for (int i = 1; i < 15; i++) {
			Caller caller = new Caller(i, "caller " + i, 556556656 + i);
			Call call = new Call(caller);
			calls.add(call);
		}

		callManagement.callCustomerCare(calls);
	}
}

class Company {
	public static int NUMBER_OF_RESPONDENTS = 5;
	public static int NUMBER_OF_MANAGERS = 3;
	public static int NUMBER_OF_DIRECTORS = 2;

	public static List<List<Employee>> listOfAllEmployees = new ArrayList<List<Employee>>(
			3);

	static {
		List<Employee> respodents = new ArrayList<Employee>(
				NUMBER_OF_RESPONDENTS);
		List<Employee> managers = new ArrayList<Employee>(NUMBER_OF_MANAGERS);
		List<Employee> directors = new ArrayList<Employee>(NUMBER_OF_DIRECTORS);

		buildCompany(respodents, EmployeeType.RESPONDENT);
		buildCompany(managers, EmployeeType.MANAGER);
		buildCompany(directors, EmployeeType.DIRECTOR);

	}

	private static void buildCompany(List<Employee> employees,
			EmployeeType employeeType) {
		Random random = new Random();
		if (employeeType == EmployeeType.RESPONDENT) {
			for (int i = 0; i < NUMBER_OF_RESPONDENTS; i++) {
				Employee respondent = new Respondent(i, "respondent " + i,
						random.nextBoolean());
				employees.add(respondent);
			}
			listOfAllEmployees.add(employees);
		}

		if (employeeType == EmployeeType.MANAGER) {
			for (int i = 0; i < NUMBER_OF_MANAGERS; i++) {
				Employee manager = new Manager(i, "manager " + i,
						random.nextBoolean());
				employees.add(manager);
			}
			listOfAllEmployees.add(employees);
		}

		if (employeeType == EmployeeType.DIRECTOR) {
			for (int i = 0; i < NUMBER_OF_DIRECTORS; i++) {
				Employee director = new Director(i, "director " + i,
						random.nextBoolean());
				employees.add(director);
			}
			listOfAllEmployees.add(employees);
		}

	}
}

enum CallStatus {
	CREATED, RESPONDED
}

class Caller {
	private long callerId;
	private String name;
	private long callerNumber;

	/**
	 * @param callerId
	 * @param name
	 * @param callerNumber
	 */
	public Caller(long callerId, String name, long callerNumber) {
		super();
		this.callerId = callerId;
		this.name = name;
		this.callerNumber = callerNumber;
	}

	/**
	 * @return the callerId
	 */
	public long getCallerId() {
		return callerId;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the callerNumber
	 */
	public long getCallerNumber() {
		return callerNumber;
	}

	/**
	 * @param callerNumber
	 *            the callerNumber to set
	 */
	public void setCallerNumber(long callerNumber) {
		this.callerNumber = callerNumber;
	}

	@Override
	public String toString() {
		return "Caller [callerId=" + callerId + ", name=" + name
				+ ", callerNumber=" + callerNumber + "]";
	}

}

class CallHandler implements CallDispatcher {

	private CallHandler() {

	}

	private static CallHandler _instance = new CallHandler();

	public static CallHandler getInstance() {
		return _instance;
	}

	public void handleCalls(List<Call> calls) {
		while (!calls.isEmpty()) {

			Call call = calls.get(calls.size() - 1);
			if (call.getCallStatus().equals(CallStatus.CREATED)) {
				dispatchCaLL(call, EmployeeType.RESPONDENT);
				if (call.getCallStatus() == CallStatus.RESPONDED) {
					calls.remove(call);
				}
			}
		}
	}

	@Override
	public void dispatchCaLL(Call call, EmployeeType employeeType) {
		List<Employee> employees = Company.listOfAllEmployees.get(employeeType
				.ordinal());
		for (Employee employee : employees) {
			if (employee.isFree()) {
				call.setCallStatus(CallStatus.RESPONDED);
				System.out.println("Call responded by " + employee);
			}
		}
		if (call.getCallStatus() == CallStatus.CREATED
				&& EmployeeType.RESPONDENT == employeeType) {
			dispatchCaLL(call, EmployeeType.MANAGER);
		} else if (call.getCallStatus() == CallStatus.CREATED
				&& EmployeeType.MANAGER == employeeType) {
			dispatchCaLL(call, EmployeeType.DIRECTOR);
		}
	}
}

class Call {
	private Caller caller;
	private CallStatus callStatus;

	/**
	 * @param caller
	 * @param callStatus
	 */
	public Call(Caller caller) {
		super();
		this.caller = caller;
		this.callStatus = CallStatus.CREATED;
	}

	/**
	 * @return the caller
	 */
	public Caller getCaller() {
		return caller;
	}

	/**
	 * @param caller
	 *            the caller to set
	 */
	public void setCaller(Caller caller) {
		this.caller = caller;
	}

	/**
	 * @return the callStatus
	 */
	public CallStatus getCallStatus() {
		return callStatus;
	}

	/**
	 * @param callStatus
	 *            the callStatus to set
	 */
	public void setCallStatus(CallStatus callStatus) {
		this.callStatus = callStatus;
	}

}

enum EmployeeType {
	RESPONDENT, MANAGER, DIRECTOR,
}

abstract class Employee {
	private long empId;
	private String name;
	private boolean isFree;
	private EmployeeType employeeType;

	/**
	 * @param empId
	 * @param name
	 * @param employeeType
	 */
	public Employee(long empId, String name, EmployeeType employeeType) {
		super();
		this.empId = empId;
		this.name = name;
		this.employeeType = employeeType;
	}

	/**
	 * @param empId
	 * @param name
	 * @param isFree
	 * @param employeeType
	 */
	public Employee(long empId, String name, boolean isFree,
			EmployeeType employeeType) {
		super();
		this.empId = empId;
		this.name = name;
		this.isFree = isFree;
		this.employeeType = employeeType;
	}

	/**
	 * @return the empId
	 */
	public long getEmpId() {
		return empId;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the employeeType
	 */
	public EmployeeType getEmployeeType() {
		return employeeType;
	}

	/**
	 * @param employeeType
	 *            the employeeType to set
	 */
	public void setEmployeeType(EmployeeType employeeType) {
		this.employeeType = employeeType;
	}

	/**
	 * @return the isFree
	 */
	public boolean isFree() {
		return isFree;
	}

	/**
	 * @param isFree
	 *            the isFree to set
	 */
	public void setFree(boolean isFree) {
		this.isFree = isFree;
	}

	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", name=" + name + ", isFree="
				+ isFree + ", employeeType=" + employeeType + "]";
	}

}

interface CallDispatcher {

	void dispatchCaLL(Call call, EmployeeType employeeType);
}

class Respondent extends Employee {

	public Respondent(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.RESPONDENT);
	}

}

class Manager extends Employee {

	public Manager(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.MANAGER);
	}

}

class Director extends Employee {

	public Director(long empId, String name, boolean isFree) {
		super(empId, name, isFree, EmployeeType.DIRECTOR);
	}

}

class CallManagement {

	private CallHandler callHandler = CallHandler.getInstance();

	public void callCustomerCare(List<Call> calls) {
		callHandler.handleCalls(calls);
	}
}


--------------------------END------------------------

-----------------------CASE 3-----------------------


@Override
	public void dispatchCaLL(Call call, EmployeeType employeeType,
			List<Call> calls) {
		List<Employee> employees = Company.listOfAllEmployees.get(employeeType
				.ordinal());
		while (!calls.isEmpty()) {
			for (Employee employee : employees) {
				if (employee.isFree()) {
					call.setCallStatus(CallStatus.RESPONDED);
					System.out.println("Call from "
							+ call.getCaller().getCallerId() + " responded by "
							+ employee);
					calls.remove(call);
					// employee.setFree(isFree.nextBoolean());
				} else {
					if (call.getCallStatus() == CallStatus.CREATED
							&& EmployeeType.RESPONDENT == employeeType) {
						dispatchCaLL(call, EmployeeType.MANAGER, calls);
					} else if (call.getCallStatus() == CallStatus.CREATED
							&& EmployeeType.MANAGER == employeeType) {
						dispatchCaLL(call, EmployeeType.DIRECTOR, calls);
					}
				}
			}
		}

	}
-------------------------------------END------------------------

--------------------CASE 4-------------------------------------
public void handleCalls(List<Call> calls) {
		if (!calls.isEmpty()) {

			Call call = calls.remove(0);
			if (call.getCallStatus().equals(CallStatus.CREATED)) {
				dispatchCaLL(call, EmployeeType.RESPONDENT, calls);
			}
		}
	}

	@Override
	public void dispatchCaLL(Call call, EmployeeType employeeType,
			List<Call> calls) {
		List<Employee> employees = Company.listOfAllEmployees.get(employeeType
				.ordinal());
		while (!calls.isEmpty()) {
			for (Employee employee : employees) {
				if (employee.isFree()) {
					call.setCallStatus(CallStatus.RESPONDED);
					System.out.println("Call from "
							+ call.getCaller().getCallerId() + " responded by "
							+ employee);
					call = calls.remove(0);
					// employee.setFree(isFree.nextBoolean());
				} else {
					if (call.getCallStatus() == CallStatus.CREATED
							&& EmployeeType.RESPONDENT == employeeType) {
						dispatchCaLL(call, EmployeeType.MANAGER, calls);
					} else if (call.getCallStatus() == CallStatus.CREATED
							&& EmployeeType.MANAGER == employeeType) {
						dispatchCaLL(call, EmployeeType.DIRECTOR, calls);
					}
				}
			}
		}

	}
----------------------END---------------------------------------------

```
