프로그램 개발/Python

[코딩 인터뷰]개념과 알고리즘 - 객체 지향 설계 문제(콜 센터:Python)

(ㅇㅅㅎ) 2022. 12. 23. 14:38
728x90
반응형

 

콜 센터

 고객 응대 담당자, 관리자, 감독관 이렇게 세 부류의 직원들로 구성된 콜 센터가 있을 때, 콜 센터로 오는 전화는 먼저 상담이 가능한 고객 응대 담당자로 연결되어야 합니다. 고객 응대 담당자가 처리할 수 없는 전화는 관리자로 연결되고, 관리자가 처리할 수 없는 전화는 다시 감독관에게 연결됩니다. 이 문제를 풀기 위한 자료구조를 설계하라.

 

[ Rank ]

from enum import Enum
class Rank(Enum):
    DIRECTOR = 0
    MANAGER = 1
    RESPONDENT = 2

    def __next__(self):
        if self.value != 0:
            return Rank(self.value - 1)
        else:
            return ValueError("You are Director.")

👀 직원들이 3 부류로 나뉘기 때문에 enum으로 Rank라는 class를 제작하였습니다.

 

 

[ Call ]

class Call:
    def __init__(self, c):
        self.__caller = c
        self.__rank = Rank.RESPONDENT
        self.__handler = None

    def setHandler(self, e):
        self.__handler = e

    def reply(self, message):
        return message

    def getRank(self):
        return self.__rank

    def setRank(self, r):
        self.__rank = r

    def incrementRank(self):
        self.__rank = next(self.__rank)

    def disconnect(self):
        self.__handler = None

👀 Call이라는 class를 제작하여 전화에 대한 class를 제작했습니다.

 

 

[ Employee ]

from abc import *
class Employee(metaclass=ABCMeta):
    __currentCall = None
    __rank = Rank.RESPONDENT

    # 상담 시작
    def receiveCall(self, c):
        self.__currentCall = c
        c.setHandler(self)

    # 상담 종료
    def callCompleted(self):
        self.__currentCall = None

    # 문제 해결 x : 상위 직급으로 전화 돌리고 현재 직원에게 다른 전화 배정
    def escalateAndReassign(self, ch):
        self.__currentCall.incrementRank()
        ch.callQueues[self.__currentCall.getRank].append(self.__currentCall)
        self.callCompleted()

    # 직원이 상담 중인지 아닌지를 반환
    def isFree(self):
        return self.__currentCall is None

    def getRank(self):
        return self.__rank

👀 직원에 대한 class를 추상 class로 구현한 뒤 Director, Manager, Respondent에서 상속받아서 사용합니다.

Director, Manager, Respondent ▼

더보기
class Director(Employee):
    def __init__(self):
        self.__rank = Rank.DIRECTOR

class Manager(Employee):
    def __init__(self):
        self.__rank = Rank.MANAGER

class Respondent(Employee):
    pass

 

 

[ CallHandler ]

class CallHandler:
    def __init__(self):
        # 10명의 담당자와 4명의 관리자, 2명의 감독관으로 초기화
        NUM_RESPONDENTS = 10
        NUM_MANAGERS = 4
        NUM_DIRECTORS = 2

        self.Employees = {
            Rank.DIRECTOR: [Director() for _ in range(NUM_DIRECTORS)],
            Rank.MANAGER: [Manager() for _ in range(NUM_MANAGERS)],
            Rank.RESPONDENT: [Respondent() for _ in range(NUM_RESPONDENTS)]
        }

        # 직급별 수신 전화 대기 큐
        self.callQueues = {Rank.DIRECTOR: [], Rank.MANAGER: [], Rank.RESPONDENT: []}

    # 전화 응대 가능한 첫 번쨰 직원 가져오기
    def getHandlerForCall(self, r):
        for e in self.Employees[r]:
            if e.isFree():
                return e
        return None

    # 응대 가능한 직원에게 전화를 연결, 응대 가능한 직원이 없으면 큐에 보관
    def dispatchCall(self, c: Call):
        rank = c.getRank()
        e = self.getHandlerForCall(rank)
        if e is not None:
            e.receiveCall(c)
        else:
            self.callQueues[rank].append(c)

    # 가용 직원을 발견한다. 해당 직원이 처리해야 할 전화를 탐색 후 새로운 전화를 배정됐다면 true를, 그렇지 않으면 false를 반환
    def assignCall(self):
        for k, employee in self.Employees.items():
            for e in employee:
                if len(self.callQueues[k]) == 0: break
                if self.getHandlerForCall(k) is not None:
                    c = self.callQueues[k].pop(0)
                    e.receiveCall(c)
                    return True
        return False

 

반응형