#include "StdAfx.h" #include "Queue.h" #include "IncomingCall.h" #include "AcdCore.h" #include "StrategyLoop.h" #include "StrategyMaxFree.h" #include "StrategyMinAnswer.h" #include "StrategySpecifiedAgent.h" CQueue::CQueue(UINT QueueNo) : m_QueueNo(QueueNo) { __initStrategy(); } CQueue::~CQueue( void ) { __freeStrategy(); } /***************************************************************** **【函数名称】 __initStrategy **【函数功能】 初始化座席分配策略 **【参数】 **【返回值】 ****************************************************************/ void CQueue::__initStrategy( void ) { CStrategyAD* pStrategy = NULL; // 循环接听 pStrategy = new CStrategyLoop(); m_StrategyMap.SetAt(AGENT_STRATEGY_LOOP, pStrategy); // 目前空闲时间最长的座席 pStrategy = new CStrategyMaxFree(); m_StrategyMap.SetAt(AGENT_STRATEGY_MAX_CUR_FREE_TIME, pStrategy); // 目前接听次数最少的坐席 pStrategy = new CStrategyMinAnswer(); m_StrategyMap.SetAt(AGENT_STRATEGY_MINI_CALLS, pStrategy); // 指定座席 pStrategy = new CStrategySpecifiedAgent(); m_StrategyMap.SetAt(AGENT_STRATEGY_KNOWN, pStrategy); } /***************************************************************** **【函数名称】 __freeStrategy **【函数功能】 释放座席分配策略 **【参数】 **【返回值】 ****************************************************************/ void CQueue::__freeStrategy( void ) { AGENT_STRATEGY Key; CStrategyAD* pStrategy = NULL; POSITION Pos = m_StrategyMap.GetStartPosition(); while(Pos != NULL) { m_StrategyMap.GetNextAssoc(Pos, Key, pStrategy); ASSERT(pStrategy != NULL); delete pStrategy; } m_StrategyMap.RemoveAll(); } /***************************************************************** **【函数名称】 __getStrategy **【函数功能】 获取指定的座席分配策略 **【参数】 **【返回值】 ****************************************************************/ CStrategyAD* CQueue::__getStrategy( AGENT_STRATEGY StrategyId ) { // 找到对应的座席分配策略 CStrategyAD* pStrategy = NULL; if(!m_StrategyMap.Lookup(StrategyId, pStrategy)) pStrategy = m_StrategyMap[AGENT_STRATEGY_LOOP]; // 如果指定的策略不存在,则选取循环接听策略 return pStrategy; } /***************************************************************** **【函数名称】 __onAgentDispatched **【函数功能】 处理请求座席结果 **【参数】 Result: 请求座席结果 Agent: 请求到的座席ID Exten: 请求到的座席分机号 CallIndex: 请求座席的来电索引 **【返回值】 ****************************************************************/ void CQueue::__onAgentDispatched( QUEUE_AGENT_RESULT Result, UINT Agent, UINT Exten, CIncomingCall* pCall ) { switch(Result) { case QUEUE_AGENT_OK: // 请求座席成功 { pCall->onQueueOK(Agent, Exten); m_CallGroup.delCall(pCall->index()); } break; case QUEUE_AGENT_FAILED_NO_AGENT: // 无签入座席 case QUEUE_AGENT_FAILED_NO_FREE: // 座席全忙 case QUEUE_AGETN_FAILED_NO_SPEC: // 在指定策略下无匹配座席 { pCall->onQueueFailed(Result, Agent); } break; } // end switch } /***************************************************************** **【函数名称】 clear **【函数功能】 清除所有资源 **【参数】 **【返回值】 ****************************************************************/ void CQueue::clear( void ) { m_CallGroup.clear(); m_AgentGroup.clear(); } /***************************************************************** **【函数名称】 onQueueRequest **【函数功能】 呼叫请求排队响应 **【参数】 pCmd: PDU命令内容 **【返回值】 被操作呼叫 ****************************************************************/ void CQueue::onQueueRequest( CPduEntity* pCmd ) { int CallPos = 0; // 是否为重复请求座席 CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(1)); if(pCall != NULL) { pCall->updateQueueInfo(pCmd); // 重置座席分配策略及信息 } else { pCall = m_CallGroup.addCall(pCmd, CallPos); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueue}: 呼叫请求排队, m_QueueNo=%d,Index = %d,Caller=%s", m_QueueNo, CallPos, pCmd->GetDataString(6)); } // end if // 当前来电是否可以请求座席(如果不能,直接返回请求座席失败) if(pCall != m_CallGroup.getTopWaitedCall()) { QUEUE_AGENT_RESULT Result = QUEUE_AGENT_FAILED_NO_FREE; if(m_AgentGroup.GetCount() == 0) Result = QUEUE_AGENT_FAILED_NO_AGENT; __onAgentDispatched(Result, CallPos, 0, pCall); } // end if else { // 处理排队请求 distributeAgent(); } } /***************************************************************** **【函数名称】 onQueueCancel **【函数功能】 呼叫取消排队 **【参数】 pCmd: PDU命令内容 **【返回值】 ****************************************************************/ bool CQueue::onQueueCancel( CPduEntity* pCmd ) { // 删除呼叫 ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueue}: 呼叫取消排队, m_QueueNo=%d,Index = %d,Caller=%s", m_QueueNo, pCmd->GetDataInt(1), pCmd->GetDataString(6)); return m_CallGroup.delCall(pCmd->GetDataInt(1)); } /***************************************************************** **【函数名称】 onQueuePause **【函数功能】 呼叫暂停排队 **【参数】 pCmd: PDU命令内容 **【返回值】 ****************************************************************/ bool CQueue::onQueuePause( CPduEntity* pCmd ) { CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(0)); if(pCall == NULL) return false; pCall->setCallState(OUTER_CALL_PAUSE); return true; } /***************************************************************** **【函数名称】 onQueueContinue **【函数功能】 呼叫继续排队 **【参数】 pCmd: PDU命令内容 **【返回值】 ****************************************************************/ bool CQueue::onQueueContinue( CPduEntity* pCmd ) { CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(1)); if(pCall == NULL) return false; pCall->updateQueueInfo(pCmd); // 主动请求坐席 distributeAgent(); return true; } /***************************************************************** **【函数名称】 addAgent **【函数功能】 添加座席 **【参数】 **【返回值】 ****************************************************************/ void CQueue::addAgent( CAgent* pAgent ) { m_AgentGroup.add(pAgent); } /***************************************************************** **【函数名称】 delAgent **【函数功能】 删除座席 **【参数】 **【返回值】 ****************************************************************/ void CQueue::delAgent( CAgent* pAgent ) { m_AgentGroup.remove(pAgent); } /***************************************************************** **【函数名称】 distributeAgent **【函数功能】 **【参数】 **【返回值】 ****************************************************************/ void CQueue::distributeAgent( void ) { // 查找当前要排队的呼叫 CIncomingCall* pCall = m_CallGroup.getTopWaitedCall(); if(pCall == NULL) return; pCall->setCallState(OUTER_CALL_QUEUE); CStrategyAD* pStrategy = __getStrategy(pCall->agentStrategy()); // 请求座席的排队策略 ASSERT(pStrategy != NULL); // 显示日志 ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{坐席排队策略号: %lu"), pCall->agentStrategy()); // 开始请求座席 UINT Agent = 0; // 要返回的座席工号 UINT Exten = 0; // 要返回的座席分机号 QUEUE_AGENT_RESULT Result = m_AgentGroup.distributeAgent(pStrategy, pCall->infoEx(), Agent, Exten); // 处理请求结果 __onAgentDispatched(Result, Agent, Exten, pCall); }