liusheng
10 天以前 f0a09ee996ab2605869844d6a3d812709e2bf0fa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
package com.ruoyi.phone.service.impl;
 
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.service.SubtaskOptionMatchApi;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.*;
import com.ruoyi.phone.domain.PhoneCallBackSHVO;
import com.ruoyi.phone.domain.PhoneCallBackVO;
import com.ruoyi.phone.domain.PhoneCallBackYQVO;
import com.ruoyi.phone.domain.PhoneCallRecordVO;
import com.ruoyi.phone.domain.PhoneCallReqYQVO;
import com.ruoyi.phone.domain.PhoneCallResultYQVO;
import com.ruoyi.phone.domain.PullTaskVO;
import com.ruoyi.phone.domain.QuestionMessage;
import com.ruoyi.phone.service.IPhoneService;
import com.ruoyi.task.api.TaskSubtaskApi;
import com.ruoyi.task.api.spi.TaskFtpPort;
import com.ruoyi.task.api.spi.TaskPreachformPort;
import com.ruoyi.task.api.spi.TaskSysConfigPort;
import com.ruoyi.task.domain.IvrTaskVisitResult;
import com.ruoyi.task.domain.ServiceSubTaskDetailReq;
import com.ruoyi.task.domain.ServiceSubtask;
import com.ruoyi.task.domain.ServiceSubtaskDetail;
import com.ruoyi.task.domain.ServiceSubtaskDetailTrace;
import com.ruoyi.task.domain.ServiceSubtaskPreachform;
import com.ruoyi.task.domain.ServiceTask;
import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
import com.ruoyi.template.domain.IvrLibaExtemplatescript;
import com.ruoyi.template.domain.IvrTaskTemplate;
import com.ruoyi.template.domain.IvrTaskTemplateScript;
import com.ruoyi.template.domain.IvrTaskTemplateScriptVO;
import com.ruoyi.template.domain.IvrTaskTemplateTargetoption;
import com.ruoyi.template.domain.IvrTaskTemplateVO;
import com.ruoyi.template.domain.SvyLibScriptCategory;
import com.ruoyi.template.service.IIvrLibaExtemplatescriptService;
import com.ruoyi.template.service.IIvrTaskTemplateScriptService;
import com.ruoyi.template.service.IIvrTaskTemplateService;
import com.ruoyi.template.service.IIvrTaskTemplateTargetoptionService;
import com.ruoyi.template.service.ISvyLibScriptCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
 
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
/**
 * 电话业务Service实现(原 {@code ruoyi-task} 里 {@code ServiceSubtaskServiceImpl} 的电话部分)。
 *
 * <h3>这个类是怎么来的</h3>
 * 逐行从 {@code ServiceSubtaskServiceImpl} 搬出,只做两类机械改写,<b>业务分支一行未动</b>:
 * <ol>
 *   <li><b>数据访问换入口</b>:原 {@code serviceSubtaskMapper} / {@code serviceSubtaskDetailMapper} /
 *       {@code serviceTaskVisitResultMapper} / {@code serviceTaskService} / {@code traceService}
 *       的调用,统一改为 {@link TaskSubtaskApi}(表归 {@code ruoyi-task},非归属模块不许写这些表);</li>
 *   <li><b>跨模块读取换入口</b>:模板话术改走 {@code ruoyi-template} 的 service 接口
 *       ({@code IIvrTaskTemplateService} / {@code IIvrTaskTemplateScriptService} /
 *       {@code IIvrTaskTemplateTargetoptionService} / {@code IIvrLibaExtemplatescriptService} /
 *       {@code ISvyLibScriptCategoryService});AI 选项匹配改走 ruoyi-common 契约
 *       {@link SubtaskOptionMatchApi}(实现在 {@code ruoyi-task},原 {@code matchOptionIndex} 仍留在那边)。</li>
 * </ol>
 *
 * <h3>会话状态在哪里</h3>
 * 一通电话的进行状态(当前题号、已问遍数、静默次数、分数、是否已挂机、结束语等)
 * <b>全部放在 Redis</b>(key 前缀是本通电话的 uuid 或"子任务ID-手机号"),
 * 这些 key 的拼写、TTL、读写顺序与原实现完全一致 —— 电话回调是外部平台驱动的、
 * 进程重启后要继续,所以这些 key 就是"业务状态机",迁移时不能动。
 *
 * <h3>被刻意删掉的东西</h3>
 * 原 {@code ServiceSubtaskServiceImpl#getSmsCompensate(Long)}("电话的补偿方法(老)")没有搬:
 * 它的两个调用点({@code phoneCallBackYQ} 里"患者挂断"、{@code recordAccept} 里"无人接听")
 * 在模块化前就已被注释掉,属死代码;搬过来只会把 {@code service_out_path} /
 * 短信发送方 / {@code pub_key} 一串依赖拖进电话模块。如需恢复电话补偿,请按
 * {@code doc/电话模块化_调研与实施方案.md} 的说明走"归属模块 API"补齐。
 *
 * @author ruoyi
 * @date 2024-08-08
 */
@Slf4j
@Service
public class PhoneServiceImpl implements IPhoneService {
 
    /**
     * 任务数据访问 API:子任务 / 子任务明细 / 任务访问结果 / 异常跟踪。
     * <p>
     * 这些表归 {@code ruoyi-task},本模块不写它们的 SQL,只经这个 API 读写。
     */
    @Autowired
    private TaskSubtaskApi taskSubtaskApi;
 
    /**
     * 发送方式状态(service_subtask_preachform):记录"电话"这一通道的发送状态与备注。
     * 该表归 ruoyi-inhospvisit,由 smartor 侧适配实现本端口。
     */
    @Autowired
    private TaskPreachformPort taskPreachformPort;
 
    /**
     * 录音文件下载(雨绮通话记录回调里把当天录音从 FTP 拉回本地)
     */
    @Autowired
    private TaskFtpPort taskFtpPort;
 
    /**
     * 参数配置读取({@code sys.voice.match.ai.url}:AI 选项匹配服务地址,按机构配置)
     */
    @Autowired
    private TaskSysConfigPort taskSysConfigPort;
 
    /**
     * AI 选项匹配契约(ruoyi-common,实现在 ruoyi-task,即原 {@code matchOptionIndex})
     */
    @Autowired
    private SubtaskOptionMatchApi subtaskOptionMatchApi;
 
    @Autowired
    private RedisCache redisCache;
 
    @Autowired
    private RedisTemplate redisTemplate;
 
    @Autowired
    private IIvrTaskTemplateService ivrTaskTemplateService;
 
    @Autowired
    private IIvrTaskTemplateScriptService iIvrTaskTemplateScriptService;
 
    @Autowired
    private IIvrTaskTemplateTargetoptionService ivrTaskTemplateTargetoptionService;
 
    @Autowired
    private IIvrLibaExtemplatescriptService ivrLibaExtemplatescriptService;
 
    @Autowired
    private ISvyLibScriptCategoryService svyLibScriptCategoryService;
 
    /**
     * 雨绮任务拉取时回填的 ASR 回调地址
     */
    @Value("${ASRCallBackPath}")
    private String ASRCallBackPath;
 
    /**
     * 雨绮外呼账号
     */
    @Value("${app_key_yq}")
    private String app_key_yq;
 
    /**
     * 上海通道短信补偿串解密用({@code saveQuestionAnswerPhone} 的 param1/param2)
     */
    @Value("${pri_key}")
    private String pri_key;
 
    /**
     * 雨绮挂机接口地址
     */
    @Value("${hangup}")
    private String hangup;
 
    /**
     * 录音本地根目录({@code ruoyi.profile})
     */
    @Value("${ruoyi.profile}")
    private String profile;
 
    /**
     * 语音文件对外访问前缀(存库前把 FTP 绝对路径改写成前端可访问路径)
     */
    @Value("${voicePathPrefix}")
    private String voicePathPrefix;
 
    /**
     * 每小时可外呼量
     */
    @Value("${phoneUpEveryHour}")
    private Integer phoneUpEveryHour;
 
    /**
     * 停止外呼的时刻(小时,默认 20 点)
     */
    @Value("${phoneEndHour}")
    private Integer phoneEndHour;
 
    @Override
    public void phoneCallBack(PhoneCallBackVO phoneCallBackVO) {
        phoneCallBackVO.setTextResult(phoneCallBackVO.getTextResult().substring(0, phoneCallBackVO.getTextResult().length() - 1));
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
 
        //获取数据
        Boolean aBoolean = redisCache.hasKey(phoneCallBackVO.getUuid());
        if (!aBoolean) {
            throw new BaseException("该uuid不存在");
        }
        Integer hangupValue = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "hangup");
        PhoneUtils phoneUtils = new PhoneUtils();
        if (hangupValue != null && hangupValue == 1) {
            String date = simpleDateFormat1.format(new Date());
            log.info("电话要挂断了: {}", date);
            //hangupValue == 1  随访结束,直接可以挂电话
            phoneUtils.hangup("", "", "", "", "", "", "", phoneCallBackVO.getUuid());
            return;
        }
 
        Map<String, Object> map = redisCache.getCacheObject(phoneCallBackVO.getUuid());
        ServiceSubtask serviceSubtask = (ServiceSubtask) map.get("ServiceSubtask");
        List<IvrTaskTemplateScriptVO> IvrTaskTemplateScriptVOs = (List<IvrTaskTemplateScriptVO>) map.get("IvrTaskTemplateScriptVO");
        //将uuid更新到数据库中
        serviceSubtask.setSenduuid(phoneCallBackVO.getUuid());
        taskSubtaskApi.updateSubtask(serviceSubtask);
 
        //获取模板信息
        IvrTaskTemplateVO ivrTaskTemplateVO = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "IvrTaskTemplateVO");
 
        //语音识别结果上报接口: 3
        Integer noVoice = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "noVoice");
        QuestionMessage returnQues = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
        //将传回的结果放到回复对象中
        returnQues.setContent(phoneCallBackVO.getTextResult());
 
        IvrTaskTemplateScriptVO nowQuestion = returnQues.getNowQuestion();
 
        if (StringUtils.isEmpty(returnQues.getContent())) {
            //无回话
            //判断noVoice是否已经到了最大值
            if (noVoice == ivrTaskTemplateVO.getNoVoiceNum().intValue()) {
                //已经问了对应的遍数,就判断是否还有下一题
                if (nowQuestion.getTargetid() == IvrTaskTemplateScriptVOs.size()) {
                    ServiceSubtask ss = new ServiceSubtask();
                    ss.setId(serviceSubtask.getId());
                    ss.setSendstate(5L);
                    ss.setRemark("电话无响应");
                    taskSubtaskApi.updateSubtask(ss);
                    //没有下一题了,就挂断电话,播放结束语
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                    phoneUtils.ttsPlayback(ivrTaskTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                    return;
                } else {
                    //有下一题
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                    IvrTaskTemplateScriptVO nextQuestion = getNextQuestion(IvrTaskTemplateScriptVOs, nowQuestion);
                    // 问题,  去调用"tts合成和播放"接口
                    String date = simpleDateFormat1.format(new Date());
                    log.info("去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                    phoneUtils.ttsPlayback(nowQuestion.getIvrtext(), phoneCallBackVO.getUuid());
                }
            } else {
                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", noVoice + 1, 120, TimeUnit.MINUTES);
                //调用ivrLibaTemplateScriptVO中的slienceText(静默话术)
                String slienceText = nowQuestion.getSlienceText();
                //静默话术  + 问题,  去调用"tts合成和播放"接口
                String date = simpleDateFormat1.format(new Date());
                log.info("静默话术  + 问题,去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                phoneUtils.ttsPlayback(slienceText + nowQuestion.getIvrtext(), phoneCallBackVO.getUuid());
                return;
            }
 
        } else {
            //isppd用来记录是否匹配到
            Boolean isppd = false;
            //有回话,对回答的问题,进行正则匹配(这里只针对选择题,其它题型不行)
            for (int j = 0; j < nowQuestion.getIvrTaskScriptTargetoptionList().size(); j++) {
                //包含
                Matcher matcher = null;
                if (StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex())) {
                    Pattern pattern = Pattern.compile(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex());
                    matcher = pattern.matcher(phoneCallBackVO.getTextResult());
                }
                //不包含
                Matcher matcher2 = null;
                if (StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2())) {
                    Pattern pattern2 = Pattern.compile(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2());
                    matcher2 = pattern2.matcher(phoneCallBackVO.getTextResult());
                }
                log.error("PCB--getQuestionText问题为:{},UUID:{}", nowQuestion.getIvrtext(), phoneCallBackVO.getUuid());
                if (StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() && StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches() || StringUtils.isEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() || StringUtils.isEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && StringUtils.isNotEmpty(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches()) {
                    //说明匹配正确了
                    //这里应该先判断类型,去再修改,设置IsUserOperation是单选题的改法
                    nowQuestion.getIvrTaskScriptTargetoptionList().get(j).setIsUserOperation(1);
                    ivrTaskTemplateTargetoptionService.updateIvrTaskTemplateTargetoption(nowQuestion.getIvrTaskScriptTargetoptionList().get(j));
 
                    //将静默置为0
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
 
                    //将患者的回签写进表里
                    IvrTaskVisitResult serviceTaskVisitResult = DtoConversionUtils.sourceToTarget(serviceSubtask, IvrTaskVisitResult.class);
                    serviceTaskVisitResult.setId(null);
                    serviceTaskVisitResult.setQuestion(nowQuestion.getIvrtext());
                    serviceTaskVisitResult.setPatientAnswer(phoneCallBackVO.getTextResult());
                    serviceTaskVisitResult.setCreateTime(new Date());
                    serviceTaskVisitResult.setOptionResult(nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getTargetvalue());
                    taskSubtaskApi.insertVisitResult(serviceTaskVisitResult);
 
                    //将匹配到的标识改成true
                    isppd = true;
 
                    //获取下一题
                    Long nextQuestion = nowQuestion.getIvrTaskScriptTargetoptionList().get(j).getNextQuestion();
                    for (IvrTaskTemplateScriptVO script : IvrTaskTemplateScriptVOs) {
                        if (script.getTargetid() == nextQuestion) {
                            QuestionMessage questionMessage = new QuestionMessage();
                            questionMessage.setNowQuestion(script);
                            questionMessage.setQuestionList(IvrTaskTemplateScriptVOs);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                            phoneUtils.ttsPlayback(script.getIvrtext(), phoneCallBackVO.getUuid());
                            return;
                        } else if (nextQuestion > IvrTaskTemplateScriptVOs.size()) {
                            //没有下一题了,就结束了
                            ServiceSubtask ss = new ServiceSubtask();
                            ss.setId(serviceSubtask.getId());
                            ss.setSendstate(6L);
                            taskSubtaskApi.updateSubtask(ss);
                            String date = simpleDateFormat1.format(new Date());
                            log.error("没有下一题了,就结束了: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                            phoneUtils.ttsPlayback(ivrTaskTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                            try {
                                Thread.sleep(3000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            phoneUtils.hangup("", "", ivrTaskTemplateVO.getRevisitAfter(), "", "", "", "", phoneCallBackVO.getUuid());
                            return;
                        }
                    }
                    return;
                } else {
                    //没有匹配上当前option
                    //Targetregex2 为false,表示在Targetregex2中存在  语句中的关键字,这个option就不用再继续匹配了,直接匹配下一个option
                    continue;
                }
            }
 
            if (isppd != true) {
                //没有匹配到
                Integer mateNum = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "mateNum");
                if (mateNum == null) mateNum = 0;
                //无匹配次数去判断是否到最大询问次数,并且所有的选项都匹配完了
                if (mateNum == ivrTaskTemplateVO.getMateNum().intValue()) {
                    //如果下一题为空.则新的数据返回,并加上感谢语
                    if (nowQuestion.getTargetid() < IvrTaskTemplateScriptVOs.size()) {
                        QuestionMessage questionMessage = new QuestionMessage();
                        IvrTaskTemplateScriptVO nextQuestion = getNextQuestion(IvrTaskTemplateScriptVOs, nowQuestion);
                        questionMessage.setQuestionList(IvrTaskTemplateScriptVOs);
                        questionMessage.setNowQuestion(nextQuestion);
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
                        String date = simpleDateFormat1.format(new Date());
                        log.info("如果下一题为空.则新的数据返回,并加上感谢语: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        phoneUtils.ttsPlayback(nextQuestion.getIvrtext(), phoneCallBackVO.getUuid());
                        return;
                    } else {
                        //就可以挂断电话了
                        ServiceSubtask ss = new ServiceSubtask();
                        ss.setId(serviceSubtask.getId());
                        ss.setSendstate(6L);
                        taskSubtaskApi.updateSubtask(ss);
 
                        String date = simpleDateFormat1.format(new Date());
                        log.info("就可以挂断电话了------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                        phoneUtils.ttsPlayback(ivrTaskTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        phoneUtils.hangup("", "", ivrTaskTemplateVO.getRevisitAfter(), "", "", "", "", phoneCallBackVO.getUuid());
                        return;
                    }
                } else if (mateNum < ivrTaskTemplateVO.getMateNum().intValue()) {
                    //没有问到规定次数
                    mateNum = mateNum + 1;
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", mateNum, 120, TimeUnit.MINUTES);
                }
            }
            //选项匹配完成后,需要再去通过库再进行匹配一次
            String extemplateID = ivrTaskTemplateVO.getSubmoduleID();
            String[] split = extemplateID.split(",");
            List<String> list = Arrays.asList(split);
            List<Long> list1 = new ArrayList<>();
            if (StringUtils.isNotEmpty(extemplateID)) {
                for (String str : list) {
                    list1.add(Long.valueOf(str));
                }
                List<IvrLibaExtemplatescript> ivrLibaExtemplatescripts = ivrLibaExtemplatescriptService.queryIvrLibaExtemplatescriptList(list1);
                for (IvrLibaExtemplatescript ivrLibaExtemplatescript : ivrLibaExtemplatescripts) {
                    Matcher matcher = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex())) {
                        Pattern pattern = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex());
                        matcher = pattern.matcher(returnQues.getContent());
                    }
 
                    Matcher matcher2 = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2())) {
                        Pattern pattern2 = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex2());
                        matcher2 = pattern2.matcher(returnQues.getContent());
                    }
                    log.error("++++++++++++++++++++++++++通用库是否为空:selfRegex : {} , selfRegex2 : {}", ivrLibaExtemplatescript.getSelfRegex(), ivrLibaExtemplatescript.getSelfRegex2());
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches() && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches()) {
                        QuestionMessage questionMessage = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
                        IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = returnQues.getNowQuestion();
                        ivrTaskTemplateScriptVO.setSubmoduleText(ivrLibaExtemplatescript.getSwitchText());
                        ivrTaskTemplateScriptVO.setSubmoduleVoice(ivrLibaExtemplatescript.getSwitchWav());
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                        if (ivrLibaExtemplatescript.getIsEnd() == 1) {
                            //将问题置空
                            IvrTaskTemplateScriptVO nowQuestion1 = questionMessage.getNowQuestion();
                            nowQuestion1.setScriptContent(null);
                            nowQuestion1.setScriptVoice(null);
                            questionMessage.setNowQuestion(nowQuestion1);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "isOver", 1, 120, TimeUnit.MINUTES);
                        }
                        //调用"15、tts合成和播放, tts_playback"将结果传回
                        String date = simpleDateFormat1.format(new Date());
                        log.info("调用tts合成和播放------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        phoneUtils.ttsPlayback(nowQuestion.getIvrtext() + ivrTaskTemplateScriptVO.getSubmoduleText(), phoneCallBackVO.getUuid());
                    }
                    break;
                }
                String date = simpleDateFormat1.format(new Date());
                log.info("最后的信息回复-: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                phoneUtils.ttsPlayback(nowQuestion.getIvrtext(), phoneCallBackVO.getUuid());
            }
        }
    }
 
    /**
     * 电话ASR通话回调(雨绮)
     *
     * @param phoneCallReqYQVO
     */
    @Override
    public PhoneCallBackYQVO phoneCallBackYQ(PhoneCallReqYQVO phoneCallReqYQVO) {
        //先把该subId从cache_exist中剔除,只要有回调就剔除(目的是,尽快让cache-exist为空,去缓存下一批要打的电话;这里剔除不影响电话的正常业务)
//        redisCache.removeElementFromList("cache-exist", phoneCallReqYQVO.getTaskid());
 
        //判断是否挂机
        String hangupState = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "- hangup");
        Object cacheObject1 = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup");
        if (StringUtils.isNotEmpty(hangupState) && hangupState.equals("1") || ObjectUtils.isNotEmpty(cacheObject1) && String.valueOf(cacheObject1).equals("1")) {
            return new PhoneCallBackYQVO();
        }
        if ("AsrCallback".equals(phoneCallReqYQVO.getOperate()) && phoneCallReqYQVO.getEnd_time() != null && phoneCallReqYQVO.getEnd_time() != -1) {
            //处理挂断
            if (phoneCallReqYQVO.getAsrtext().contains("拨叫的用户正忙")) {
                //判断 recordAccept-hungup 是否有值,如果有,则说明不用处理了,之前已经处理过了(recordAccept-hungup这个主要是给"通话记录用的,")
                Object cacheObject = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup");
                if (ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("1")) {
                    ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallReqYQVO.getTaskid()));
                    setFailPreachForm(serviceSubtask, "3", "拨叫的用户正忙", "4");
                    return new PhoneCallBackYQVO();
                }
                //如果发送状态为6,就说明已经打完了,也没有必要继续往下走了
                if (StringUtils.isNotEmpty(phoneCallReqYQVO.getTaskid())) {
                    ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallReqYQVO.getTaskid()));
                    if (serviceSubtask.getSendstate() == 6L) return new PhoneCallBackYQVO();
                }
 
                ServiceSubtask serviceSubtask2 = new ServiceSubtask();
                serviceSubtask2.setRemark("电话发送成功(患者挂断)");
                serviceSubtask2.setSenduuid(phoneCallReqYQVO.getUuid());
                serviceSubtask2.setId(Long.valueOf(phoneCallReqYQVO.getTaskid()));
                taskSubtaskApi.updateSubtask(serviceSubtask2);
                Map<String, String> req = new HashMap<>();
                req.put("uuid", phoneCallReqYQVO.getUuid());
                req.put("caller", phoneCallReqYQVO.getPhone());
                HttpUtil.postJsonRequest(hangup, new Gson().toJson(req));
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- hangup", "1", 2, TimeUnit.MINUTES);
                //先把默认的recordAccept-hungup删除,再更新
                redisCache.deleteObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup");
                redisCache.setCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup", "1", 10, TimeUnit.MINUTES);
 
                //记录电话发送状态
                setFailPreachForm(serviceSubtask2, "3", "电话发送成功(患者挂断)", "4");
 
                //这个时候就需要走补偿机制了,先暂定走短信
                //原 getSmsCompensate(...) 未随电话模块化搬迁(模块化前调用点就已注释、属死代码),
                //如需恢复短信补偿,请走 service_out_path / 短信发送方的归属模块 API,见 doc/电话模块化_调研与实施方案.md
                return new PhoneCallBackYQVO();
            }
        }
        //定义一个分数的变量
        Boolean aBoolean1 = redisCache.hasKey(phoneCallReqYQVO.getUuid() + "SCORE");
        if (!aBoolean1) redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", 0.0, 120, TimeUnit.MINUTES);
        PhoneCallBackYQVO phoneCallBackYQVO = new PhoneCallBackYQVO();
        //channel_create 通道创建的时候,可以执行一些其它操作,譬如发个短信之类的;  我们的业务可以不用管    PlayEventCallback 这个是播放语音的,暂时用不到     End_time()= -1或null表示当前的asrtext不是一句完整的话
        if (phoneCallReqYQVO.getOperate().equals("channel_create")) {
            return phoneCallBackYQVO;
        }
        //PlayEventCallback 这个是播放语音的    playstart:放音开始(问题播报开始)    playstop: 放音结束(问题播报结束)
        if (phoneCallReqYQVO.getOperate().equals("PlayEventCallback")) {
            String cacheJSY = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "- jsy");
            if (phoneCallReqYQVO.getOperate().equals("PlayEventCallback") && phoneCallReqYQVO.getPlaystop() == false) {
                //判断redis中是否有结束语
                if (StringUtils.isEmpty(cacheJSY)) {
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop", false, 120, TimeUnit.MINUTES);
                    log.error("PlayEventCallbackPlaystop的值为-------:{}", false);
                }
            } else {
                //如果结束语不为空,则要挂电话了
                if (StringUtils.isNotEmpty(cacheJSY)) {
                    Map<String, String> req = new HashMap<>();
                    req.put("uuid", phoneCallReqYQVO.getUuid());
                    req.put("caller", phoneCallReqYQVO.getPhone());
//                    HttpUtils.sendPost(hangup, new Gson().toJson(req));
                    HttpUtil.postJsonRequest(hangup, new Gson().toJson(req));
                    ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallReqYQVO.getTaskid()));
                    //记录电话发送状态
                    setFailPreachForm(serviceSubtask, "3", "通话正常结束", "9");
                    //删除结束语的缓存
                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "- jsy");
                } else {
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop", true, 120, TimeUnit.MINUTES);
                    log.error("-------PlayEventCallbackPlaystop的值为:{}", true);
                }
            }
 
            return phoneCallBackYQVO;
        }
        //获取放音是否结束
        Object isPlayEventOverObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
        if (ObjectUtils.isNotEmpty(isPlayEventOverObj)) {
            Boolean isPlayEventOver = (Boolean) isPlayEventOverObj;
            if (!isPlayEventOver) {
                return phoneCallBackYQVO;
            }
        }
 
        //通过子任务ID获取到模板信息
        ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallReqYQVO.getTaskid()));
        IvrTaskTemplate ivrTaskTemplate = ivrTaskTemplateService.selectIvrTaskTemplateByID(serviceSubtask.getTemplateid());
        //获取模板问题
        IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript();
        ivrTaskTemplateScript.setTemplateID(serviceSubtask.getTemplateid());
        List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript);
        //获取问题ID 和 序号
        String scriptId = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim());
        log.error("scriptId是多少:{}", scriptId);
        //当前题的信息
        IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = iIvrTaskTemplateScriptService.getTaskTempScriptInfoByid(Long.valueOf(scriptId));
        //判断UUID是否存在
        Boolean aBoolean = redisCache.hasKey(phoneCallReqYQVO.getUuid());
        if (!aBoolean) {
            //给静默设置一个默认次数在redis中
            redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
            //如果不存在,就把当前的UUID做为key,放到对象中去
            redisCache.setCacheObject(phoneCallReqYQVO.getUuid(), phoneCallReqYQVO, 120, TimeUnit.MINUTES);
        }
 
        if ("SilentCallback".equals(phoneCallReqYQVO.getOperate())) {
            //如果是静默回调
            Integer num = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "noVoice");
            //判断静默回调次数是否小与模板规定的次数
            if (num < ivrTaskTemplate.getNoVoiceNum()) {
                //小与的话,就继续问患者
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                String scriptContent = ivrTaskTemplateScriptVO.getIvrtext();
                log.error("SilentCallback的问题内容scriptContent:{}", scriptContent);
                phoneCallBackYQVO.setValue(getObject(serviceSubtask, scriptContent));
                //将静默次数加1
                Integer noVoiceNum = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "noVoice");
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "noVoice", noVoiceNum + 1, 120, TimeUnit.MINUTES);
                return phoneCallBackYQVO;
            } else {
                log.error("静默次数达到,挂掉电话:{}", num);
                ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                ServiceSubtask ss = new ServiceSubtask();
                ss.setId(serviceSubtask.getId());
                ss.setSendstate(5L);
                ss.setRemark("电话静默");
                taskSubtaskApi.updateSubtask(ss);
                //大与等于的话,直接挂断
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                phoneCallBackYQVO.setValue(serviceTask1.getJsy());
                //将结果写到detail中
                ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate));
                serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                saveQuestionAnswerPhone(serviceSubTaskDetailReq);
                //去redis中,把该子任务ID删除
                Long id = serviceSubtask.getId();
                //先更新一下分数
                double score = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                serviceSubtask.setScore(String.valueOf(score));
                serviceSubtask.setFinishtime(new Date());
                serviceSubtask.setUpdateTime(new Date());
                log.error("先更新一下分数,电话的serviceSubtask的值为:{}", serviceSubtask);
                taskSubtaskApi.updateSubtask(serviceSubtask);
                //记录状态
                setFailPreachForm(serviceSubtask, "3", "静默次数达到" + num + "次", "4");
 
                Map<String, String> map = delRedisValue(null, id.toString());
                if (ObjectUtils.isNotEmpty(map)) redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                //在redis中保存一下结束语,在调用挂电话的方法时删除
                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
            }
            return phoneCallBackYQVO;
        } else if ("AsrCallback".equals(phoneCallReqYQVO.getOperate()) && phoneCallReqYQVO.getEnd_time() != null && phoneCallReqYQVO.getEnd_time() != -1) {
            //做一个标识,用来在通话详情接口里,判断是否有人接电话(value=2,表示有人接)
            redisCache.deleteObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup");
            redisCache.setCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup", "2", 10, TimeUnit.MINUTES);
            // 先对通话进行通用库匹配一次
            String extemplateID = ivrTaskTemplate.getSubmoduleID();
            if (StringUtils.isNotEmpty(extemplateID)) {
                String[] split = extemplateID.split(",");
                List<String> list = Arrays.asList(split);
                List<Long> list1 = new ArrayList<>();
                for (String str : list) {
                    list1.add(Long.valueOf(str));
                }
                List<IvrLibaExtemplatescript> ivrLibaExtemplatescripts = ivrLibaExtemplatescriptService.queryIvrLibaExtemplatescriptList(list1);
                IvrLibaExtemplatescript les = null;
                for (IvrLibaExtemplatescript ivrLibaExtemplatescript : ivrLibaExtemplatescripts) {
                    Matcher matcher = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex())) {
                        Pattern pattern = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex());
                        matcher = pattern.matcher(phoneCallReqYQVO.getAsrtext());
                    }
 
                    Matcher matcher2 = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2())) {
                        Pattern pattern2 = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex2());
                        matcher2 = pattern2.matcher(phoneCallReqYQVO.getAsrtext());
                    }
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches() && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches()) {
                        //将通用库匹配的,放到返回值中
//                        phoneCallBackYQVO.setValue(phoneCallBackYQVO.getValue() + ivrLibaExtemplatescript.getSwitchText());
                        phoneCallBackYQVO.setCommonValue(ivrLibaExtemplatescript.getSwitchText());
                        les = ivrLibaExtemplatescript;
                    }
                    break;
                }
                log.info("是否需要挂机:{}", les);
                if (ObjectUtils.isNotEmpty(les)) {
                    //对匹配的结果处理一下(看看是不是需要挂机)
                    if (les.getIsEnd() != null && les.getIsEnd() == 1) {
                        ServiceSubtask ss = new ServiceSubtask();
                        ss.setId(serviceSubtask.getId());
                        ss.setSendstate(6L);
                        ss.setRemark("电话拨打已完成");
                        taskSubtaskApi.updateSubtask(ss);
                        //记录状态
                        setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                        //可以挂机了
                        redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                        redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                        redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                        redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice");
                        //在redis中保存一下结束语,在调用挂电话的方法时删除
                        ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                        redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                        phoneCallBackYQVO.setType("text");
                        phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + les.getSwitchText());
                        //将结果写进detail表
                        ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                        List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                        ivrTaskTemplateScriptVO.setExtemplateText(les.getSwitchText());
                        serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate));
                        serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                        serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                        serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                        saveQuestionAnswerPhone(serviceSubTaskDetailReq);
                        return phoneCallBackYQVO;
                    }
                }
            }
 
            //如果是文本回调
            //根据问题ID获取该问题的类型
            if (ivrTaskTemplateScriptVO.getScriptType().equals("1")) {
                //用来标记,是否有匹配上的
                Integer flag = 0;
                //1-AI识别
                String url = taskSysConfigPort.selectConfigValue("sys.voice.match.ai.url", phoneCallReqYQVO.getOrgid());
 
                if (ObjectUtils.isNotEmpty(url)) {
                    PhoneCallBackYQVO aiMatchResult = AiMatch(url, phoneCallReqYQVO, phoneCallBackYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate, ivrTaskTemplateScripts, scriptId, flag, phoneCallReqYQVO.getUuid());
                    if (aiMatchResult != null) {
                        return aiMatchResult;
                    }
                } else {
                    //是选择题
                    for (int j = 0; j < ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().size(); j++) {
                        log.error("phoneCallReqYQVO.getAsrtext()的值为:{}", phoneCallReqYQVO.getAsrtext());
                        if (StringUtils.isEmpty(phoneCallReqYQVO.getAsrtext())) {
                            continue;
                        }
                        boolean matchedFlag = false;
                        //包含
                        Matcher matcher = null;
                        if (StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex())) {
                            Pattern pattern = Pattern.compile(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex());
                            matcher = pattern.matcher(phoneCallReqYQVO.getAsrtext());
                        }
                        //不包含
                        Matcher matcher2 = null;
                        if (StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2())) {
                            Pattern pattern2 = Pattern.compile(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2());
                            matcher2 = pattern2.matcher(phoneCallReqYQVO.getAsrtext());
                        }
 
                        if (StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() && StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches() || StringUtils.isEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() || StringUtils.isEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex2()) && StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches()) {
                            matchedFlag = true;
                        }
                        //说明匹配正确了
                        if (matchedFlag) {
                            //这里应该先判断类型,去再修改,设置IsUserOperation是单选题的改法
                            log.info("匹配正确了吗--------------");
                            ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).setIsUserOperation(1);
                            ivrTaskTemplateTargetoptionService.updateIvrTaskTemplateTargetoption(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j));
 
                            //将患者的回签写进service_subtask_detail中
                            ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                            List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                            ivrTaskTemplateScriptVO.setQuestionResult(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getOptiondesc());
                            ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
                            //修改一下语音路径(改成前端可以访问的,存到数据库中)
                            if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                                String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                                String[] split = questionvoice.split("\\\\");
                                if (split.length > 0) {
                                    String lastPart = split[split.length - 1];
                                    serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                                }
                            }
                            serviceSubtaskDetailList.add(serviceSubtaskDetail);
                            serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                            serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                            serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                            saveQuestionAnswerPhone(serviceSubTaskDetailReq);
 
                            //判断一下当前的问题是不是满意度问题,并且dutyDeptCode是否有值,并且选项是不是异常选项,如果全符合,则往满意度问题异常表新增
                            if (StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getDutyDeptCode()) && 1 == ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getIsabnormal()) {
                                ServiceSubtaskDetailTrace subtaskDetailTrace = new ServiceSubtaskDetailTrace();
                                //用taskid、subid和scriptid去获取detailid
                                ServiceSubtaskDetail ssd = new ServiceSubtaskDetail();
                                ssd.setSubId(serviceSubtask.getId());
                                ssd.setTaskid(serviceSubtask.getTaskid());
                                ssd.setScriptid(StringUtils.isNotEmpty(scriptId) ? Long.valueOf(scriptId) : null);
                                List<ServiceSubtaskDetail> serviceSubtaskDetails = taskSubtaskApi.findSubtaskDetails(ssd);
                                subtaskDetailTrace.setDetailId(CollectionUtils.isNotEmpty(serviceSubtaskDetails) ? serviceSubtaskDetails.get(0).getId() : null);
 
                                subtaskDetailTrace.setSubId(serviceSubtask.getId());
                                subtaskDetailTrace.setTaskid(serviceSubtask.getTaskid());
                                subtaskDetailTrace.setTemplateid(ivrTaskTemplateScriptVO.getId());
                                subtaskDetailTrace.setTemplatequestionnum(ivrTaskTemplateScriptVO.getScriptno());
                                subtaskDetailTrace.setSwitchid(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getId());
                                subtaskDetailTrace.setQuestiontext(ivrTaskTemplateScriptVO.getScriptContent());
                                subtaskDetailTrace.setQuestionvoice(null);
                                subtaskDetailTrace.setCategoryname(ivrTaskTemplateScriptVO.getScriptAssortname());
                                subtaskDetailTrace.setCategoryid(ivrTaskTemplateScriptVO.getScriptAssortid());
                                //获取所有选项
                                String optionDescStr = Optional.ofNullable(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList()).filter(list -> !list.isEmpty()).map(list -> list.stream().map(IvrTaskTemplateTargetoption::getOptiondesc).filter(Objects::nonNull).collect(Collectors.joining("&"))).orElse("");
                                subtaskDetailTrace.setTargetid(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getId());
                                subtaskDetailTrace.setTargetvalue(optionDescStr);
                                subtaskDetailTrace.setMatchedtext(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getOptiondesc());
                                subtaskDetailTrace.setValueType(serviceSubtaskDetails.get(0).getValueType());
                                subtaskDetailTrace.setTemplateType(1);
 
                                SvyLibScriptCategory svyLibScriptCategory = svyLibScriptCategoryService.selectSvyLibScriptCategoryById(ivrTaskTemplateScriptVO.getScriptAssortid());
                                subtaskDetailTrace.setType(svyLibScriptCategory.getType());
                                subtaskDetailTrace.setScriptid(ivrTaskTemplateScriptVO.getId());
                                subtaskDetailTrace.setAsrtext(phoneCallReqYQVO.getAsrtext());
                                subtaskDetailTrace.setRecordpath(phoneCallReqYQVO.getRecordpath());
                                subtaskDetailTrace.setPatid(serviceSubtask.getPatid());
                                JSONObject patdescJson = new JSONObject();
                                patdescJson.put("sendname", serviceSubtask.getSendname());
                                patdescJson.put("phone", serviceSubtask.getPhone());
                                patdescJson.put("age", serviceSubtask.getAge());
                                patdescJson.put("sex", serviceSubtask.getSex() != null ? serviceSubtask.getSex() == 1 ? "男" : "女" : null);
                                subtaskDetailTrace.setPatdesc(patdescJson.toJSONString());
                                subtaskDetailTrace.setTodeptcode(ivrTaskTemplateScriptVO.getDutyDeptCode());
                                subtaskDetailTrace.setTodeptname(ivrTaskTemplateScriptVO.getDutyDeptName());
                                subtaskDetailTrace.setOrgid(serviceSubtask.getOrgid());
                                subtaskDetailTrace.setHandleFlag("0");
                                subtaskDetailTrace.setGuid(phoneCallReqYQVO.getGuid());
                                subtaskDetailTrace.setCreateTime(new Date());
                                subtaskDetailTrace.setUpdateTime(new Date());
                                subtaskDetailTrace.setOrgid(phoneCallReqYQVO.getOrgid());
                                taskSubtaskApi.insertDetailTrace(subtaskDetailTrace);
                            }
 
                            //判断一下,这个选项结果是不是还有继续问下去的必要,例如选项结果是别人不想继续回答问题,就要结束掉
                            if (ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getIsEnd() == 1) {
                                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice");
                                //在redis中保存一下结束语,在调用挂电话的方法时删除
                                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                                phoneCallBackYQVO.setType("text");
                                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                                //记录状态
                                setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                                return phoneCallBackYQVO;
                            }
 
                            flag = 1;
                            //将当前前的播报状态删除,给下一题让位
                            redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
//                        //获取下一题
                            log.error("获取下一题的信息:{}", ivrTaskTemplateScriptVO);
                            if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1") || ivrTaskTemplateScriptVO.getBranchFlag().equals("0") && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) {
                                Long nextQuestion = null;
                                if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1")) {
                                    nextQuestion = ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getNextQuestion();
                                    //更新分数
                                    double score = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                    score = BigDecimal.valueOf(score).add(new BigDecimal(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getScore())).doubleValue();
                                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score);
                                } else {
                                    nextQuestion = ivrTaskTemplateScriptVO.getNextScriptno();
                                    //更新分数
                                    Object obj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                    Double score = (obj == null ? new Double(0.00) : new Double(((Double) obj).doubleValue()));
                                    score = BigDecimal.valueOf(score).add(new BigDecimal(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getScore())).doubleValue();
                                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
                                }
                                if (nextQuestion == null || nextQuestion == 0L) {
                                    //如果下一题为空,或者为0,则挂机
                                    ServiceSubtask ss = new ServiceSubtask();
                                    ss.setId(serviceSubtask.getId());
                                    ss.setSendstate(6L);
                                    ss.setRemark("电话拨打已完成");
                                    taskSubtaskApi.updateSubtask(ss);
                                    //记录状态
                                    setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
 
                                    redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice");
                                    //在redis中保存一下结束语,在调用挂电话的方法时删除
                                    ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                                    phoneCallBackYQVO.setType("text");
                                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                                    //将结果写进detail表
                                    ServiceSubTaskDetailReq ssdReq = new ServiceSubTaskDetailReq();
                                    List<ServiceSubtaskDetail> serviceSubtaskDetailList2 = new ArrayList<>();
                                    serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate));
                                    serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList2);
                                    ssdReq.setGuid(phoneCallReqYQVO.getGuid());
                                    ssdReq.setOrgid(phoneCallReqYQVO.getOrgid());
                                    saveQuestionAnswerPhone(ssdReq);
                                    return phoneCallBackYQVO;
                                }
 
                                for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                                    if (script.getSort() == nextQuestion.intValue()) {
                                        phoneCallBackYQVO.setType("text");
                                        phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                                        String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent();
                                        log.error("下一题问题:{}", scriptContent);
                                        log.error("下一题的子任务是:{}", serviceSubtask);
                                        phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                                        //将该患者的Redis中的题目ID,进行修改
                                        redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES);
                                        //删除无响应
                                        redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                                    }
                                }
                            } else if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                                ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                                phoneCallBackYQVO.setType("text");
                                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                                //更新一下分数
                                double score = 0.0;
                                Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                if (ObjectUtils.isNotEmpty(scoreObj)) score = (double) scoreObj;
                                serviceSubtask.setScore(String.valueOf(score));
                                serviceSubtask.setFinishtime(new Date());
                                serviceSubtask.setSendstate(6L);
                                serviceSubtask.setRemark("电话拨打已完成");
                                taskSubtaskApi.updateSubtask(serviceSubtask);
                                //记录状态
                                setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                                //设置结束语
                                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
                                Long id = serviceSubtask.getId();
                                Map<String, String> map = delRedisValue(null, id.toString());
                                log.error("map的值为:{}", map);
                                if (ObjectUtils.isNotEmpty(map))
                                    redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                                redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                                //在redis中保存一下结束语,在调用挂电话的方法时删除
                                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
//                                return phoneCallBackYQVO;
 
                            }
                        } else {
                            log.info("没有匹配上----------------------------");
                            //flag=0,说明没 匹配上,也要把患者说的话记录下来
                            if (j == ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().size() - 1 && flag == 0) {
                                ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                                List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                                ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
                                //修改一下语音路径(改成前端可以访问的,存到数据库中)
                                if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                                    String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                                    String[] split = questionvoice.split("\\\\");
                                    if (split.length > 0) {
                                        String lastPart = split[split.length - 1];
                                        serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                                    }
                                }
                                serviceSubtaskDetailList.add(serviceSubtaskDetail);
                                //如果没有 匹配上,这个必须为null
                                serviceSubtaskDetailList.get(0).setMatchedtext("");
                                serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                                serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                                serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                                saveQuestionAnswerPhone(serviceSubTaskDetailReq);
                            }
                            continue;
                        }
                    }
                }
                //都没有匹配到
                if (StringUtils.isEmpty(phoneCallBackYQVO.getValue())) {
                    log.info("都没有匹配到-------------------------");
                    Integer count = null;
                    Object countObj = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                    if (ObjectUtils.isNotEmpty(countObj)) count = (Integer) countObj;
                    if (count != null && count >= ivrTaskTemplate.getMateNum()) {
                        //如果count已经大于或等于没有匹配次数
                        if (ivrTaskTemplateScriptVO.getBranchFlag().equals("0") && ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getBranchFlag().equals("0") && ivrTaskTemplateScriptVO.getNextScriptno() == 0 || ivrTaskTemplateScriptVO.getBranchFlag().equals("1") && ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getBranchFlag().equals("1") && ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                            //如果是最后一道题,或者没有下一题了,就直接挂机
                            ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                            phoneCallBackYQVO.setType("text");
                            phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                            if (StringUtils.isNotEmpty(phoneCallBackYQVO.getValue()))
                                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + phoneCallBackYQVO.getValue() + serviceTask1.getJsy());
                            else phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
 
                            //更新一下分数
                            Double score = null;
                            Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                            if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                            serviceSubtask.setScore(String.valueOf(score));
                            serviceSubtask.setFinishtime(new Date());
                            serviceSubtask.setSendstate(6L);
                            serviceSubtask.setRemark("电话拨打已完成");
                            taskSubtaskApi.updateSubtask(serviceSubtask);
                            //记录状态
                            setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                            //在redis中保存一下结束语,在调用挂电话的方法时删除
                            ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                            redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                            //去redis中,把该子任务ID删除
                            Long id = serviceSubtask.getId();
                            Map<String, String> map = delRedisValue(null, id.toString());
                            if (ObjectUtils.isNotEmpty(map)) {
                                redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                            }
//                            return phoneCallBackYQVO;
                        } else {
                            //根据ivrTaskTemplateScriptVO.getNextScriptno()获取下一题进行提问
                            for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                                if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) {
                                    phoneCallBackYQVO.setType("text");
                                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                                    String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent();
                                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                                    //将该患者的Redis中的题目ID,进行修改
                                    redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES);
 
                                    //更新一下分数
                                    Double score = null;
                                    Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                                    if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                                    score = BigDecimal.valueOf(score).add(new BigDecimal(script.getScore())).doubleValue();
 
                                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
                                }
                            }
                        }
                    } else {
                        if (count == null)
                            redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid(), 1, 120, TimeUnit.MINUTES);
                        else
                            redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid(), count + 1, 120, TimeUnit.MINUTES);
 
                        phoneCallBackYQVO.setType("text");
                        phoneCallBackYQVO.setValue(ivrTaskTemplateScriptVO.getNoMatchText() + getObject(serviceSubtask, StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent()));
                    }
                }
 
            } else {
                //不是选择题,直接记录答案,将结果写到detail中
                ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
                //修改一下语音路径(改成前端可以访问的,存到数据库中)
                if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                    String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                    String[] split = questionvoice.split("\\\\");
                    if (split.length > 0) {
                        String lastPart = split[split.length - 1];
                        serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                    }
                }
                serviceSubtaskDetailList.add(serviceSubtaskDetail);
                serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                saveQuestionAnswerPhone(serviceSubTaskDetailReq);
                //    String xh = idSort.split("-")[1];
 
                //如果选项分支为1的话,则需要根据问题上的nextScriptno进行跳转
                //问答题没有跳转
                if (ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) {
                    for (IvrTaskTemplateScript ivrTaskTemplateScript1 : ivrTaskTemplateScripts) {
                        if (ivrTaskTemplateScriptVO.getNextScriptno().intValue() == ivrTaskTemplateScript1.getSort()) {
                            phoneCallBackYQVO.setType("text");
                            phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                            String scriptContent = StringUtils.isNotEmpty(ivrTaskTemplateScript1.getIvrtext()) ? ivrTaskTemplateScript1.getIvrtext() : ivrTaskTemplateScript1.getScriptContent();
 
                            phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                            redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                            redisCache.setCacheObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone(), ivrTaskTemplateScript1.getId().toString());
 
                            //更新一下分数
                            Double score = null;
                            Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                            if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                            score = BigDecimal.valueOf(score).add(new BigDecimal(ivrTaskTemplateScriptVO.getScore())).doubleValue();
                            redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
 
                        }
                    }
                } else if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                    //没有下一题了,就结束了
                    ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
 
                    //更新一下分数
                    Double score = null;
                    Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                    serviceSubtask.setScore(String.valueOf(score));
                    serviceSubtask.setFinishtime(new Date());
                    serviceSubtask.setRemark("电话拨打已完成");
                    serviceSubtask.setSendstate(6L);
                    taskSubtaskApi.updateSubtask(serviceSubtask);
                    //记录状态
                    setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                    //去redis中,把该子任务ID删除
                    Long id = serviceSubtask.getId();
                    Map<String, String> map = delRedisValue(null, id.toString());
                    redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                    //在redis中保存一下结束语,在调用挂电话的方法时删除
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask1.getJsy(), 120, TimeUnit.MINUTES);
                    redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                }
            }
        }
        log.error("phoneCallBackYQVO的返回值是:{}", phoneCallBackYQVO);
        return phoneCallBackYQVO;
    }
 
    private String getObject(ServiceSubtask serviceSubtask, String scriptContent) {
        Map<String, Map<String, String>> param = getParam(serviceSubtask.getTaskid());
        for (Map<String, String> map : param.values()) {
            for (String key : map.keySet()) {
                scriptContent = scriptContent.replace(key, StringUtils.isNotEmpty(map.get(key)) ? map.get(key) : "");
            }
        }
        if (StringUtils.isEmpty(scriptContent)) {
            return scriptContent;
        }
        scriptContent = scriptContent.replace("${name}", StringUtils.isNotEmpty(serviceSubtask.getSendname()) ? serviceSubtask.getSendname() : "");
        scriptContent = scriptContent.replace("${dzz}", StringUtils.isNotEmpty(serviceSubtask.getAddr()) ? serviceSubtask.getAddr() : "");
        scriptContent = scriptContent.replace("${phone}", StringUtils.isNotEmpty(serviceSubtask.getTelcode()) ? serviceSubtask.getTelcode() : "");
 
        return scriptContent;
    }
 
    /**
     * 获取任务里的通配符
     *
     * @param taskId
     * @return
     */
    private Map<String, Map<String, String>> getParam(Long taskId) {
        ServiceTask serviceTask = taskSubtaskApi.getTask(taskId);
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Map<String, String>> serviceTaskMap = null;
        try {
            serviceTaskMap = objectMapper.readValue(serviceTask.getTextParam(), Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return serviceTaskMap;
    }
 
    private Map<String, String> delRedisValue(String cache, String id) {
        id = "," + id + ",";
        String val = "";
        String cacheName = "";
        Map<String, String> map = new HashMap<>();
 
        if (StringUtils.isNotEmpty(cache)) {
            val = redisCache.getCacheObject(cache);
            if (!StringUtils.isEmpty(val)) {
                if (val.contains(id)) {
                    val = val.replaceAll(id, "");
                }
            }
            map.put("val", val);
            map.put("cacheName", cache);
            return map;
        }
 
        for (int i = 0; i < 6; i++) {
            val = redisCache.getCacheObject("cache-0" + i);
            if (!StringUtils.isEmpty(val)) {
                if (val.contains(id)) {
                    val = val.replaceAll(id, "");
                    map.put("val", val);
                    map.put("cacheName", "cache-0" + i);
                }
            }
        }
        return map;
    }
 
    /**
     * 雨绮任务拉取
     *
     * @return
     */
    @Override
    public List<PullTaskVO> taskPull() {
        //pullTaskVOList用于数据返回
        List<PullTaskVO> pullTaskVOList = new ArrayList<>();
        List<String> cacheList = new ArrayList<>();
        ListOperations<String, String> listOps = redisTemplate.opsForList();
        //必须等ache-exist全部打完才能拉取下一批(主要是怕所有的数据都堆在电话的缓存里,在规定的时间打不完)
//        long existSize = listOps.size("cache-exist");
//        if (existSize > 0) return pullTaskVOList;
        int count = 0;
        long size = listOps.size("cache-0");
        log.info("---------打电话之前缓存中的数据量:{}", size);
        if (size > 0) {
            //phoneCount()  通过给出的每个小时需要打出的电话量,算出到晚上8点一点能打出多少个电话,获取到总量
            //如果需要立即执行的数据量大于一天要执行的上限,则只取上限的数量,其它的则放回redis中
            count = Math.min(phoneCount(), (int) size);
            if (count != 0) {
                cacheList = listOps.range("cache-0", 0, count - 1);
            } else {
                return null;
            }
        }
 
        log.info("任务拉取cache-0的值是多少:{}", cacheList);
        //  cache-0为立即发起的,其它的先推迟
        if (!CollectionUtils.isEmpty(cacheList)) {
            pullTaskVOList = getPullTaskList(cacheList, "cache-0");
            // 删除已处理的数据
            listOps.trim("cache-0", count, -1);
            log.info("打电话之后缓存中的数据量---------:{}", listOps.size("cache-0"));
        } else {
            for (int i = 1; i < 6; i++) {
                //取出从cache-1 到 cache-5的第一个子任务信息
                try {
                    Long size1 = listOps.size("cache-" + i);
                    if (size1 == null || size1 == 0) continue;
                    int count1 = Math.min(phoneCount(), size1.intValue());
                    List<String> value = listOps.range("cache-0" + i, 0, count1 - 1);
 
                    List<PullTaskVO> pullTaskVOList2 = getPullTaskList(value, "cache-" + i);
                    if (CollectionUtils.isNotEmpty(pullTaskVOList2) && pullTaskVOList2.size() > 0) {
                        pullTaskVOList.addAll(pullTaskVOList2);
                    }
                    //将处理过的数据删除
                    listOps.trim("cache-0" + i, count1, -1);
                } catch (Exception e) {
//                    log.error("看着烦");
                }
            }
        }
        //existList用来记录接下来需要执行的子任务ID
//        List<String> existList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(pullTaskVOList)) {
            //给回调参数赋值
            for (PullTaskVO pullTaskVO : pullTaskVOList) {
//                existList.add(pullTaskVO.getTaskid());
                pullTaskVO.setAsrcallback(ASRCallBackPath);
            }
        }
//        if (existList.size() != 0) redisCache.setCacheListRight("cache-exist", existList);
        log.info("-----------实际拉取的电话数据量:{}", CollectionUtils.isNotEmpty(pullTaskVOList) ? pullTaskVOList.size() : null);
        return pullTaskVOList;
    }
 
    private List<PullTaskVO> getPullTaskList(List<String> subIds, String cacheName) {
        log.error("任务拉取subIds的值是多少:{}", subIds);
        //pullTaskVOList用于数据返回
        List<PullTaskVO> pullTaskVOList = new ArrayList<>();
        //newValue0用于保存没有处理的子 任务
//        String newValue0 = "";
        List<String> newValue0 = new ArrayList<>();
        //根据,获取子任务的ID
//        String[] split = subIds.split(",,");
        for (int i = 0; i < subIds.size(); i++) {
            if (cacheName.equals("cache-0") && i < subIds.size() || !cacheName.equals("cache-0") && i < 1) {
                PullTaskVO pullTaskVO = new PullTaskVO();
                String subId = subIds.get(i).trim();
                ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(subId));
                if (ObjectUtils.isEmpty(serviceSubtask)) {
                    log.error("该subId有问题,在表中查询不到:{}", subId);
                    continue;
                }
                if (StringUtils.isEmpty(serviceSubtask.getPhone())) {
                    serviceSubtask.setRemark("手机号为空");
                    serviceSubtask.setSendstate(4L);
                    serviceSubtask.setResult("error");
//                    serviceSubtask.setFinishtime(new Date());
                    taskSubtaskApi.updateSubtask(serviceSubtask);
                    continue;
                }
                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                IvrTaskTemplate ivrTaskTemplate = ivrTaskTemplateService.selectIvrTaskTemplateByID(serviceSubtask.getTemplateid());
                if (ObjectUtils.isEmpty(ivrTaskTemplate)) continue;
                //通过任务模板中的"第一次问题编号"获取第一个问题;
                IvrTaskTemplateScript ivrTaskTemplateScript = null;
                IvrTaskTemplateScript ivrTaskTemplateScript1 = new IvrTaskTemplateScript();
                ivrTaskTemplateScript1.setTemplateID(ivrTaskTemplate.getId());
                List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript1);
                aa:
                for (IvrTaskTemplateScript ivrTaskTemplateScript2 : ivrTaskTemplateScripts) {
                    if (ivrTaskTemplate.getFirstQuestionNum() == Long.valueOf(ivrTaskTemplateScript2.getSort())) {
                        ivrTaskTemplateScript = ivrTaskTemplateScript2;
                        break aa;
                    }
                }
                //如果ivrTaskTemplateScript为空,也就没有往下执行的必要了
                if (ObjectUtils.isEmpty(ivrTaskTemplateScript)) {
                    log.error("---------这个ivrTaskTemplate.getId()的问题为空:{}", ivrTaskTemplate.getId());
                    continue;
                }
                //获取通配符匹配过后的问题
                String scriptContent = ivrTaskTemplateScript.getIvrtext();
                if (StringUtils.isEmpty(scriptContent)) scriptContent = ivrTaskTemplateScript.getScriptContent();
                String scrContent = getObject(serviceSubtask, scriptContent);
                String kcb = serviceTask.getKcb() + "," + scrContent;
 
                //封装返回数据
                //taskId = 子任务ID + 问题ID +问题序号
                pullTaskVO.setTaskid(subId);
                pullTaskVO.setAppkey(app_key_yq);
                pullTaskVO.setSections(LocalTime.now().format(DateTimeFormatter.ofPattern("hh:mm")) + "-" + LocalTime.now().plusMinutes(1).format(DateTimeFormatter.ofPattern("hh:mm")));
                pullTaskVO.setPhones(serviceSubtask.getPhone());
                pullTaskVO.setPrologue(kcb);
                if (cacheName.equals("cache-0")) pullTaskVO.setDisplayNo("2");
                else pullTaskVO.setDisplayNo("2");
                pullTaskVOList.add(pullTaskVO);
                redisCache.setCacheObject(subId.trim() + "-" + serviceSubtask.getPhone().trim(), ivrTaskTemplateScript.getId().toString(), 120, TimeUnit.MINUTES);
            } else {
                newValue0.add(subIds.get(i));
                redisCache.setCacheListRight(cacheName, newValue0);
            }
        }
 
        return pullTaskVOList;
    }
 
    @Override
    public Integer saveQuestionAnswerPhone(ServiceSubTaskDetailReq serviceSubTaskDetailReq) {
        int i = 0;
        log.info("保存电话回调内容 saveQuestionAnswerPhone:{}", serviceSubTaskDetailReq);
        if (StringUtils.isNotEmpty(serviceSubTaskDetailReq.getParam1())) {
            RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample();
            Long tid = Long.valueOf(rsaPublicKeyExample.decryptedData(serviceSubTaskDetailReq.getParam1(), pri_key));
            Long pid = Long.valueOf(rsaPublicKeyExample.decryptedData(serviceSubTaskDetailReq.getParam2(), pri_key));
            ServiceSubtaskEntity ivrTaskSingle = new ServiceSubtaskEntity();
            ivrTaskSingle.setTaskid(tid);
            ivrTaskSingle.setPatid(pid);
            List<ServiceSubtask> selectServiceSubtaskList = taskSubtaskApi.findSubtasks(ivrTaskSingle);
            if (CollectionUtils.isEmpty(selectServiceSubtaskList) || selectServiceSubtaskList.size() == 0) {
                log.error("报错了,selectServiceSubtaskList数据为空了:{}", ivrTaskSingle);
                return 0;
            }
            //随访
            for (ServiceSubtaskDetail serviceSubtaskDetail : serviceSubTaskDetailReq.getServiceSubtaskDetailList()) {
                if (serviceSubtaskDetail.getScriptid() != null) {
                    //设置一下问题分类
                    IvrTaskTemplateScript ivrTaskTemplateScript = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptByID(serviceSubtaskDetail.getScriptid());
                    if (ivrTaskTemplateScript != null)
                        serviceSubtaskDetail.setCategoryid(ivrTaskTemplateScript.getScriptAssortid());
                    serviceSubtaskDetail.setIsMydException(ivrTaskTemplateScript.getIsMydException());
                    serviceSubtaskDetail.setDimension(ivrTaskTemplateScript.getDimension());
                }
 
                serviceSubtaskDetail.setSubId(selectServiceSubtaskList.get(0).getId());
//                serviceSubtaskDetail.setId(UUID.randomUUID().toString());
                serviceSubtaskDetail.setCreateTime(new Date());
                serviceSubtaskDetail.setGuid(selectServiceSubtaskList.get(0).getGuid());
                serviceSubtaskDetail.setOrgid(serviceSubTaskDetailReq.getOrgid());
                serviceSubtaskDetail.setGuid(serviceSubTaskDetailReq.getGuid());
                i = taskSubtaskApi.insertSubtaskDetail(serviceSubtaskDetail);
            }
        } else {
            if (serviceSubTaskDetailReq != null && CollectionUtils.isNotEmpty(serviceSubTaskDetailReq.getServiceSubtaskDetailList())) {
                for (ServiceSubtaskDetail serviceSubtaskDetail : serviceSubTaskDetailReq.getServiceSubtaskDetailList()) {
                    if (serviceSubtaskDetail.getScriptid() != null) {
                        //设置一下问题分类
                        IvrTaskTemplateScript ivrTaskTemplateScript = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptByID(serviceSubtaskDetail.getScriptid());
                        if (ivrTaskTemplateScript != null)
                            serviceSubtaskDetail.setCategoryid(ivrTaskTemplateScript.getScriptAssortid());
                    }
                    serviceSubtaskDetail.setCreateTime(new Date());
                    serviceSubtaskDetail.setGuid(serviceSubTaskDetailReq.getGuid());
                    serviceSubtaskDetail.setOrgid(serviceSubTaskDetailReq.getOrgid());
                    //先根据子任务id,任务ID和问题序号查询一下,该问题是否已经有值,如果有值,直接修改,如果为空,直接插入
                    ServiceSubtaskDetail ssd = new ServiceSubtaskDetail();
                    ssd.setSubId(serviceSubtaskDetail.getSubId());
                    ssd.setTaskid(serviceSubtaskDetail.getTaskid());
                    ssd.setScriptid(serviceSubtaskDetail.getScriptid());
                    if (serviceSubtaskDetail.getSubId() != null) {
                        ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(serviceSubtaskDetail.getSubId());
                        ssd.setGuid(serviceSubtask.getGuid());
                        ssd.setOrgid(serviceSubtask.getOrgid());
                    }
                    List<ServiceSubtaskDetail> serviceSubtaskDetails = taskSubtaskApi.findSubtaskDetails(ssd);
                    if (CollectionUtils.isNotEmpty(serviceSubtaskDetails) && StringUtils.isNotEmpty(serviceSubtaskDetails.get(0).getMatchedtext())) {
                        serviceSubtaskDetail.setId(serviceSubtaskDetails.get(0).getId());
                        taskSubtaskApi.updateSubtaskDetail(serviceSubtaskDetail);
                    } else {
                        if (serviceSubtaskDetail.getSubId() != null) {
                            ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(serviceSubtaskDetail.getSubId());
                            serviceSubtaskDetail.setGuid(serviceSubtask.getGuid());
                            serviceSubtaskDetail.setOrgid(serviceSubtask.getOrgid());
                        }
                        i = taskSubtaskApi.insertSubtaskDetail(serviceSubtaskDetail);
                    }
                }
            }
        }
        return i;
    }
 
    @Override
    public Integer recordAccept(PhoneCallRecordVO phoneCallRecordVO) {
        Object cacheObject = redisCache.getCacheObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup");
        if (phoneCallRecordVO.getHangup_cause().equals("NO_USER_RESPONSE") || ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("1")) {
            //无人接听
            //记录电话发送状态
            ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallRecordVO.getTaskid()));
            setFailPreachForm(serviceSubtask, "3", "无人接听", "4");
            //进行短信补偿
            //原 getSmsCompensate(...) 未随电话模块化搬迁(模块化前调用点就已注释、属死代码),
            //如需恢复短信补偿,请走 service_out_path / 短信发送方的归属模块 API,见 doc/电话模块化_调研与实施方案.md
            redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup");
//            redisCache.removeElementFromList("cache-exist", phoneCallRecordVO.getTaskid());
        } else if (ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("2")) {
//        if (phoneCallRecordVO.getAnswered() != null && phoneCallRecordVO.getAnswered() == true) {
            log.error("有人接电话了,并且完了");
            //说明有人接了
            int startIndex = phoneCallRecordVO.getRecord_path().indexOf("voice") + "voice".length() + 1;  // 加1是跳过/符号
            int endIndex = phoneCallRecordVO.getRecord_path().lastIndexOf("/");
            String result = phoneCallRecordVO.getRecord_path().substring(startIndex, endIndex);
            ServiceSubtask serviceSubtask = new ServiceSubtask();
            serviceSubtask.setRemark("电话拨打已完成");
            serviceSubtask.setSendstate(6L);
            serviceSubtask.setId(Long.valueOf(phoneCallRecordVO.getTaskid()));
            serviceSubtask.setFinishtime(new Date());
            serviceSubtask.setUpdateTime(new Date());
            log.error("电话拨打已完成serviceSubtask的值为:{}", serviceSubtask);
            taskSubtaskApi.updateSubtask(serviceSubtask);
            setFailPreachForm(serviceSubtask, StringUtils.isNotEmpty(serviceSubtask.getCurrentPreachform()) ? serviceSubtask.getCurrentPreachform() : "3", "电话拨打已完成", "9");
            //下载文件
            taskFtpPort.downloadFolder("/" + LocalDate.now().toString(), profile + "/upload/vadio/voice/" + LocalDate.now().toString());
            redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup");
        } else {
            //患者拒绝随访
            //先把该subId从cache_exist中剔除,只要有回调就剔除(目的是,尽快让cache-exist为空,去缓存下一批要打的电话;这里剔除不影响电话的正常业务)
//            redisCache.removeElementFromList("cache-exist", phoneCallRecordVO.getTaskid());
            ServiceSubtask serviceSubtask = new ServiceSubtask();
            serviceSubtask.setRemark("电话接通成功,患者拒绝随访");
            serviceSubtask.setId(Long.valueOf(phoneCallRecordVO.getTaskid()));
            serviceSubtask.setSendstate(6L);
            taskSubtaskApi.updateSubtask(serviceSubtask);
//            int startIndex = phoneCallRecordVO.getRecord_path().indexOf("voice") + "voice".length() + 1;  // 加1是跳过/符号
//            int endIndex = phoneCallRecordVO.getRecord_path().lastIndexOf("/");
//            String result = phoneCallRecordVO.getRecord_path().substring(startIndex, endIndex);
            //下载文件
//            taskFtpPort.downloadFolder("/" + LocalDate.now().toString(), profile + "/upload/vadio/voice/" + LocalDate.now().toString());
            redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup");
            ServiceSubtask ss = taskSubtaskApi.getSubtask(serviceSubtask.getId());
            setFailPreachForm(ss, StringUtils.isNotEmpty(ss.getCurrentPreachform()) ? ss.getCurrentPreachform() : "3", "电话接通成功,患者拒绝随访", "5");
        }
 
        return 1;
    }
 
    private IvrTaskTemplateScriptVO getNextQuestion(List<IvrTaskTemplateScriptVO> IvrTaskTemplateScriptVOList, IvrTaskTemplateScriptVO IvrTaskTemplateScriptVO) {
 
        for (int j = 0; j < IvrTaskTemplateScriptVOList.size(); j++) {
            if (IvrTaskTemplateScriptVOList.get(j).getTargetid() == IvrTaskTemplateScriptVO.getTargetid() + 1) {
                // 对该条templateScriptVO进行处理
                return IvrTaskTemplateScriptVOList.get(j);
            }
        }
        return null;
    }
 
    private ServiceSubtaskDetail getServiceSubtaskDetail(PhoneCallReqYQVO phoneCallReqYQVO, IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask, IvrTaskTemplate ivrTaskTemplate) {
        log.info("-----------------phoneCallReqYQVO的值为:{}", phoneCallReqYQVO);
 
        ServiceSubtaskDetail serviceSubtaskDetail = new ServiceSubtaskDetail();
        serviceSubtaskDetail.setSubId(Long.valueOf(phoneCallReqYQVO.getTaskid()));
        ServiceSubtask serviceSubtask1 = taskSubtaskApi.getSubtask(Long.valueOf(phoneCallReqYQVO.getTaskid()));
        if (serviceSubtask1 != null) {
            serviceSubtaskDetail.setTaskid(serviceSubtask1.getTaskid());
            serviceSubtaskDetail.setPatid(serviceSubtask1.getPatid());
        }
        serviceSubtaskDetail.setTargetid(ivrTaskTemplateScriptVO.getTargetid() != null ? ivrTaskTemplateScriptVO.getTargetid().intValue() : null);
        serviceSubtaskDetail.setUuid(phoneCallReqYQVO.getUuid());
        serviceSubtaskDetail.setPhone(phoneCallReqYQVO.getPhone());
        serviceSubtaskDetail.setOperate(serviceSubtask.getCreateBy());
        serviceSubtaskDetail.setDisplayno(phoneCallReqYQVO.getPhone());
        serviceSubtaskDetail.setAssigntime(System.currentTimeMillis());
        serviceSubtaskDetail.setStarttime(System.currentTimeMillis());
        serviceSubtaskDetail.setAnswertime(System.currentTimeMillis());
        serviceSubtaskDetail.setCategoryid(ivrTaskTemplateScriptVO.getScriptAssortid());
        serviceSubtaskDetail.setAsrtext("无应答");
        if (StringUtils.isNotEmpty(phoneCallReqYQVO.getAsrtext()))
            serviceSubtaskDetail.setAsrtext(phoneCallReqYQVO.getAsrtext());
        serviceSubtaskDetail.setBeginTime(System.currentTimeMillis());
        serviceSubtaskDetail.setEndTime(System.currentTimeMillis());
        serviceSubtaskDetail.setSentEnd(1L);
        serviceSubtaskDetail.setTemplateid(ivrTaskTemplate.getId().toString());
        serviceSubtaskDetail.setTemplatequestionnum(ivrTaskTemplateScriptVO.getScriptno());
        serviceSubtaskDetail.setQuestiontext(StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent());
        serviceSubtaskDetail.setQuestionvoice(phoneCallReqYQVO.getRecordpath());
        serviceSubtaskDetail.setCategoryname(ivrTaskTemplateScriptVO.getScriptType());
        serviceSubtaskDetail.setTargetoptions(ivrTaskTemplateScriptVO.getTargetOptions());
        serviceSubtaskDetail.setExtemplateText(ivrTaskTemplateScriptVO.getExtemplateText());
        serviceSubtaskDetail.setScriptid(ivrTaskTemplateScriptVO.getId());
        serviceSubtaskDetail.setLibTemplateid(serviceSubtask.getLibtemplateid() != null ? serviceSubtask.getLibtemplateid().intValue() : null);
 
        int i = 1;
        for (IvrTaskTemplateTargetoption ivrTaskTemplateTargetoption : ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList()) {
            if (ivrTaskTemplateTargetoption.getIsUserOperation() == 1) {
                serviceSubtaskDetail.setMatchedtext(ivrTaskTemplateTargetoption.getTargetvalue());
                serviceSubtaskDetail.setScore(ivrTaskTemplateTargetoption.getScore() != null ? ivrTaskTemplateTargetoption.getScore().toString() : "0");
            }
            serviceSubtaskDetail.setTargetvalue(StringUtils.isEmpty(serviceSubtaskDetail.getTargetvalue()) ? ivrTaskTemplateTargetoption.getTargetvalue() : serviceSubtaskDetail.getTargetvalue() + "&" + ivrTaskTemplateTargetoption.getTargetvalue());
        }
 
        serviceSubtaskDetail.setAddtime(new Date());
        serviceSubtaskDetail.setIsupload(0L);
        serviceSubtaskDetail.setUploadTime(new Date());
        serviceSubtaskDetail.setDelFlag("0");
        serviceSubtaskDetail.setValueType(ivrTaskTemplateScriptVO.getScriptType());
        return serviceSubtaskDetail;
    }
 
    //通过当前时间,拉取电话总数
    private Integer phoneCount() {
        // 当前时间
        LocalTime currentTime = LocalTime.now();
        // 目标时间(晚上 8 点)
        LocalTime targetTime = LocalTime.of(phoneEndHour, 0);
//        // 计算当前时间到目标时间的时长
//        Duration duration = Duration.between(currentTime, targetTime);
//        // 获取剩余时间的小时数
//        long remainingHours = 0;
//        long remainingMinutes = duration.toMinutes();
//        //如果超过8点,就设置为0
//        //距离结束时间小于20分钟,就不拉取了
//        if (remainingMinutes < 20) remainingHours = 0;
//        else if (remainingMinutes < 60 && remainingMinutes > 20) remainingHours = 1;
//        else if (remainingMinutes > 60) remainingHours = remainingMinutes / 60;
//        // 计算剩余可以打的电话数
//        int remainingCalls = (int) (remainingHours * phoneUpEveryHour);
//        return remainingCalls;
        if (currentTime.isBefore(targetTime)) {
            //如果当前时间还在截止时间内,则继续发
            return phoneUpEveryHour;
        }
        return 0;
    }
 
    /**
     * @param serviceSubtask
     * @param preachform
     * @param remark
     * @param failSendstate
     * @return
     */
    public Boolean setFailPreachForm(ServiceSubtask serviceSubtask, String preachform, String remark, String failSendstate) {
        log.info("setFailPreachForm 随访流程处理 serviceSubtask:{}, preachform:{}, remark:{}, failSendstate:{}", serviceSubtask, preachform, remark, failSendstate);
        //将状态设置为失败
        ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
        serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
        serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid());
        serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
        //获取该患者的发送方式总数
        List<ServiceSubtaskPreachform> spSize = taskPreachformPort.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
 
        serviceSubtaskPreachform.setPreachform(preachform);
        //1:未发送状态
        serviceSubtaskPreachform.setSendstate("1");
        if (preachform.equals("3")) {
            //电话进入队列后,状态会变成2
            serviceSubtaskPreachform.setSendstate("2");
        }
        List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = taskPreachformPort.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) {
            ServiceSubtaskPreachform serviceSubtaskPreachform1 = serviceSubtaskPreachforms.get(0);
            serviceSubtaskPreachform1.setSendstate(failSendstate);
            serviceSubtaskPreachform1.setRemark(remark);
            taskPreachformPort.updateServiceSubtaskPreachform(serviceSubtaskPreachform1);
 
            //如果当前的preachform已经是最后一个了,那直接将serviceSubtask的sendstate状态改成5就行了(全失败了)
            if (serviceSubtaskPreachform1.getSort() == spSize.size() && failSendstate.equals("4")) {
                serviceSubtask.setCurrentPreachform(preachform);
                serviceSubtask.setSendstate(5L);
                serviceSubtask.setRemark(remark + ";所有执行方式均未获取结果,任务失败");
                taskSubtaskApi.updateSubtask(serviceSubtask);
                return true;
            } else {
                //加入目前补偿里的 remark
                serviceSubtask.setRemark(StringUtils.isNotEmpty(serviceSubtask.getRemark()) ? serviceSubtask.getRemark() + "," + remark : remark);
                taskSubtaskApi.updateSubtask(serviceSubtask);
            }
        }
 
        //尽管失败,这里也将当前发送方式继续设置成“电话”,sendstate设置成3;因为ryTask里的补偿的定时任务运行时,会找到这条subtask,并进行处理
        serviceSubtask.setCurrentPreachform(preachform);
        serviceSubtask.setSendstate(3L);
        //如果等于9,则说明电话正常结束了
        if (failSendstate.equals("9")) serviceSubtask.setSendstate(6L);
        serviceSubtask.setVisitTime(getNextVisitTime(serviceSubtask.getId(), serviceSubtask.getTaskid(), serviceSubtask.getVisitTime()));
        taskSubtaskApi.updateSubtask(serviceSubtask);
        return true;
    }
 
    private Date getNextVisitTime(Long subid, Long taskid, Date visitTime) {
        ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
        serviceSubtaskPreachform.setSubid(subid);
        serviceSubtaskPreachform.setTaskid(taskid);
        List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = taskPreachformPort.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) {
            //没有随访时间则按当天来算--临时
            if (ObjectUtils.isEmpty(visitTime)) {
                visitTime = new Date();
            }
 
            String compensateTime = serviceSubtaskPreachforms.get(0).getCompensateTime();
            int hoursToAdd = Integer.valueOf(compensateTime) * 24;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(visitTime);
            calendar.add(Calendar.HOUR_OF_DAY, hoursToAdd);
            Date newDate = calendar.getTime();
            return newDate;
        }
        return visitTime;
    }
 
    public PhoneCallBackSHVO getFirstQues(PhoneCallReqYQVO phoneCallReqYQVO) {
        //用于返回
        PhoneCallBackSHVO phoneCallBackSHVO = new PhoneCallBackSHVO();
 
        //根据手机号获取用户的的子任务信息
        ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
        serviceSubtaskVO.setPhone(phoneCallReqYQVO.getPhone());
        serviceSubtaskVO.setType("1");
        serviceSubtaskVO.setSendstate(2L);
        List<ServiceSubtask> serviceSubtasks = taskSubtaskApi.findSubtasks(serviceSubtaskVO);
        if (CollectionUtils.isNotEmpty(serviceSubtasks)) {
            ServiceSubtask serviceSubtask = serviceSubtasks.get(0);
            IvrTaskTemplate ivrTaskTemplate = ivrTaskTemplateService.selectIvrTaskTemplateByID(serviceSubtask.getTemplateid());
 
            //通过任务模板中的"第一次问题编号"获取第一个问题;
            IvrTaskTemplateScript ivrTaskTemplateScript = null;
            IvrTaskTemplateScript ivrTaskTemplateScript1 = new IvrTaskTemplateScript();
            ivrTaskTemplateScript1.setTemplateID(ivrTaskTemplate.getId());
            List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript1);
 
            for (IvrTaskTemplateScript ivrTaskTemplateScript2 : ivrTaskTemplateScripts) {
                if (ivrTaskTemplate.getFirstQuestionNum() == Long.valueOf(ivrTaskTemplateScript2.getSort())) {
                    ivrTaskTemplateScript = ivrTaskTemplateScript2;
                    break;
                }
            }
            //获取开场白
            ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
 
            phoneCallBackSHVO.setSubId(serviceSubtask.getId());
            phoneCallBackSHVO.setScriptId(ivrTaskTemplateScript.getId());
            phoneCallBackSHVO.setSort(ivrTaskTemplateScript.getSort());
            phoneCallBackSHVO.setTaskTemplateid(ivrTaskTemplateScript.getTemplateID());
            phoneCallBackSHVO.setScriptContent(serviceTask.getKcb() + "," + ivrTaskTemplateScript.getScriptContent());
        }
        return phoneCallBackSHVO;
    }
 
    /**
     * 三汇ASR结果处理
     *
     * @param phoneCallResultYQVO
     * @return
     */
    public PhoneCallBackSHVO processResust(PhoneCallResultYQVO phoneCallResultYQVO) {
        PhoneCallBackSHVO phoneCallBackSHVO = new PhoneCallBackSHVO();
        //通过scriptid,获取所有的结果
        String url = taskSysConfigPort.selectConfigValue("sys.voice.match.ai.url", phoneCallResultYQVO.getOrgid());
        ServiceSubtask serviceSubtask = taskSubtaskApi.getSubtask(phoneCallResultYQVO.getSubId());
        IvrTaskTemplate ivrTaskTemplate = ivrTaskTemplateService.selectIvrTaskTemplateByID(serviceSubtask.getTemplateid());
        IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO = iIvrTaskTemplateScriptService.getTaskTempScriptInfoByid(Long.valueOf(phoneCallResultYQVO.getScriptId()));
        Integer i = subtaskOptionMatchApi.matchOptionIndex(url, phoneCallResultYQVO.getScriptContent(), phoneCallResultYQVO.getAsrResult(), ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList(), phoneCallResultYQVO.getUuid());
        if (i >= 0) {
            String optiondesc = ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(i).getOptiondesc();
            //将患者的回答写进service_subtask_detail中
            ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
            List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
            ivrTaskTemplateScriptVO.setQuestionResult(optiondesc);
 
            PhoneCallReqYQVO phoneCallReqYQVO = new PhoneCallReqYQVO();
            phoneCallReqYQVO.setTaskid("" + serviceSubtask.getId());
            phoneCallReqYQVO.setPhone(phoneCallResultYQVO.getPhone());
            phoneCallReqYQVO.setAsrtext(phoneCallResultYQVO.getAsrResult());
            ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
            //修改一下语音路径(改成前端可以访问的,存到数据库中)
            if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                String[] split = questionvoice.split("\\\\");
                if (split.length > 0) {
                    String lastPart = split[split.length - 1];
                    serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                }
            }
            serviceSubtaskDetailList.add(serviceSubtaskDetail);
            serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
            serviceSubTaskDetailReq.setGuid(phoneCallResultYQVO.getGuid());
            serviceSubTaskDetailReq.setOrgid(phoneCallResultYQVO.getOrgid());
            saveQuestionAnswerPhone(serviceSubTaskDetailReq);
 
            IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript();
            ivrTaskTemplateScript.setTemplateID(ivrTaskTemplateScriptVO.getTemplateID());
            List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript);
 
            //获取下一题
            for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                    ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                    phoneCallBackSHVO.setScriptContent(serviceTask.getJsy());
                    phoneCallBackSHVO.setTaskTemplateid(script.getTemplateID());
                    phoneCallBackSHVO.setSort(script.getSort());
                    phoneCallBackSHVO.setScriptId(script.getId());
                    phoneCallBackSHVO.setSubId(serviceSubtask.getId());
                    phoneCallBackSHVO.setStatus("0");
                } else if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) {
                    phoneCallBackSHVO.setScriptContent(script.getScriptContent());
                    phoneCallBackSHVO.setTaskTemplateid(script.getTemplateID());
                    phoneCallBackSHVO.setSort(script.getSort());
                    phoneCallBackSHVO.setScriptId(script.getId());
                    phoneCallBackSHVO.setSubId(serviceSubtask.getId());
                    break;
                }
            }
            //把缓存清除
            redisCache.deleteObject(phoneCallResultYQVO.getSubId() + "-" + phoneCallResultYQVO.getScriptId());
        } else {
            //再将重复询问
            //记录一下这个问题被问题的次数
            Object cacheObject = redisCache.getCacheObject(phoneCallResultYQVO.getSubId() + "-" + phoneCallResultYQVO.getScriptId());
            if (cacheObject == null || (Integer) cacheObject < ivrTaskTemplate.getMateNum()) {
 
                // 获取选项集合中的 optiondesc 用于引导患者
                List<IvrTaskTemplateTargetoption> optionList = ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList();
                String optionDescStr = "";
                if (optionList != null && !optionList.isEmpty()) {
                    optionDescStr = optionList.stream().map(IvrTaskTemplateTargetoption::getTargetvalue).filter(StringUtils::isNotEmpty).collect(Collectors.joining("或"));
                }
 
                String scriptContent = "请问" + phoneCallResultYQVO.getScriptContent();
                if (StringUtils.isNotEmpty(optionDescStr)) {
                    scriptContent += ",你可以回答:" + optionDescStr;
                }
                phoneCallBackSHVO.setScriptContent(scriptContent);
                phoneCallBackSHVO.setTaskTemplateid(phoneCallResultYQVO.getTaskTemplateid());
                phoneCallBackSHVO.setSort(phoneCallResultYQVO.getSort());
                phoneCallBackSHVO.setScriptId(phoneCallResultYQVO.getScriptId());
                phoneCallBackSHVO.setSubId(phoneCallResultYQVO.getSubId());
                if (cacheObject == null)
                    redisCache.setCacheObject(phoneCallResultYQVO.getSubId() + "-" + phoneCallResultYQVO.getScriptId(), 1, 120, TimeUnit.MINUTES);
                else
                    redisCache.setCacheObject(phoneCallResultYQVO.getSubId() + "-" + phoneCallResultYQVO.getScriptId(), (Integer) cacheObject + 1, 120, TimeUnit.MINUTES);
            } else if ((Integer) cacheObject >= ivrTaskTemplate.getMateNum()) {
                //如果已经问了规定次数,就不问了,继续问下一题(这个要商量一下,是继续问下一题,还是停了,是不是要做个开关)
                IvrTaskTemplateScript ivrTaskTemplateScript = new IvrTaskTemplateScript();
                ivrTaskTemplateScript.setTemplateID(ivrTaskTemplateScriptVO.getTemplateID());
                List<IvrTaskTemplateScript> ivrTaskTemplateScripts = iIvrTaskTemplateScriptService.selectIvrTaskTemplateScriptList(ivrTaskTemplateScript);
                //获取下一题
                for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                    if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) {
                        phoneCallBackSHVO.setScriptContent(script.getScriptContent());
                        phoneCallBackSHVO.setTaskTemplateid(script.getTemplateID());
                        phoneCallBackSHVO.setSort(script.getSort());
                        phoneCallBackSHVO.setScriptId(script.getId());
                        phoneCallBackSHVO.setSubId(serviceSubtask.getId());
                        break;
                    }
                }
                //把缓存清除
                redisCache.deleteObject(phoneCallResultYQVO.getSubId() + "-" + phoneCallResultYQVO.getScriptId());
            }
        }
        return phoneCallBackSHVO;
    }
 
    public PhoneCallBackYQVO AiMatch(String url, PhoneCallReqYQVO phoneCallReqYQVO, PhoneCallBackYQVO phoneCallBackYQVO, IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO, ServiceSubtask serviceSubtask, IvrTaskTemplate ivrTaskTemplate, List<IvrTaskTemplateScript> ivrTaskTemplateScripts, String scriptId, Integer flag, String uuid) {
        PhoneCallBackYQVO back = null;
        List<IvrTaskTemplateTargetoption> options = ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList();
        String voiceText = phoneCallReqYQVO.getAsrtext();
        String questionText = StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent();
        Integer matched = -1;
        log.info("AI匹配:url = {},questionText = {},voiceText = {},options = {},uuid ={}",
                url,questionText,voiceText,options,uuid);
        matched = subtaskOptionMatchApi.matchOptionIndex(url, questionText, voiceText, options, uuid);
        //说明匹配正确了
        if (matched != null && matched >= 0) {
            IvrTaskTemplateTargetoption chosenOption = options.get(matched);
            //这里应该先判断类型,去再修改,设置IsUserOperation是单选题的改法
            log.info("匹配正确了吗--------------");
            chosenOption.setIsUserOperation(1);
            ivrTaskTemplateTargetoptionService.updateIvrTaskTemplateTargetoption(chosenOption);
 
            //将患者的回签写进service_subtask_detail中
            ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
            List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
            ivrTaskTemplateScriptVO.setQuestionResult(chosenOption.getOptiondesc());
            ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
            //修改一下语音路径(改成前端可以访问的,存到数据库中)
            if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                String[] split = questionvoice.split("\\\\");
                if (split.length > 0) {
                    String lastPart = split[split.length - 1];
                    serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                }
            }
            serviceSubtaskDetailList.add(serviceSubtaskDetail);
            serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
            serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
            serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
            saveQuestionAnswerPhone(serviceSubTaskDetailReq);
 
            //判断一下当前的问题是不是满意度问题,并且dutyDeptCode是否有值,并且选项是不是异常选项,如果全符合,则往满意度问题异常表新增
            if (StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getDutyDeptCode()) && 1 == chosenOption.getIsabnormal()) {
                ServiceSubtaskDetailTrace subtaskDetailTrace = new ServiceSubtaskDetailTrace();
                //用taskid、subid和scriptid去获取detailid
                ServiceSubtaskDetail ssd = new ServiceSubtaskDetail();
                ssd.setSubId(serviceSubtask.getId());
                ssd.setTaskid(serviceSubtask.getTaskid());
                ssd.setScriptid(StringUtils.isNotEmpty(scriptId) ? Long.valueOf(scriptId) : null);
                List<ServiceSubtaskDetail> serviceSubtaskDetails = taskSubtaskApi.findSubtaskDetails(ssd);
                subtaskDetailTrace.setDetailId(CollectionUtils.isNotEmpty(serviceSubtaskDetails) ? serviceSubtaskDetails.get(0).getId() : null);
 
                subtaskDetailTrace.setSubId(serviceSubtask.getId());
                subtaskDetailTrace.setTaskid(serviceSubtask.getTaskid());
                subtaskDetailTrace.setTemplateid(ivrTaskTemplateScriptVO.getId());
                subtaskDetailTrace.setTemplatequestionnum(ivrTaskTemplateScriptVO.getScriptno());
                subtaskDetailTrace.setSwitchid(chosenOption.getId());
                subtaskDetailTrace.setQuestiontext(ivrTaskTemplateScriptVO.getScriptContent());
                subtaskDetailTrace.setQuestionvoice(null);
                subtaskDetailTrace.setCategoryname(ivrTaskTemplateScriptVO.getScriptAssortname());
                subtaskDetailTrace.setCategoryid(ivrTaskTemplateScriptVO.getScriptAssortid());
                //获取所有选项
                String optionDescStr = Optional.ofNullable(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList()).filter(list -> !list.isEmpty()).map(list -> list.stream().map(IvrTaskTemplateTargetoption::getOptiondesc).filter(Objects::nonNull).collect(Collectors.joining("&"))).orElse("");
                subtaskDetailTrace.setTargetid(chosenOption.getId());
                subtaskDetailTrace.setTargetvalue(optionDescStr);
                subtaskDetailTrace.setMatchedtext(chosenOption.getOptiondesc());
                subtaskDetailTrace.setValueType(serviceSubtaskDetails.get(0).getValueType());
                subtaskDetailTrace.setTemplateType(1);
 
                SvyLibScriptCategory svyLibScriptCategory = svyLibScriptCategoryService.selectSvyLibScriptCategoryById(ivrTaskTemplateScriptVO.getScriptAssortid());
                subtaskDetailTrace.setType(svyLibScriptCategory.getType());
                subtaskDetailTrace.setScriptid(ivrTaskTemplateScriptVO.getId());
                subtaskDetailTrace.setAsrtext(phoneCallReqYQVO.getAsrtext());
                subtaskDetailTrace.setRecordpath(phoneCallReqYQVO.getRecordpath());
                subtaskDetailTrace.setPatid(serviceSubtask.getPatid());
                JSONObject patdescJson = new JSONObject();
                patdescJson.put("sendname", serviceSubtask.getSendname());
                patdescJson.put("phone", serviceSubtask.getPhone());
                patdescJson.put("age", serviceSubtask.getAge());
                patdescJson.put("sex", serviceSubtask.getSex() != null ? serviceSubtask.getSex() == 1 ? "男" : "女" : null);
                subtaskDetailTrace.setPatdesc(patdescJson.toJSONString());
                subtaskDetailTrace.setTodeptcode(ivrTaskTemplateScriptVO.getDutyDeptCode());
                subtaskDetailTrace.setTodeptname(ivrTaskTemplateScriptVO.getDutyDeptName());
                subtaskDetailTrace.setOrgid(serviceSubtask.getOrgid());
                subtaskDetailTrace.setHandleFlag("0");
                subtaskDetailTrace.setGuid(phoneCallReqYQVO.getGuid());
                subtaskDetailTrace.setCreateTime(new Date());
                subtaskDetailTrace.setUpdateTime(new Date());
                subtaskDetailTrace.setOrgid(phoneCallReqYQVO.getOrgid());
                taskSubtaskApi.insertDetailTrace(subtaskDetailTrace);
            }
 
            //判断一下,这个选项结果是不是还有继续问下去的必要,例如选项结果是别人不想继续回答问题,就要结束掉
            if (chosenOption.getIsEnd() == 1) {
                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice");
                //在redis中保存一下结束语,在调用挂电话的方法时删除
                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                //记录状态
                setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                back = phoneCallBackYQVO;
                return back;
            }
 
            flag = 1;
            //将当前前的播报状态删除,给下一题让位
            redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
//                        //获取下一题
            log.error("获取下一题的信息:{}", ivrTaskTemplateScriptVO);
            //branchFlag为null时按分支0处理,避免NPE
            if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) {
                Long nextQuestion = null;
                if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag())) {
                    nextQuestion = chosenOption.getNextQuestion();
                    //更新分数
                    double score = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    score = BigDecimal.valueOf(score).add(new BigDecimal(chosenOption.getScore())).doubleValue();
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score);
                } else {
                    nextQuestion = ivrTaskTemplateScriptVO.getNextScriptno();
                    //更新分数
                    Object obj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    Double score = (obj == null ? new Double(0.00) : new Double(((Double) obj).doubleValue()));
                    score = BigDecimal.valueOf(score).add(new BigDecimal(String.valueOf(chosenOption.getScore()))).doubleValue();
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
                }
                if (nextQuestion == null || nextQuestion == 0L) {
                    //如果下一题为空,或者为0,则挂机
                    ServiceSubtask ss = new ServiceSubtask();
                    ss.setId(serviceSubtask.getId());
                    ss.setSendstate(6L);
                    ss.setRemark("电话拨打已完成");
                    taskSubtaskApi.updateSubtask(ss);
                    //记录状态
                    setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
 
                    redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                    redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice");
                    //在redis中保存一下结束语,在调用挂电话的方法时删除
                    ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                    //明细在本题匹配成功时已落库(见上方 saveQuestionAnswerPhone),这里不再重复保存
                    back = phoneCallBackYQVO;
                    return back;
                }
 
                for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                    if (script.getSort() == nextQuestion.intValue()) {
                        phoneCallBackYQVO.setType("text");
                        phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                        String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent();
                        log.error("下一题问题:{}", scriptContent);
                        log.error("下一题的子任务是:{}", serviceSubtask);
                        phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                        //将该患者的Redis中的题目ID,进行修改
                        redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES);
                        //删除无响应
                        redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                    }
                }
                //下一题脚本没找到时,兜底重问当前题,避免调用方误判为未处理而退回正则识别
                if (StringUtils.isEmpty(phoneCallBackYQVO.getValue())) {
                    log.error("下一题脚本未找到,重问当前题,nextQuestion:{}", nextQuestion);
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, questionText));
                }
                back = phoneCallBackYQVO;
                return back;
            } else if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                //更新一下分数
                double score = 0.0;
                Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                if (ObjectUtils.isNotEmpty(scoreObj)) score = (double) scoreObj;
                serviceSubtask.setScore(String.valueOf(score));
                serviceSubtask.setFinishtime(new Date());
                serviceSubtask.setSendstate(6L);
                serviceSubtask.setRemark("电话拨打已完成");
                taskSubtaskApi.updateSubtask(serviceSubtask);
                //记录状态
                setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                //设置结束语
                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
                Long id = serviceSubtask.getId();
                Map<String, String> map = delRedisValue(null, id.toString());
                log.error("map的值为:{}", map);
                if (ObjectUtils.isNotEmpty(map)) redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
                //在redis中保存一下结束语,在调用挂电话的方法时删除
                ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                //结束语已拼进返回值,挂机由平台按返回值执行
                back = phoneCallBackYQVO;
                return back;
 
            }
        } else {
            //AI没有匹配上:由AI分支自己按"没问清就重问"的次数处理,不再退回正则识别
            log.info("ai没有匹配上----------------------------");
            //没匹配上也要把患者说的话记录下来(matchedtext置空,与正则路径口径一致)
            ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
            List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
            ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
            //修改一下语音路径(改成前端可以访问的,存到数据库中)
            if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                String[] split = questionvoice.split("\\\\");
                if (split.length > 0) {
                    String lastPart = split[split.length - 1];
                    serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                }
            }
            serviceSubtaskDetailList.add(serviceSubtaskDetail);
            //如果没有 匹配上,这个必须为null
            serviceSubtaskDetailList.get(0).setMatchedtext("");
            serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
            serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
            serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
            saveQuestionAnswerPhone(serviceSubTaskDetailReq);
 
            String mateKey = phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid();
            Integer count = null;
            Object countObj = redisCache.getCacheObject(mateKey);
            if (ObjectUtils.isNotEmpty(countObj)) count = (Integer) countObj;
            if (count != null && count >= ivrTaskTemplate.getMateNum()) {
                //没匹配次数已经用满,不能再重问了
                boolean noNextQuestion = ("0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "1".equals(ivrTaskTemplateScriptVO.getBranchFlag()))
                        && (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0);
                if (noNextQuestion) {
                    //已经是最后一题,直接挂机
                    ServiceTask serviceTask1 = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
                    //更新一下分数
                    Double score = null;
                    Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                    serviceSubtask.setScore(String.valueOf(score));
                    serviceSubtask.setFinishtime(new Date());
                    serviceSubtask.setSendstate(6L);
                    serviceSubtask.setRemark("电话拨打已完成");
                    taskSubtaskApi.updateSubtask(serviceSubtask);
                    //记录状态
                    setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                    //在redis中保存一下结束语,在调用挂电话的方法时删除
                    ServiceTask serviceTask = taskSubtaskApi.getTask(serviceSubtask.getTaskid());
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                    //去redis中,把该子任务ID删除
                    Long id = serviceSubtask.getId();
                    Map<String, String> map = delRedisValue(null, id.toString());
                    if (ObjectUtils.isNotEmpty(map)) {
                        redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                        redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                        redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    }
                } else {
                    //还有下一题,按nextScriptno继续提问
                    for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                        if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) {
                            phoneCallBackYQVO.setType("text");
                            phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                            String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent();
                            phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                            //将该患者的Redis中的题目ID,进行修改
                            redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES);
                            //更新一下分数
                            Double score = null;
                            Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                            if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                            score = BigDecimal.valueOf(score).add(new BigDecimal(script.getScore())).doubleValue();
                            redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
                            //换题成功,没匹配次数清零
                            redisCache.deleteObject(mateKey);
                        }
                    }
                }
            } else {
                //还没问满次数,用noMatchText引导患者重答
                redisCache.setCacheObject(mateKey, count == null ? 1 : count + 1, 120, TimeUnit.MINUTES);
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                phoneCallBackYQVO.setValue(ivrTaskTemplateScriptVO.getNoMatchText() + getObject(serviceSubtask, StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent()));
            }
            back = phoneCallBackYQVO;
            return back;
        }
        return back;
    }
}