走读arbd-ivr-report第二遍

走读arbd-ivr-report.md,这是我第一次阅读arbd-ivr-report时的笔记,里面有很多看不太懂的东西,现在我基本上已经弄懂这个程序了,所以我要重新再写一篇,来证明自己已经看懂它了。

入口

arbd-ivr-report的入口位于ReportTaskContext:startTask(),这个函数是被arbd项目里面的all-report作为定时任务跑起来的。在src/main/resources/application.properties里面可以看到report.cronExpression=0 0 12 * * ?这个定时任务表达式。然后在src/main/resources/conf/app-reportcreate.xml里面可以看到一个类名为org.springframework.scheduling.quartz.CronTriggerBean的bean,它的jobDetail就是一个目标为reportTaskContext:startTask()的bean,它的cronExpression就是刚才在application.properties里面的report.cronExpression=0 0 12 * * ?,也就是说在每天中午12点的时候,会运行reportTaskContext:startTask(),也就是arbd-ivr-report里面的ReportTaskContext:startTask()

另外提一句,数据库配置位于all-report项目的src/main/resources/application-db.properties,配置情况如下所示:

hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=jdbc:oracle:thin:@192.168.6.241:1521:ora11g
hibernate.connection.username=xbj12366
hibernate.connection.password=xbj12366
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.default_schema=xbj12366
hibernate.show_sql=false
hibernate.format_sql=false

初始化

在定时任务运行之前,其实还有一步是初始化ReportTaskContext。初始化一共分为两个步骤,第一步是构造bean,也就是调用构造函数;第二步是容器加载完毕事件,也就是里面的onApplicationEvent(ContextRefreshedEvent)函数。这两步各有各的用途。

构造函数

将七个复杂规则类按照编号->类名的方式放入到一个名叫ruleClassMap的Map中。

onApplicationEvent

第一步,将各种按键放入到一个叫caseCodeList的数组中。

第二步,获取IVR_REPORT_NODES表中所有有效的节点,并处理节点中的ASR_IDS字段

之后将所有的IVRReportNode按照code->node的方式放入到nodeMap中,根据node的count_mode字段(0复杂、1简单、2忽略),将节点对应的规则放入到rules中,最后再往rules里面添加内置回溯规则。

两个线程池

进入startTask之后,就会看到start()startCaseDataTask()两个启动函数,每个启动函数先会清除开始时间到结束时间在内的所有记录,然后分别运行各自的线程池。第一个线程池运行所有的ReportTask线程,第二个线程池运行所有的ReportCaseCountTask线程。这些task是从哪里来的呢?其实它是从TX_ASR_CALL_LOGO获取的,取出INASRDT位于开始结束时间内且EXITASR不为firsterror的CALL_LOGO。

然后开始结束时间又是什么呢?首先我们要知道,统计的任务最后都是存储在IVR_REPORT_LOG表中的,上次任务的结束时间就是这次任务的开始时间,这次任务的结束时间就是今天凌晨0点0分0秒。

当所有任务结束之后又会将结果写回到IVR_REPORT_LOG表中。

ReportTask

取出所有的规则,依次判断CALL_LOGO是否属于这个规则。正如之前所说的,一共有三类规则,即复杂规则、简单规则和回溯规则。下面我依次说说这三类规则如何判断CALL_LOGO的吧!

复杂规则

IVR200000Rule

IVR200000Rule为例,它会获取CALL_LOGO的callid,然后去TX_ASRTOKEY表中查询是否有这个callid

如果有这个callid的话,就去TX_ASR_FLOW_RECORD表中根据callid统计交互量,统计出来的值叫做service_count,后面会用到

之后再统计命中量。首先从TX_QUERYSTATE表中查询命中量,为什么查询的时候要按JDBH分组,并且CZLX要为2或3呢?为什么TX_QUERYSTATE表居然连注释都没有?

然后再通过TX_ASR_FLOW_RECORD统计2.2节点的咨询命中量,只挑选(1)asr_id为2.2开头,(2)confidence(置信度)>80或者sfzxwt为1,(3)callid为所需要的id。只有满足这三个条件的才算咨询命中量。看完我有以下几个疑问:(1)confidence在oracle数据库中为VARCHAR2类型,为啥可以在SQL语句中用>比较呢?(2)sfzxwt是什么鬼玩意儿?

之后咨询命中量被放到统计命中量数组中,并写入到IVR_REPORT_PERFECTCOUNT表中

此外根据ReportNode的node_level,设置对应的节点和子节点Code,最后写入IVR_REPORT_HANGUP表中,此外之前统计出来的service_count也会被写入进去

其它

因为时间有限,暂时不看

简单规则

将ReportNode中的ASR_IDS与asrCallLog中的existAsr进行对比。如果existAsr在ASR_IDS里面的话,再判断ReportNode中的nodeCode是否以1开头,还要记录TX_ASR_FLOW_RECORD表中(1)指定call_id(2)prompt_wav不带有2a或者asr_id不为asrerror,满足这两个条件的记录数。如果1开头,记录数为0,则满足条件;如果不是1开头,则记录service_count为记录数,也满足条件。

保存部分与复杂规则类似,也是写入IVR_REPORT_PERFECTCOUNTIVR_REPORT_HANGUP这两张表。

回溯规则

如果CallLogo里面的exitAsrId格式类似SW_ASR*.txt的话,那么就认为它是一个NodeCode为200504且ParentNode为200500的节点,然后统计并设置交互次数,满足条件退出。

如果是重听或短信发送,从TX_ASR_FLOW_RECORD表中根据call_id获取对应的asr_id列表,这里我获取到一个非常重要的信息,那就是asr_id如果为2.1的话,那就是查询节点;如果为2.2的话,那就是咨询节点。

不管是2.1还是2.2,都要设置NodeCode,ParentNode,NodeLevel,ServiceCount,然后满足条件退出。

第二轮查询

当第一轮复杂/简单/回溯规则都没有找到CALL_LOG对应的编码时,CALL_LOG就会用代理的退出编码,即ASRWHJDBH或FLOW_RESULT(当ASRWHJDBH为空时)作为自己的existasr,然后进行第二轮复杂/简单/回溯规则查询。过程和之前的复杂/简单/回溯规则查询类似。

如果还是没有找到,那就不找了,和之前的复杂/简单/回溯规则类似,统计命中量会存储到IVR_REPORT_PERFECTCOUNT表中,ServiceCount和NodeCode会被写入到IVR_REPORT_HANGUP表中

至此一个ReportTask就结束了

ReportCaseCountTask

通过CallLog构造出一个IVRReportCaseCount。然后拿所有的CaseCode一个个去执行call_id。我感觉这个执行函数写得有问题!为啥call_id进入执行函数之后就变成reportDate了?这是个很严重的问题,基本上可以算作错误了,等下我要好好问问!所以这个执行函数里面的内容我暂时不看了,感觉都是垃圾!

经过上面那个执行函数,可以获取到一个count变量,因为我质疑上面的执行函数,所以我目前还不知道count变量代表什么东西,然后通过反射的方法来为caseCount对象各个字段赋值,最后存储到IVR_REPORT_CASEDATA表中

数据库总结

TX_ASRTOKEY

TX_ASR_FLOW_RECORD

TX_QUERYSTATE

IVR_REPORT_LOG

IVR_REPORT_NODES

IVR_REPORT_PERFECTCOUNT

IVR_REPORT_HANGUP

IVR_REPORT_CASEDATA

总结问题

问题1

问:IVRReportHangupService第51行,czlx是什么?

问题2

问:IVRReportHangupService第54行,confidence在tx_asr_flow_record表中是VARCHAR2类型,为啥可以和数字80进行比较?

答:VARCHAR2字段如果全部是数字,那么就可以和数字进行比较了

问题3

问:IVRReportHangupService第54行,sfzxwt是什么?

问题4

问:IVRReportCaseCountService第104行和第109行,reportDate本质是asr_id,为啥它能够和2018-09-07这样的字符串进行比较?ReportTaskContext第41行进入的。

答:确实是bug,应该拿TxAsrCallLog.inasrdt进行比较

我干过的事情

通过tx_asr_flow_record的asr_id,indate,call_id,callerno,asr_content,ivr_record,xh,jkzt这几个字段,新建了IVR_REPORT_FLOW_RECORD这张表,里面有这些字段。

我还需要干的事情

相关资料

上海智能语音项目IVR需求

上海国税智能导航IVR流程设计图

猜你喜欢

转载自www.cnblogs.com/hellozjf/p/9664198.html
今日推荐