多数据源中间件标准版1.0

Queue.cpp 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "StdAfx.h"
  2. #include "Queue.h"
  3. #include "IncomingCall.h"
  4. #include "AcdCore.h"
  5. #include "StrategyLoop.h"
  6. #include "StrategyMaxFree.h"
  7. #include "StrategyMinAnswer.h"
  8. #include "StrategySpecifiedAgent.h"
  9. #include "StrategyLoopByAgentId.h"
  10. CQueue::CQueue(UINT QueueNo) : m_QueueNo(QueueNo)
  11. {
  12. __initStrategy();
  13. }
  14. CQueue::~CQueue( void )
  15. {
  16. __freeStrategy();
  17. }
  18. /*****************************************************************
  19. **【函数名称】 __initStrategy
  20. **【函数功能】 初始化座席分配策略
  21. **【参数】
  22. **【返回值】
  23. ****************************************************************/
  24. void CQueue::__initStrategy( void )
  25. {
  26. CStrategyAD* pStrategy = NULL;
  27. // 循环接听
  28. pStrategy = new CStrategyLoop();
  29. m_StrategyMap.SetAt(AGENT_STRATEGY_LOOP, pStrategy);
  30. // 2020-01-13 循环接听,按照座席id大小顺序
  31. pStrategy = new CStrategyLoopByAgentId();
  32. m_StrategyMap.SetAt(AGENT_STRATEGY_LOOPBYAGENTID, pStrategy);
  33. // 目前空闲时间最长的座席
  34. pStrategy = new CStrategyMaxFree();
  35. m_StrategyMap.SetAt(AGENT_STRATEGY_MAX_CUR_FREE_TIME, pStrategy);
  36. // 目前接听次数最少的坐席
  37. pStrategy = new CStrategyMinAnswer();
  38. m_StrategyMap.SetAt(AGENT_STRATEGY_MINI_CALLS, pStrategy);
  39. // 指定座席
  40. pStrategy = new CStrategySpecifiedAgent();
  41. m_StrategyMap.SetAt(AGENT_STRATEGY_KNOWN, pStrategy);
  42. }
  43. /*****************************************************************
  44. **【函数名称】 __freeStrategy
  45. **【函数功能】 释放座席分配策略
  46. **【参数】
  47. **【返回值】
  48. ****************************************************************/
  49. void CQueue::__freeStrategy( void )
  50. {
  51. AGENT_STRATEGY Key;
  52. CStrategyAD* pStrategy = NULL;
  53. POSITION Pos = m_StrategyMap.GetStartPosition();
  54. while(Pos != NULL)
  55. {
  56. m_StrategyMap.GetNextAssoc(Pos, Key, pStrategy);
  57. ASSERT(pStrategy != NULL);
  58. delete pStrategy;
  59. }
  60. m_StrategyMap.RemoveAll();
  61. }
  62. /*****************************************************************
  63. **【函数名称】 __getStrategy
  64. **【函数功能】 获取指定的座席分配策略
  65. **【参数】
  66. **【返回值】
  67. ****************************************************************/
  68. CStrategyAD* CQueue::__getStrategy( AGENT_STRATEGY StrategyId )
  69. {
  70. // 找到对应的座席分配策略
  71. CStrategyAD* pStrategy = NULL;
  72. if(!m_StrategyMap.Lookup(StrategyId, pStrategy))
  73. pStrategy = m_StrategyMap[AGENT_STRATEGY_LOOP]; // 如果指定的策略不存在,则选取循环接听策略
  74. return pStrategy;
  75. }
  76. /*****************************************************************
  77. **【函数名称】 __onAgentDispatched
  78. **【函数功能】 处理请求座席结果
  79. **【参数】 Result: 请求座席结果
  80. Agent: 请求到的座席ID
  81. Exten: 请求到的座席分机号
  82. CallIndex: 请求座席的来电索引
  83. **【返回值】
  84. ****************************************************************/
  85. void CQueue::__onAgentDispatched( QUEUE_AGENT_RESULT Result, UINT Agent, UINT Exten, CIncomingCall* pCall )
  86. {
  87. switch(Result)
  88. {
  89. case QUEUE_AGENT_OK: // 请求座席成功
  90. {
  91. pCall->onQueueOK(Agent, Exten);
  92. m_CallGroup.delCall(pCall->index());
  93. }
  94. break;
  95. case QUEUE_AGENT_FAILED_NO_AGENT: // 无签入座席
  96. case QUEUE_AGENT_FAILED_NO_FREE: // 座席全忙
  97. case QUEUE_AGETN_FAILED_NO_SPEC: // 在指定策略下无匹配座席
  98. {
  99. pCall->onQueueFailed(Result, Agent);
  100. }
  101. break;
  102. } // end switch
  103. }
  104. /*****************************************************************
  105. **【函数名称】 clear
  106. **【函数功能】 清除所有资源
  107. **【参数】
  108. **【返回值】
  109. ****************************************************************/
  110. void CQueue::clear( void )
  111. {
  112. m_CallGroup.clear();
  113. m_AgentGroup.clear();
  114. }
  115. /*****************************************************************
  116. **【函数名称】 onQueueRequest
  117. **【函数功能】 呼叫请求排队响应
  118. **【参数】 pCmd: PDU命令内容
  119. **【返回值】 被操作呼叫
  120. ****************************************************************/
  121. void CQueue::onQueueRequest( CPduEntity* pCmd )
  122. {
  123. int CallPos = 0;
  124. // 是否为重复请求座席
  125. CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(1));
  126. if(pCall != NULL)
  127. {
  128. pCall->updateQueueInfo(pCmd); // 重置座席分配策略及信息
  129. }
  130. else
  131. {
  132. pCall = m_CallGroup.addCall(pCmd, CallPos);
  133. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "{CQueue}: 呼叫请求排队, m_QueueNo=%d,Index = %d,Caller=%s", m_QueueNo, CallPos, pCmd->GetDataString(6));
  134. } // end if
  135. // 当前来电是否可以请求座席(如果不能,直接返回请求座席失败)
  136. if(pCall != m_CallGroup.getTopWaitedCall())
  137. {
  138. QUEUE_AGENT_RESULT Result = QUEUE_AGENT_FAILED_NO_FREE;
  139. if(m_AgentGroup.GetCount() == 0)
  140. Result = QUEUE_AGENT_FAILED_NO_AGENT;
  141. __onAgentDispatched(Result, CallPos, 0, pCall);
  142. } // end if
  143. else
  144. {
  145. // 处理排队请求
  146. distributeAgent();
  147. }
  148. }
  149. /*****************************************************************
  150. **【函数名称】 onQueueCancel
  151. **【函数功能】 呼叫取消排队
  152. **【参数】 pCmd: PDU命令内容
  153. **【返回值】
  154. ****************************************************************/
  155. bool CQueue::onQueueCancel( CPduEntity* pCmd )
  156. {
  157. // 删除呼叫
  158. 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));
  159. return m_CallGroup.delCall(pCmd->GetDataInt(1));
  160. }
  161. /*****************************************************************
  162. **【函数名称】 onQueuePause
  163. **【函数功能】 呼叫暂停排队
  164. **【参数】 pCmd: PDU命令内容
  165. **【返回值】
  166. ****************************************************************/
  167. bool CQueue::onQueuePause( CPduEntity* pCmd )
  168. {
  169. CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(0));
  170. if(pCall == NULL)
  171. return false;
  172. pCall->setCallState(OUTER_CALL_PAUSE);
  173. return true;
  174. }
  175. /*****************************************************************
  176. **【函数名称】 onQueueContinue
  177. **【函数功能】 呼叫继续排队
  178. **【参数】 pCmd: PDU命令内容
  179. **【返回值】
  180. ****************************************************************/
  181. bool CQueue::onQueueContinue( CPduEntity* pCmd )
  182. {
  183. CIncomingCall* pCall = m_CallGroup.getCall(pCmd->GetDataInt(1));
  184. if(pCall == NULL)
  185. return false;
  186. pCall->updateQueueInfo(pCmd);
  187. // 主动请求坐席
  188. distributeAgent();
  189. return true;
  190. }
  191. /*****************************************************************
  192. **【函数名称】 addAgent
  193. **【函数功能】 添加座席
  194. **【参数】
  195. **【返回值】
  196. ****************************************************************/
  197. void CQueue::addAgent( CAgent* pAgent )
  198. {
  199. m_AgentGroup.add(pAgent);
  200. }
  201. /*****************************************************************
  202. **【函数名称】 delAgent
  203. **【函数功能】 删除座席
  204. **【参数】
  205. **【返回值】
  206. ****************************************************************/
  207. void CQueue::delAgent( CAgent* pAgent )
  208. {
  209. m_AgentGroup.remove(pAgent);
  210. }
  211. /*****************************************************************
  212. **【函数名称】 distributeAgent
  213. **【函数功能】
  214. **【参数】
  215. **【返回值】
  216. ****************************************************************/
  217. void CQueue::distributeAgent( void )
  218. {
  219. // 查找当前要排队的呼叫
  220. CIncomingCall* pCall = m_CallGroup.getTopWaitedCall();
  221. if(pCall == NULL)
  222. return;
  223. pCall->setCallState(OUTER_CALL_QUEUE);
  224. CStrategyAD* pStrategy = __getStrategy(pCall->agentStrategy()); // 请求座席的排队策略
  225. ASSERT(pStrategy != NULL);
  226. // 显示日志
  227. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{坐席排队策略号: %lu"), pCall->agentStrategy());
  228. // 开始请求座席
  229. UINT Agent = 0; // 要返回的座席工号
  230. UINT Exten = 0; // 要返回的座席分机号
  231. QUEUE_AGENT_RESULT Result = m_AgentGroup.distributeAgent(pStrategy, pCall->infoEx(), Agent, Exten);
  232. // 处理请求结果
  233. __onAgentDispatched(Result, Agent, Exten, pCall);
  234. }