From ec4280334801e3ff8c8f65e6b6bd422880ff8a1d Mon Sep 17 00:00:00 2001 From: surenjun Date: Tue, 14 Jan 2025 15:34:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:request&judge=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/common/utils/request.ts | 1985 +++----------------- entry/src/main/ets/pages/judgeSDK/judge.ts | 1977 ++++++++++++++++--- 2 files changed, 1981 insertions(+), 1981 deletions(-) diff --git a/entry/src/main/ets/common/utils/request.ts b/entry/src/main/ets/common/utils/request.ts index 18983a79..75446b8a 100644 --- a/entry/src/main/ets/common/utils/request.ts +++ b/entry/src/main/ets/common/utils/request.ts @@ -1,1798 +1,249 @@ -import systemTime from '@ohos.systemDateTime'; -import router from '@ohos.router'; -import util from '@ohos.util'; -import buffer from '@ohos.buffer'; -import { testKm2Items,testKm3Items, testMarkRules } from './dataTest/index'; -import { EXAMDATA, SOUND, KSJS } from './api/judgeSDK'; -import VoiceAnnounce from './utils/voiceAnnouncements'; -import FileModel from './utils/fileModel'; -import FilePhoto from './utils/filePhoto'; +import http from '@ohos.net.http'; +import convertxml from '@ohos.convertxml'; +import prompt from '@ohos.prompt' +import { sendGreen } from '../../pages/judgeSDK/utils/judgeCommon'; +import {GlobalConfig} from '../../config/index' import FileUtil from '../../common/utils/File'; -import FileLog from './utils/fileLog'; -import JudgeTask from './utils/judgeTask'; -import { judgeConfig } from './utils/judgeConfig'; -import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; -import UsbService from '../../common/service/usbService'; -import { LANE,KF } from '../judgeSDK/api/judgeSDK.d'; -import {saveStartRecordVideo,endRecordVideo} from '../../common/service/videoService' -import { - Array2Byte, - convertGpsCoord2, - deepClone, - fillZero, - getCurrentTime, - string2Bytes, - stringToASC -} from '../../common/utils/tools'; +import { dateFormat } from '../utils/tools' -import { - getCarStatus, - getCarStatusType, - getDwStatusType, - getCenterProjectStatus, - getKmProjectVoice, - getTranslateSignals, - plcStrToJson, - plcStrToWXJson, - promptWxCode, - senorToWXDataStr, - getKmProjectCancelVoice -} from './utils/judgeCommon'; +const config = { + host:GlobalConfig.host, +} -import { - examJudgeArtificialItem, - examJudgeArtificialMark, - examJudgeBeginExam, - examJudgeEndExam, - examJudgeInit, - examJudgeSoundEnd, - examJudgeRealExam, - examJudgeSetLogCallback, - examJudgeSetPerformCallback, - examJudgeSetRealExamCallback, - examCalcGpsDistance, - examJudgeVersion -} from './api/index'; +/** + * @author: Renjun Su + * @date: 2023/2/20 + * @desc 接口请求封装 + * @param {method} + * @param {xml} xml请求的数据 xml是字符串 + * @param {data} post请求的数据 + * @param {params} get请求的数据 + * + */ +// let httpRequest = http.createHttp(); -const judgeTag = 'SURENJUN_JUDGE' -import { getSyncData, upDateTableByArray } from '../../common/service/initable'; -export default class Judge { - constructor(judgeUI) { - this.serialIndex = 1; - this.judgeUI = judgeUI - //语音播放工具 - this.avPlayer = new VoiceAnnounce(); - //模型工具 - this.fileModel = new FileModel(judgeUI.context); - //文件工具 - this.fileUtil = new FileUtil(judgeUI.context) - this.judgeTask = new JudgeTask() - this.usbService = new UsbService(); - this.filePhoto = new FilePhoto(judgeUI.context); - this.kfArr = judgeUI.kfArr - this.xmmcStr = ''; - this.xmmcCode = ''; - this.xmmcEndCode = undefined; - this.carztStr = ''; - this.testKmItems = {}; - // 考试回放配置 - const {isTrajectoryOpen,modelPath,trajectoryPath} = judgeConfig - this.isTrajectoryOpen = isTrajectoryOpen; - this.modelPath = modelPath; - this.trajectoryPath = trajectoryPath; - - this.isExam = !this.judgeUI.singlePlay; - const {projectsCenterObj,examSubject} = judgeUI; - - (examSubject ==2 ? testKm2Items : testKm3Items ).forEach(item => { - const projectCenterObj = projectsCenterObj[item.code] - this.testKmItems[item.code] = item; - //考试项目存在 - this.testKmItems[item.code] = { - code: item.code, - status: projectCenterObj === undefined - ? 0 - : ( projectCenterObj.isEnd ? 3 : 1 ) - } - }) - - console.info(judgeTag+'testKmItems',JSON.stringify(this.testKmItems)) - this.isExamEnd = false; +export default async function request(req: any) { + const {url,params = {},data = {},xml,method = 'get',host,isNewCenter = false} = req; + let httpRequest = http.createHttp(); + const options = { + method: http.RequestMethod[method.toUpperCase()], + header: { + 'Content-Type': xml ? 'text/xml' : 'application/json' + }, + extraData: xml ? data : JSON.stringify(data), + //15秒超时 + connectTimeout:15 * 1000 } + //params转url拼接参数 + let paramsStr = Reflect.ownKeys(params).reduce((p: string, n: string) => (`${p}${n}=${params[n]}&`), '?') || ''; + paramsStr = paramsStr.toString(); + paramsStr = paramsStr.substring(0, paramsStr.length-1) + try { + let baseUrl=host?host:globalThis.host + // let baseUrl=host?config.csptHost:config.host' + console.log('响应头地址1' + baseUrl,url,options.extraData.length) + const {result,responseCode} = await httpRequest.request(`${baseUrl}${url}${paramsStr}`, {...options}); + // fileUtil.editFile(`${folderPath}/request.txt`, JSON.stringify(arrList)) + // writeLog({ + // time:dateFormat(new Date()), + // url, + // result:JSON.stringify(result), + // extraData: JSON.stringify(data), + // state:'end' + // }) + console.log('响应头地址' + JSON.stringify(result)) + let res:any = xml ? xmlToJson(result,url) : result; + console.log('响应头地址' + JSON.stringify(res)) - public async onJudgeFn(fn: Function) { - await this.judging(fn) - } - - //开始评判 - private async judging(callBack: Function) { - const {judgeUI} = this; - const { name, lsh, idCard,kssycs,manualMarkRules} = judgeUI; - const fileLog = new FileLog(judgeUI.context); - const filePath = await fileLog.initFileLogo({ - name, lsh, idCard - }); - this.fileLog = fileLog; - this.filePath = filePath; - - const {getJudgeBeginData,handleUdp,handDistance,fileUtil,handleTrajectoryUdp,isTrajectoryOpen,trajectoryPath,avPlayer} = this; - const isJudgeInitBool = globalThis.isJudgeInitBool; - let strArr = []; - if (isTrajectoryOpen) { - const folderPath = await this.fileUtil.initFolder(trajectoryPath); - const str = await fileUtil.readFile(folderPath) - strArr = str.split('\n') + let resObj = null; + if(typeof res === "string"){ + res=JSON.parse(res) } - //日志回调 - console.info(judgeTag, '1.进入评判入口') - await examJudgeSetLogCallback(3, async (level, info, len) => { - console.log('评判日志:' + info) - await fileLog.setExamJudgeLogData(info); - }) - - console.info(judgeTag, '2.注册日志回调完成') - - let initInfo = isTrajectoryOpen ? JSON.parse(strArr[0]) : await this.getJudgeInitData(); - await fileLog.setExamJudgeData(initInfo) - //相关评判初始化只做一次 - if (!isJudgeInitBool) { - const tempJudge = await examJudgeInit(initInfo); - globalThis.isJudgeInitBool = true - console.info(judgeTag, '4.评判初始化完成') + //处理中心服务code + if(res.Envelope){ + const msgXml = res.Envelope.Body.writeObjectOutResponse.return; + //Envelope.Body.writeObjectOutResponse.return + const dd = handleCenterCode(msgXml,isNewCenter); + httpRequest.destroy(); + return dd } - globalThis.isJudge = true - // 2.评判过程回调 - await examJudgeSetRealExamCallback(async (strData, len) => { - await fileLog.setExamJudgeCallbackData(strData) - console.info('评判回调数据', strData) - this.handleRealExam(strData, callBack) - }) - - await examJudgeSetPerformCallback(async (info) => { - console.info('评判实时数据', info) - const performInfo = JSON.parse(info) - this.performInfo = performInfo - const jl = Math.floor((performInfo.qjjl + performInfo.dcjl) / 100); - if(jl > this.judgeUI.examMileage){ - this.checkExamIsEnd() - } - this.judgeUI.jl = jl - //TODO 待优化 跨组件传值不生效 - globalThis.laneData = performInfo.lane; - }) - - // 3.开始考试 - let beginExamInfo = isTrajectoryOpen ? { - ...JSON.parse(strArr[1]), - replay: 1, - } : await getJudgeBeginData() - - await fileLog.setExamJudgeData(beginExamInfo) - await examJudgeBeginExam(beginExamInfo); - console.info(judgeTag, '6.开始考试注册完成') - avPlayer.playAudio([globalThis.singlePlay ? 'voice/ksks.wav' : 'voice/监管成功.mp3']) - - if(!globalThis.singlePlay){ - this.videoData = await saveStartRecordVideo(`${name}_${kssycs}`) - } - - const {examSubject,projectsObj} = this.judgeUI - // if(examSubject == 3){ - // //不做模拟灯光,需要做上车准备 =>(请上车准备) - // if(projectsObj[41]?.type == 3 && projectsObj[1]?.type != 3){ - // avPlayer.playAudio(['voice/上车准备.mp3']) - // } - // //不做模拟灯光,不做上车准备 =>(请起步,完成考试) - // if(projectsObj[41]?.type == 3 && projectsObj[1]?.type == 3){ - // avPlayer.playAudio(['voice/402001.mp3']) - // } - // } - - this.judgeUI.draw = true - // 处理轨迹plc信息 - if (isTrajectoryOpen) { - handleTrajectoryUdp(strArr); - return - } - // 处理实时udp里的plc信号 - // globalThis.udpClient.closeMessage_1(); - globalThis.udpClient.onMessage_1(async (msg) => { - console.info('socketTag[PLC.UdpClient]', '收到udp回调数据') - handleUdp(msg) - const udpIndex = globalThis.udpIndex; - if (udpIndex % 5 === 0) { - handDistance(); - } - }); - - // this.checkExamIsEnd() - - //监听远程结束考试 - globalThis.udpEvent.onEndExam(async ()=>{ - this.checkExamIsEnd(true); - }) - - console.info(judgeTag,JSON.stringify(manualMarkRules)) - //监听远程扣分 - globalThis.udpEvent.onKfExam(async (content)=>{ - console.info('评判收到远程扣分项目内容' + JSON.stringify(content)) - const { kfxh , directives } = content.data; - console.info(judgeTag ,'评判收到远程扣分项目内容,扣分序号:' + `kfxh=>${kfxh}; directives=>${directives}`) - //根据扣分序号找扣分代码 - const currentKf = manualMarkRules.filter(mark => mark.kfxh == kfxh)[0]; - console.info(judgeTag, '扣分项目:' + JSON.stringify(currentKf)) - this.setJudgeMark(currentKf.itemno, currentKf.markserial, 2); - globalThis.judgeUdp.confirmKf(directives , 1) - }) - - } - //实时计算gps经纬度距离 - handDistance= async ()=>{ - const {jd,wd,hxj,dwzt,jdzt} = this.tempData.gps; - const tJD = convertGpsCoord2(jd) - const tWD = convertGpsCoord2(wd) - const {prevJd,prevWd} = this - if(prevJd && dwzt == 4 && jdzt == 3){ - const distance = await examCalcGpsDistance({ - jd1:prevJd, - wd1:prevWd, - jd2:tJD, - wd2:tWD, - h:hxj || 1, - }) - //@ts-ignore - globalThis.distanceClass?.setTimeData(((distance / 100).toFixed(2)) * 1) - } - this.prevJd = tJD; - this.prevWd = tWD; - } - - // 获取评判初始化数据 - getJudgeInitData = async () => { - const {getModelData,getKm3JudgeInitConfig} = this - const carInfo = globalThis.carInfo; - const { examSubject,plateNo,carId } = carInfo; - const judgeUI = this.judgeUI - const {projectsObj,itemInfoObj,markRuleListObj,carType,carName,systemparmArr,carinfoArr} = judgeUI - const examType = examSubject == 2 ? 'km2' : 'km3' - - let allitems = []; - if (examSubject == 2) { - allitems = Reflect.ownKeys(itemInfoObj).map(cdsbKey => { - const cdsb = itemInfoObj[cdsbKey]; - const {xmdm,xmxh,modelKey} = cdsb - return { - xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`) - } - }) - } - //获取版本号 - const sdkver = await examJudgeVersion(); - const initInfo = { - sdkver, - appver:globalThis.version, - kskm: examSubject * 1, - kchp: plateNo, - kchm: carId * 1, - kscx: carType, - cxcode: '1', - name: carName, - carmodel: getModelData(`${examType}/${carType}.txt`), - allitems, - iteminfo: [], - systemparm: systemparmArr, - mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, - sysset: judgeUI.judgeConfig, - itemInfoObj, - carlist:judgeUI.carlist, - carinfo: carinfoArr, - }; - let km3Config = {} - - if (examSubject == 3) { - km3Config = await getKm3JudgeInitConfig(); - } - // 获取科目三的评判配置 - console.info(judgeTag, '3.获取评判初始化数据完成') - return { - ...initInfo, - ...km3Config, - } - } - - // 获取开始考试数据 - getJudgeBeginData = async () => { - const {code,name:examinerName} = globalThis.examinerInfo; - let currentParams: any = router.getParams(); - const {sczb,kfdm} = currentParams; - const {isExam} = this; - const judgeUI = this.judgeUI - const {projects,carType,kssycs,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr,passingScore} = judgeUI; - const beginInfo = { - kgid: '012', - kgxm: decodeURI(examinerName || ''), - exam: isExam ? 1 : 0, - //是否回放 - replay: 0, - //生成的轨迹文件 - track: '', - xm: judgeUI.name, - sex: 0, - kslsh: judgeUI.lsh, - sfzmhm: judgeUI.idCard, - ksyy: '', - kscx: carType, - kkcs: Number(kssycs) || 2 , - sfyk: 0, - ykkkcs: 1, - wayno: judgeUI.wayno * 1, - czlx: 0, - kskssj: await systemTime.getCurrentTime(), - passing:passingScore * 1, - ksxm: projects.map(project => { - return { - xmdm: project.projectCode * 1, - xmxh: '', - } - }), - //断点续考 - ddxk: isDdxk ? 1 : 0, - ddkssj: ddxkTime || 0, - ykxm: (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) || [], - kfxm: isDdxk ? (ddxkKfArr?.map(kf => { - const [xmdm, kfdm] = kf.split(',') - return {xmdm: xmdm * 1,kfdm} - })) : [], - //TODO 已考里程待修改 - yklc: 0, - special: [], - //TODO 科目三参数临时写死 - sczb: (sczb === undefined || sczb == 0) ? 0 : 1, - sczbkf: kfdm, - dmndg: false, - mfxx: false, - mfxxn: false - } - console.info(judgeTag, '5.获取开始考试数据完成') - return beginInfo - } - - //处理评判过程回调 - handleRealExam = async (strData, callBack) => { - let examData: EXAMDATA = JSON.parse(strData); - const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,avPlayer,fileLog,judgeUI} = this; - const {carzt,xmks,kf,event,xmjs,xmqx,ksjs,sound,mndg,lane,precast,nongps} = examData - const param512 = (judgeUI.judgeConfigObj['512'] || '').split(','); - //获取项目结束、项目开始代码 - const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm - const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; - const isManualProjectIn = this.artSubject3ProjectsCodesArr.includes(xmdm); - const {examSubject,projects,judgeConfigObj} = this.judgeUI; - const param611 = judgeConfigObj['611'] || ''; - switch (event) { - //项目开始 - case 1: - judgeUI.projectsObj[xmdm].type = '2'; - if (isManualProjectIn) { - //手动项目是否在进行中 - this.judgeUI.isManualProjectIn = true - } - if (xmdm == 41 && examSubject == 3) { - this.rmndg = 1 - } - this.judgeUI.currentXmdm = xmdm; - const xmmcStr = judgeUI.projectsObj[xmdm].name; - const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; - const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; - this.testKmItems[xmmcCode].status = 2; - this.xmmcStr = xmmcStr; - this.xmmcCode = xmmcCode; - this.xmmcSingleCode = xmmcSingleCode - this.xmmcEndCode = xmmcCode - this.xmdm = xmdm; - this.xmxh = xmxh; - this.judgeUI.isProjectIn = true - break; - - //项目结束 - case 2: { - const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; - judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3'); - //计算项目是否全部结束 - this.judgeUI.isProjectIn = (Reflect.ownKeys(judgeUI.projectsObj).filter( - projectKey => judgeUI.projectsObj[projectKey].type == '2').length - ) > 0; - if (isManualProjectIn) { - this.judgeUI.isManualProjectIn = false - } - this.testKmItems[xmmcCode].status = 3; - //统计必考项目数量 - this.xmmcStr = '无'; - this.xmmcCode = ''; - this.xmdm = ''; - this.judgeUI.currentXmdm = undefined; - break; - } - - //扣分 - case 3: - const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`) - //扣分信息 - this.kfArr.push({ - //扣分项目名称 - xmmcStr: getDqxmStr(kf.xmdm), - xmdm: kf.xmdm, - //扣分描述 - desc: thisKf.desc, - //扣分分数 - score: thisKf.score, - // 扣分无锡所代码 - markcatalog: thisKf.markcatalog, - markserial: thisKf.markserial, - kfxh: thisKf.kfxh, - //扣分类型 - type: kf.type - }) - this.judgeUI.totalScore += thisKf.score * 1; - if(kf.xmdm != 20){ - const type = judgeUI.projectsObj[kf.xmdm].type; - judgeUI.projectsObj[kf.xmdm].type = (type == 3 || type == 4) ? '4' : '5'; - } - break; - - //考车状态 - case 4: - this.carztStr = getCarStatus(carzt); - break; - - //考试结束 - case 5: - this.ksjs = ksjs; - await fileLog.setExamJudgeData({ - method: 'examJudgeEndExam', - }) - break; - - //项目取消 - case 6:{ - console.info(judgeTag,'项目取消'); - const {examSubject} = this.judgeUI - const xmdm = xmqx.xmdm; - const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; - const voiceCode = getKmProjectCancelVoice(examSubject,xmmcCode); - // avPlayer.playAudio([`voice/${voiceCode}.mp3`],true) - this.judgeUI.projectsObj[xmdm].type = '1'; - this.testKmItems[xmmcCode].status = '1'; - break; - } - - //语音播放和提示 - case 7: - goJudgeVoice(sound) - break; - - //模拟灯光事件 - case 8: - setMndg(mndg) - break; - - //车道和路段变化 - case 9: - this.judgeUI.lane = lane - this.lane = lane; - break; - - //预进项目事件 - case 10:{ - const param611 = judgeConfigObj['611'] || ''; - const [f,s] = param611.split('/') - const {xmdm,xmxh} = precast; - const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; - const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; - // if(examSubject == 2 && ((xmdm == 0 && f == 1) || (xmdm == 1 && s == 1) || xmdm == 3)){ - // //倒车入库/桩考/侧方停车 - // avPlayer.playAudio([`voice/${xmmcCode}.mp3`],false) - // } - this.testKmItems[xmmcCode].status = 2; - this.xmmcStr = xmmcStr; - this.xmmcCode = xmmcCode; - this.xmdm = xmdm; - this.xmxh = xmxh; - this.xmmcSingleCode = xmmcSingleCode; - judgeUI.projectsObj[xmdm].type = '2'; - } - break; - - //差分事件 - case 11:{ - const {type}= nongps - this.checkDwzt(type) - } - default: - break; - - } - - const {xmmcStr,carztStr,kfArr} = this; - - await callBack({ - //项目名称 考车状态 扣分arr - xmmcStr, carztStr, kfArr - }); - - //语音播报 - this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs, ksjs,xmxh) - //更新UI - if (event == 1 || event == 2 || event == 3 || event == 6) { - const copyProjectsObj = this.judgeUI.projectsObj; - judgeUI.projectsObj = deepClone(copyProjectsObj); - } - } - - // 更改考试状态 - goVoiceAnnounce = async (event, xmdm, kf, xmjs, ksjs,xmxh) => { - const { - beginProject, - pointsDedute, - endProject, - avPlayer, - uploadProgressPhoto, - judgeTask, - handEndExam, - judgeUI, - checkExamIsEnd, - checkProjectIsStart, - lane, - closeAllFiles - } = this; - - const {projectsObj,judgeConfigObj,examSubject,examMileage,jl,isAllProjectsEnd} = judgeUI; - const kfLen = kf.length; - //不报语音的项目列表 - const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') - const param611 = judgeConfigObj['611'] || ''; - const param512 = (judgeConfigObj['512'] || '').split(','); - const [f,s] = param611.split('/') - switch (event) { - // 项目开始 - case 1: - const code = projectsObj[xmdm].projectCodeCenter; - const isEnd = projectsObj[xmdm].isEnd; - const kmCode = getKmProjectVoice(code, 1, judgeConfigObj, lane,xmxh) - // if (!ignoreVoiceCodeArr.includes(code)) { - // if(examSubject == 2 && ((xmdm == 0 && f == 2) || (xmdm == 1 && s == 2) || xmdm == 3)){ - // //倒出入库、桩考\进项目语音控制 - // }else{ - // kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`],true) - // } - // } - setTimeout(()=>{if(param512[7] != 0){ - clearTimeout(this.deductedPopShowTimer) - this.judgeUI.isDeductedPopShow = true - }},200) - //项目已考不上传监管信息 - if (!isEnd) { - judgeTask.addTask(async () => { - console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`) - await beginProject(xmdm) - },{isDelay: true}) - judgeTask.addTask(async () => { - console.info(judgeTag, `项目-${xmdm}-上传照片 start`) - await uploadProgressPhoto(xmdm) - },{isDelay: true}) - this.judgeUI.projectsObj[xmdm].isUpload = true; - } - break; - - // 项目结束 - case 2:{ - const endCode = projectsObj[xmdm].projectCodeCenter; - const projectIsEnd = projectsObj[xmdm].isEnd; - const endKmCode = getKmProjectVoice(endCode, 2, judgeConfigObj, lane,xmxh) - // if (!ignoreVoiceCodeArr.includes(endCode) && examSubject == 3) { - // endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) - // } - const isStart = await checkProjectIsStart(xmdm,1); - if(isStart){ - //项目结束了就不再生成数据 - console.info(judgeTag + ' projectIsEnd =>',projectIsEnd) - if (!projectIsEnd) { - judgeTask.addTask(async () => { - console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`) - await endProject(xmdm); - this.xmmcSingleCode = 0; - this.xmmcEndCode = undefined; - }, {isDelay: true}) - } - } - if(!this.judgeUI.isProjectIn){ - this.deductedPopShowTimer = setTimeout(()=>{ - this.judgeUI.isDeductedPopShow = false - },(param512[5] || 0) * 1000) - } - judgeUI.projectsObj[xmdm].isEnd = true; - break; - } - - // 扣分 - case 3: - console.info('surenjun','扣分开始') - //扣分时实时播报语音(0-否+1-是) - const currentKf = kf[kfLen -1]; - if (judgeConfig.kfVoiceOpen ||(examSubject == 2 && judgeConfigObj['618'] == '1') || (examSubject== 3&& judgeConfigObj['418'] == '1') ) { - avPlayer.playAudio([`voice/${currentKf.markcatalog}.mp3`,`voice/mark_${Math.abs(currentKf.score)}.mp3`]) - } - const isStart = await checkProjectIsStart(currentKf.xmdm,2,currentKf); - if(isStart){ - await judgeTask.addTask(async () => { - console.info(judgeTag, `项目扣分-${currentKf.markcatalog}-${currentKf.desc}`) - await pointsDedute(currentKf.xmdm, currentKf) - }, {isDelay: true}) - } - break; - - // 考车状态 - case 4: - break - - // 考试结束 - case 5: - console.info(judgeTag, '考试结束') - //关闭录像 - if(!globalThis.singlePlay){ - await endRecordVideo(this.videoData) - } - judgeTask.addTask(async () => { - console.info(judgeTag, '考试结束 start') - globalThis.isJudge = false; - await handEndExam(ksjs) - }) - clearInterval(globalThis.judgeTimer) - break - default: - break - } - if (event == 2 || event == 3) { - setTimeout(() => { - this.judgeUI.kfArrScroller.scrollTo({ - yOffset: 999999, xOffset: 0 - }) - },500) - //统计必考项目完成数量 - await this.setCountItems(); - await checkExamIsEnd() - } - } - - // 检测扣分、结束项目时该项目是否开始 - checkProjectIsStart = async(xmdm,currentType:1|2,kf?:KF) => { - if(xmdm == 20){ - return true - } - const {judgeTask,beginProject,pointsDedute,uploadProgressPhoto,endProject,checkExamIsEnd,totalScore} = this; - const {projectsObj,passingScore:passingGrade} = this.judgeUI - const {isUpload} = projectsObj[xmdm]; - //如果项目没有开始 - console.info('surenjun isUpload=>',isUpload) - if(!isUpload){ - console.info(judgeTag,'项目补传开始') - //项目开始补传 - judgeTask.addTask(async ()=>{await beginProject(xmdm)},{isDelay:true}) - judgeTask.addTask(async ()=>{await uploadProgressPhoto(xmdm)},{isDelay:true}) - this.judgeUI.projectsObj[xmdm].isUpload = true; - //扣分补传 - if(currentType == 2){ - judgeTask.addTask(async ()=>{await pointsDedute(xmdm,kf)},{isDelay:true}) - } - //扣分补传判断是否合格 不合格补传项目结束 - if(currentType == 1 || (currentType == 2 && totalScore < passingGrade)){ - judgeTask.addTask(async ()=>{await endProject(xmdm)},{isDelay:true}) - this.judgeUI.projectsObj[xmdm].isEnd = true; - } - judgeTask.addTask(async ()=>{ - checkExamIsEnd() - }) - return false; - }else{ - return true - } - } - - // 项目开始接口同步 - beginProject = async (ksxm) => { - const carInfo = globalThis.carInfo; - const { examSubject,plateNo } = carInfo; - const {judgeUI,fileLog,getSbbm,xmxh,filePath} = this; - const {lsh,idCard,serialNumber,projectsObj,ksdd,kslx,xldm} = judgeUI - const time = await getCurrentTime(); - const project = projectsObj[ksxm] - const sbxh = getSbbm(ksxm, xmxh) - const data = { - //系统类别 接口序列号 接口标识 - xtlb: '17', jkxlh: serialNumber, jkid: '17C52', - drvexam: { - // 考试科目 身份证号码 - lsh, - kskm: examSubject, - sfzmhm: idCard, - ksxm: project.projectCodeCenter, - sbxh, - ksxl:xldm, - kchp: encodeURI(plateNo), - // 开始时间 - ksdd: encodeURI(ksdd), - kslx: encodeURI(kslx) || '', - kssj: time - } - } - const {code} = await this.sendWriteObjectOut(data,filePath) - console.info(judgeTag, '项目开始 end') - if (code === 2300007) { - this.isJudgeDisConnect = true; - } - promptWxCode('17C52', code) - } - - // 项目结束接口同步 - endProject = async (ksxm) => { - const carInfo = globalThis.carInfo; - const deviceNo = globalThis.deviceNo; - const { examSubject,plateNo,carNo } = carInfo; - const {judgeUI,fileLog,getSbxh,xmxh,getSbbm,filePath} = this; - const {lsh,idCard,serialNumber,projectsObj,cdsbInfoObj,ksdd,kslx,xldm,} = judgeUI - const time = await getCurrentTime(); - const project = projectsObj[ksxm] - const sbxh = examSubject == 3 ? undefined : getSbbm(ksxm, xmxh) - - const data = { - xtlb: '17', jkxlh: serialNumber, jkid: '17C55', - drvexam: { - lsh, - kskm: examSubject, - sfzmhm: idCard, - ksxm: project.projectCodeCenter, - sbxh, - //TODO 操作类型 1:正常 0:撤销该考试记录 - czlx: '1', - ksxl:xldm, - kchp: encodeURI(plateNo), - ksdd: encodeURI(ksdd), - kslx: encodeURI(kslx) || '', - jssj: time - } - } - const {code} = await this.sendWriteObjectOut(data,filePath) - if (code === 2300007) { - this.isJudgeDisConnect = true; - } - console.info(judgeTag, '项目结束 end') - promptWxCode('17C55', code) - } - - // 考试扣分 - pointsDedute = async (ksxm, kf) => { - const carInfo = globalThis.carInfo; - const deviceNo = globalThis.deviceNo; - const { examSubject,plateNo,carNo } = carInfo; - const {judgeUI,getProjectInfo,fileLog,xmmcSingleCode,xmmcEndCode,filePath} = this; - const {lsh,idCard,serialNumber,ksdd,projectsObj} = judgeUI - const time = await getCurrentTime(); - const project = getProjectInfo(ksxm); - //科目三夜间行驶.模拟灯光、上车准备出现通用评判,ksxm为当前进行的项目 - const checkProjects = ['17', '41', '1']; - //获取正在进行的项目 - const inProjects = Reflect.ownKeys(projectsObj).filter(projectKey => projectsObj[projectKey].type == 2); - - let commonKsxm = ''; - checkProjects.forEach(projectCode=>{ - if(inProjects.includes(projectCode)){ - commonKsxm = projectCode - } - }) - - const data = { - xtlb: '17', jkxlh: serialNumber, jkid: '17C53', - drvexam: { - lsh, - kskm: examSubject, - ksxm: project == undefined - ? (commonKsxm - ? (projectsObj[commonKsxm].projectCodeCenter) - : (examSubject == 3 ? 30000 : (xmmcEndCode == undefined ? 10000 : xmmcEndCode))) - : project.projectCodeCenter , - kfxm: kf.markcatalog, - kfxmmx: `${ksxm},${kf.markserial}`, - sfzmhm: idCard, - kchp: encodeURI(carInfo.plateNo), - //扣分方式 - kffs: kf.type == 0 ? 1 : 2, - ksdd: encodeURI(ksdd), - kfsj: time - } - } - console.info(judgeTag + 'ksxm=>',data.drvexam.ksxm) - - const {code} = await this.sendWriteObjectOut(data,filePath); - if (code == 2300007) { - this.isJudgeDisConnect = true - } - console.info(judgeTag, '项目扣分 end') - promptWxCode('17C53', code) - } - - //调用监管接口 - sendWriteObjectOut = async (data,filePath)=>{ - const temp = await writeObjectOut(data,filePath); - //断网&网络超时次数计算 - if(temp.code == 2300007 || temp.code == 2300008){ - this.disConnectNum += 1; - if(this.disConnectNum < 5){ - return await this.sendWriteObjectOut(data,filePath) - } - } - - if(this.disConnectNum >= 5){ - console.info('surenjun','123') - this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!'; - this.judgeUI.disConnectErrorOpen = true - } - - this.disConnectNum= 0 - return temp - } - - // 考试过程照片 - uploadProgressPhoto = async (ksxm) => { - const time = await getCurrentTime(); - const {judgeUI,plcData,getPhoto,fileLog,filePath} = this; - const photoBase64 = await getPhoto(); - const carInfo = globalThis.carInfo; - const { examSubject,plateNo,carNo } = carInfo; - const {lsh,idCard,serialNumber,projectsObj,ksdd,judgeConfigObj} = judgeUI; - const {sensor,gps} = plcData - const project = projectsObj[ksxm] - - const data = { - xtlb: '17', jkxlh: serialNumber, jkid: '17C54', - drvexam: { - lsh, - kskm: examSubject, - ksxm: project.projectCodeCenter, - sfzmhm: idCard, - kchp: encodeURI(plateNo), - zpsj: time, - //@ts-ignore - zp: photoBase64, - cs: Math.floor((judgeConfigObj['350'] == 0?gps.sd:sensor.cs) * 1.852), - ksdd: encodeURI(ksdd) - } - }; - const {code} = await this.sendWriteObjectOut(data,filePath); - if (code === 2300007) { - this.isJudgeDisConnect = true - } - promptWxCode('17C54', code) - console.info(judgeTag, '上传照片 end') - } - - // 评判语音提示 - goJudgeVoice = async (sound: SOUND) => { - const {avPlayer,fileLog} = this; - const {xmdm,code,type} = sound; - console.info('surenjun code=>',JSON.stringify(code)) - //判断是不是模拟灯光语音 - if (type == 1) { - avPlayer.playAudio([`voice/${code[0]}.mp3`], false, () => { - examJudgeSoundEnd({ - itemno: xmdm, code:code[0], type - }) - fileLog.setExamJudgeData({ - method: 'examJudgeSoundEnd', - itemno: xmdm, - code:code[0], - type, - }) - }) - }else{ - avPlayer.playAudio([`voice/${code[0]}.mp3`]) - } - } - - // 校验考试是否结束 - checkExamIsEnd = - async (isManual?: boolean) => { - const {judgeUI,avPlayer,isExamEnd,isEndTip,ksjs} = this; - const {isAllProjectsEnd,examSubject,singlePlay,totalScore,judgeConfigObj,passingScore,examMileage,jl} = judgeUI; - - if (isExamEnd) { - return - } - //及格分 - let passingGrade = passingScore - if (isManual) { - // 考试不合格 - await examJudgeEndExam() - this.isExamEnd = true - this.isManual = true - } else { - const param302 = judgeConfigObj['302']; - const param342 = judgeConfigObj['342']; - const param512 = (judgeConfigObj['512'] || '').split(','); - - //单机模式 - if (singlePlay) { - console.info(judgeTag + ' isAllProjectsEnd => ',isAllProjectsEnd) - if (isAllProjectsEnd && jl >= examMileage) { - //成绩合格 - if(totalScore >= passingGrade && !isEndTip) { - if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) { - if(param512[7] != 0){ - clearTimeout(this.deductedPopShowTimer) - avPlayer.playAudio(['voice/综合评判.mp3']) - this.judgeUI.isDeductedPopShow = true - this.judgeUI.defaultTabIndex = 1 - this.isEndTip = true - return - } - } else { - await examJudgeEndExam() - this.isExamEnd = true - return - } - }else{ - if(examSubject == 3 && (param302 == 4 || param302 == 5 || param302 == 7 || param302 == 8)){ - await examJudgeEndExam() - this.isExamEnd = true - return - } - } - await examJudgeEndExam() - this.isExamEnd = true - } - } else { - //成绩不合格 - if (totalScore < passingGrade) { - //科目三不合格报靠边停车 - if(examSubject == 3 && param302 ==1){ - avPlayer.playAudio([`voice/考试结束.mp3`]); - return - } - await examJudgeEndExam() - this.isExamEnd = true - return - } - - //成绩合格 - if (isAllProjectsEnd && totalScore >= passingGrade && !isEndTip) { - if(examSubject == 2){ - await examJudgeEndExam() - this.isExamEnd = true - return - } - - //考试里程判断 - if(examSubject == 3 && jl < examMileage){ - return - } - - //考试合格自动退出 - if(examSubject == 3 && (param302 == 4 || param302 == 7) || param302 == 8){ - await examJudgeEndExam() - this.isExamEnd = true - return - } - - if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) { - if(param512[7] != 0){ - clearTimeout(this.deductedPopShowTimer) - this.judgeUI.isDeductedPopShow = false - avPlayer.playAudio(['voice/综合评判.mp3']) - this.judgeUI.isDeductedPopShow = true - this.judgeUI.defaultTabIndex = 1 - this.isEndTip = true - } - } else { - await examJudgeEndExam() - this.isExamEnd = true - } - } - } - } - } - - // 处理考试结束 - public handEndExam = async (ksjs: KSJS) => { - this.judgeUI.loadingPopupVisible = true; - this.judgeUI.endPopupVisible = false; - this.judgeUI.isDeductedPopShow = false; - const {qjjl,dcjl} = ksjs - const {judgeUI,endExam,handleSEP,kfArr,avPlayer,judgeTask,isManual,closeAllFiles} = this; - const {judgeConfigObj,examSubject,isAllProjectsEnd,totalScore,passingScore} = judgeUI; - //计算考试分数 - // this.judgeUI.totalScore = isAllProjectsEnd ? totalScore : 0; - const singlePlay = globalThis.singlePlay - const param302 = judgeConfigObj['302']; - // globalThis.windowClass.setWindowSystemBarEnable(['navigation']) - - //自动退出待验证并且不合格 - if (!isManual && examSubject == 3 && (param302 == 1 || (singlePlay && param302 == 2)) && totalScore < passingScore) { - avPlayer.playAudio([`voice/考试结束.mp3`]) - } - //联网模式下手动结束的直接退出 - if (!singlePlay && isManual && !isAllProjectsEnd) { - avPlayer.playAudio(['voice/empty.mp3'], true, () => { - this.isUdpEnd = true; - closeAllFiles() - router.back(); - }) - return - } - if (examSubject == 3) { - const param302 = judgeConfigObj['302']; - if (totalScore < passingScore) { - //考试不合格;考试模式,自动退出; - if (param302 == 4 || param302 == 5 || param302 == 7 || param302 == 8) { - - } - } else { - //考试合格 - } - } - await handleSEP(306); - avPlayer.playAudio(['voice/exam_waiting.mp3'], globalThis.singlePlay, async () => { - try { - if (!singlePlay) { - const bytes = await this.getMessageHeartbeat(true); - globalThis.judgeUdp.send(bytes) - } - await endExam() - } catch (e) { - console.info(judgeTag,JSON.stringify(e)) - // setTimeout(() => { - // // avPlayer.avPlayerStop(); - // router.back(); - // }, 3000) - } - }); - - } - - // 考试结束 - public endExam = async (isManual?: Boolean) => { - const carInfo = globalThis.carInfo; - const singlePlay = globalThis.singlePlay - const { examSubject ,plateNo} = carInfo; - const {judgeUI,ksjs,getPhoto,uploadProgressData,uploadDisConnectData,avPlayer,kfArr,judgeTask,filePath,closeAllFiles} = this; - const {lsh,idCard,serialNumber,kssycs,totalScore,judgeConfigObj,isAllProjectsEnd,passingScore} = judgeUI - //TODO 断网考试结束补传 - // await uploadDisConnectData(); - const time = await getCurrentTime(); - const photoBase64 = await getPhoto(); - const {d1,d2,d3,d4,d5} = ksjs - const data = { - xtlb: '17', jkxlh: serialNumber, jkid: '17C56', - drvexam: { - lsh, - kchp: encodeURI(plateNo), - kskm: examSubject, - sfzmhm: idCard, - //@ts-ignore - zp: photoBase64, - jssj: time, - kscj: (totalScore * 1) > 0 ? totalScore : 0, - kslc: Math.ceil(((ksjs?.qjjl + ksjs?.dcjl) || 0) / 100), - // 1,22;2,560;3,128;4,0;5,0; - dwlc: [d1,d2,d3,d4,d5].map((d,index) => `${index+1},${Math.floor(d /100)}`).join(';'), - } - } - const {code,keystr,message} = await this.sendWriteObjectOut(data,filePath) ; - promptWxCode('17C56', code) - - if(code != 1){ - avPlayer.playAudio(['voice/监管失败.mp3']) - this.judgeUI.errorMsg = decodeURIComponent(message) - - if(code == 2300028 || code == 2300027){ - this.judgeUI.errorMsg = '当前的考试过程信息监管审核未通过,程序将退出!' - } - this.isUdpEnd = true; - closeAllFiles() - this.judgeUI.loadingPopupVisible = false; - return - } - - console.info(judgeTag, '考试结束 end') - const param302 = judgeConfigObj['302']; - judgeUI.loadingPopupVisible = true; - - let currentKssycs =0; - let voiceURL = '' - if (examSubject == 2) { - if (isAllProjectsEnd) { - voiceURL = (totalScore < passingScore ? `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav` : 'voice/qualified.mp3') + if(!xml){ + if(res.head.resultCode === '0'){ + return res }else{ - voiceURL = `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav` - currentKssycs = kssycs == 1 ? 0 : 1 - } - switch (voiceURL){ - case 'voice/unqualified_one.wav': - currentKssycs = 0; - break; - - case 'voice/unqualified_two.wav': - currentKssycs = 1; - break; - - case 'voice/qualified.mp3': - currentKssycs = 0; - break; + const resultMessage = res?.body?.resultMessage || res?.head?.resultMessage + prompt.showToast({ + message: decodeURIComponent(resultMessage), + duration: 3000 + }); + return false } } - if (examSubject == 3) { - if (isAllProjectsEnd) { - if (totalScore < passingScore) { - voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3` - currentKssycs = kssycs == 1 ? 0 : 1 - } else { - voiceURL = 'voice/exam_pass.mp3' - currentKssycs = 0 - } - } else { - voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3` - currentKssycs = kssycs == 1 ? 0 : 1 - } - switch (voiceURL){ - case 'voice/exam_no_pass_finish.mp3': - currentKssycs = 0; - break; + for( let i in res ) { + resObj = res[i].head + } + console.info('jiangsong:res in request' + url + JSON.stringify(resObj)) + if(resObj.resultCode === '0') { + httpRequest.destroy(); + return res + }else { + prompt.showToast({ + message: decodeURIComponent(resObj.resultMessage), + duration: 3000 + }); + httpRequest.destroy(); + return res + } + } catch (e) { + console.info('test-error' + url + ' error:resp: '+ JSON.stringify(e)) + if(!e||!(e?.message)){ + httpRequest.destroy(); + return {code:-1} + } + const code = e?.code; + prompt.showToast({ + message: e?.message, + duration: 5000 + }); + httpRequest.destroy(); + switch (code){ + //断网 + case 2300007: return {code:2300007} + // 超时 + case 2300028: return {code:2300028} + default: + } + return {code:e.code} + } - case 'voice/exam_no_pass.mp3': - currentKssycs = 1; - break; +} +async function writeLog(param){ + const fileUtil = new FileUtil(globalThis.context) + const folderPath = await fileUtil.initFolder(`/errorMsg/`); + fileUtil.editFile(`${folderPath}/request.txt`, JSON.stringify(param)+`\n`) - case 'voice/exam_pass.mp3': - currentKssycs = 0; - break; +} + +//xml格式转JSON +function xmlToJson(result,url) { + console.log("xmlToJson begin",url); + let xmlOptions = {trim : false, declarationKey:"_declaration", + instructionKey : "_instruction", attributesKey : "_attributes", + textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", + commentKey : "_comment", parentKey : "_parent", typeKey : "_type", + nameKey : "_name", elementsKey : "_elements", "skipPreprocess" : true} + + let strXml = result.toString(); + let conv = new convertxml.ConvertXML(); + + console.log("xmlToJson result.length = " + result.length); + console.log("xmlToJson result content = " + result); + // @ts-ignore + let {_elements:xmlArr} = conv.convertToJSObject(strXml, xmlOptions); + console.log("xmlToJson deeml begin"); + let res = deeml(xmlArr); + console.log("xmlToJson end",url); + return res +} + +//处理中心服务code +function handleCenterCode(msgXml,isNewCenter){ + //新监管 + if(isNewCenter){ + const msg = JSON.parse(msgXml); + const result = msg?.data[0]?.result; + if(result){ + const {code,message,retval} = result + if(code != '1'){ + const rMessage = decodeURIComponent(message as string) + // globalThis.title=rMessage + // globalThis.type='1' + // globalThis.errorDialog.open() + prompt.showToast({ + message:rMessage, + duration: 3000 + }); + return {code,message} + }else{ + return { code ,keystr:retval} } } - - const USER = await getSyncData('USER'); - await upDateTableByArray('USER', [{ - ...USER[0], - kssycs:currentKssycs - }]) - - console.info(judgeTag, `考试成绩:${totalScore}`) - if(!singlePlay){ - await uploadProgressData(); - } - //语音播放扣分项 - let score = 0; - //结束考试时候是否播报一遍所有扣分 - const param634 = judgeConfigObj['634']; - if (kfArr.length && ((examSubject == 2 && param634 == 1) || examSubject == 3)) { - avPlayer.playAudio([`voice/kfdesc.mp3`], false, () => { - try { - kfArr.forEach((kf, index) => { - score += Math.abs(Number(kf.score)); - //TODO 考试分数待替换 - if (score <= (examSubject == 3 ? 10 : 20)) { - if (kfArr.length - 1 === index) { - avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`, voiceURL], false, () => { - this.isUdpEnd = true; - closeAllFiles() - router.back(); - }) - throw new Error('End Loop') - } - avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`]) - } else { - avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`, voiceURL], false, () => { - this.isUdpEnd = true; - closeAllFiles() - router.back(); - }) - throw new Error('End Loop') - } - }) - } catch (e) { - console.info(judgeTag,JSON.stringify(e)) - } - }) - } else { - avPlayer.playAudio([voiceURL], true, () => { - setTimeout(() => { - this.isUdpEnd = true - closeAllFiles() - router.back(); - }, param302 == 8 ? 3000 : 0) - }) - } } - // 当前项目转换 - getDqxmStr = (type) => { - const projectsObj = this.judgeUI.projectsObj - return projectsObj[type]?.abbreviation || '通用评判' - } + //正则匹配code message字段 + const [code,message,keystr] = [/(.*)<\/code>/i,/(.*)<\/message>/i,/(.*)<\/keystr>/i].map(pattern=>{ + const patternArr = pattern.exec(msgXml); + return patternArr && patternArr[1] + }); - // 扣分项目转换 - getKfStr = (code) => { - const markRuleListObj = this.judgeUI.markRuleListObj; - const thisMark = markRuleListObj[code] - return { - desc: thisMark.markshow, - score: thisMark.markreal, - markcatalog: thisMark.markcatalog, - markserial: thisMark.markserial, - kfxh: thisMark.kfxh - } + if(code != '1'){ + prompt.showToast({ + message: decodeURIComponent(message as string), + duration: 3000 + }); + // globalThis.type='1' + // globalThis.title=decodeURIComponent(message as string) + // globalThis.errorDialog.open() + return {code,message:decodeURIComponent(message)} + }else{ + return { code ,keystr, message } } - // 消息心跳发送 - getMessageHeartbeat = async (isEnd?: Boolean) => { - const carInfo = globalThis.carInfo; - const { examSubject,plateNo,ksyh } = carInfo; - const { - judgeUI, - isExam, - serialIndex, - tempData, - xmmcCode, - xmxh, - xmmcSingleCode, - xmdm, - performInfo, - kfArr, - getTranslateProject, - getSbxh, - fileLog, - } = this; - const singlePlay = globalThis.singlePlay - const {lsh,startHourTime,totalScore,examTime,judgeConfigObj} = judgeUI; - const {fourInOneScreen:{gpsDigit}} = judgeConfig - const examType = examSubject == 2?2:3 - const {sensor,gps} = tempData; - if(tempData.sensor === undefined){ - return - } - const {zfxd,yfxd,shtd,ygd,jgd,skd,dh1,dh2,lhq,jsc,ssc,fsc,lb,mkg,aqd,ygq,cs,fdjzs,dw} = sensor - const {jd,wd, hxj, fyj, hbg,sd} = gps; +} - //过滤错误数据 - if(jd == 0){ - return - } - const translateProject = getTranslateProject(); - const sbxh = getSbxh(xmdm, xmxh) - const {carzt,dcjl,qjjl,dxjl,bxjl} = performInfo || {}; - const asclshArr = stringToASC( - fillZero((singlePlay ? (examSubject == 2 ? '0000000000000':'1111111111111') : lsh) || 0, 13) - ); - //13不足要补0 - const ascksyhArr = stringToASC(fillZero(ksyh || 0, 13)) - const ascsbxhArr = stringToASC(sbxh) - const translateSignals = getTranslateSignals( - [zfxd, yfxd, shtd, ygd, jgd, skd, dh1, dh2, lhq, jsc, ssc, fsc, lb, mkg, aqd].concat(getDwStatusType(dw)).concat(getCarStatusType(carzt)).concat([ygq, sensor.wd, 0]) - ) - //@ts-ignore - const translateJd = convertGpsCoord2(wd).toFixed(gpsDigit) * Math.pow(10, gpsDigit); - //@ts-ignore - const translateWd = convertGpsCoord2(jd).toFixed(gpsDigit) * Math.pow(10, gpsDigit) - //@ts-ignore - const translateProjects = translateProject.map(numStr => string2Bytes(parseInt(numStr, 2), 8)[0]) +//JSON转xml格式 +const deeml = (elements,_name?)=>{ + const json = {} - //@ts-ignore - let tempSd = ((judgeConfigObj['350'] ==0 ? sd : cs) * 1.852).toFixed(0) * 1 - if(tempSd < 1){ - tempSd = 0 - } - - const arr = [ - //考生号 - asclshArr.map(lsh => string2Bytes(lsh, 8)[0]), - //考试员号 - ascksyhArr.map(ksyh => string2Bytes(ksyh, 8)[0]), - //科目类型(0:未考试 1:科目二 2:科目三) + 考试开始时间 - string2Bytes(`${examType}${globalThis.startHourTime || startHourTime}`, 4 * 8), - // TODO 消息序号从1开始,0结束 - string2Bytes(isEnd ? 0 : serialIndex, 2 * 8), - /*左向灯 右向灯 双跳灯 远光灯 近光灯 视宽灯 点火1 点火2 离合器 脚刹 手刹 副刹 喇叭 门开关 安全带 档位 车辆状态 雨刮器 雾灯 0*/ - translateSignals, - //速度 发动机转速 GPS纬度 GPS经度 主天线位置 - //@ts-ignore - string2Bytes(tempSd * 100, 2 * 8), string2Bytes(fdjzs / 100, 8), string2Bytes(translateJd, 4 * 8), string2Bytes(translateWd, 4 * 8), string2Bytes(1, 8), - //GPS东向距离 - string2Bytes(dxjl < 0 ? (dxjl + 4294967296) : dxjl, 4 * 8), - //GPS北向距离 - string2Bytes(bxjl < 0 ? (bxjl + 4294967296) : bxjl, 4 * 8), - //航向角 俯仰角 高程(海拔) - string2Bytes((hxj) * 100, 2 * 8), string2Bytes(fyj * 100, 2 * 8), string2Bytes(hbg * 100, 4 * 8), - //项目状态 parseInt('01010010',2) 二进制转成10进制 - translateProjects, - //当前项目编号 - string2Bytes(xmmcSingleCode ? (xmmcSingleCode * 1 + 1) : 0, 8), - //场地设备编号 - ascsbxhArr.map(sbxh => string2Bytes(sbxh, 8)[0]), - //本次考试行驶距离 - string2Bytes(Math.floor((dcjl + qjjl) / 100), 2 * 8), - //扣分 - string2Bytes(100 - Math.abs(totalScore), 2 * 8), - //扣分项数量 - string2Bytes(kfArr.length, 8), - //n个扣分序号 - kfArr.map(kf => string2Bytes(kf.kfxh, 8)[0]), - //TODO 牵引车第二gps精度、纬度 - string2Bytes(0, 4 * 8), string2Bytes(0, 4 * 8), - //TODO 牵引车第二航向角 - string2Bytes(0, 2 * 8), - //TODO 摩托压线 Byte[20], - string2Bytes(0, 20 * 8), - //考试用时 - string2Bytes(examTime, 4 * 8), - //TODO 项目用时 - string2Bytes(fillZero(0,2), 2 * 8), - //TODO 设备信号状态 - string2Bytes(0, 4 * 8), - ] - - let tempArr = []; - arr.forEach(itemArr => { - tempArr = tempArr.concat(itemArr) - }) - this.serialIndex += 1; - fileLog.setFourAndOneLogData(`${lsh},${ksyh},${examType}${globalThis.startHourTime || startHourTime},`); - fileLog.setFourAndOneLogDataBytes(tempArr.toString()); - return Array2Byte(tempArr) - } - //获取场地序号 - getSbxh = (ksxm, xmxh) => { - const {judgeUI} = this; - const {cdsbInfoObj,projectsObj} = judgeUI; - const project = projectsObj[ksxm] - if(project == 3){ - return '0000000000' - } - if (project === undefined) { - return '0000000000' - } - const projectType = project.sbxh; - const projectKey = `${ksxm}_${xmxh}`; - const currentCdsb = cdsbInfoObj[projectKey] || {}; - const sbxh = currentCdsb.sbbh || '0000000000' - return sbxh - } - - getSbbm = (ksxm, xmxh) => { - const {judgeUI} = this; - const {cdsbInfoObj,projectsObj,examSubject} = judgeUI; - const project = projectsObj[ksxm] - //科目三不需要 - if(examSubject == 3){ - return undefined - } - if (project === undefined) { - return '00000000' - } - const projectKey = `${ksxm}_${xmxh}`; - const currentCdsb = cdsbInfoObj[projectKey] || {}; - const sbxh = currentCdsb.sbbm || '00000000' - return sbxh - } - // 中心所有项目转换 - getTranslateProject = () => { - const {examSubject} = this.judgeUI; - const tempItems = (examSubject == 2 ? testKm2Items:testKm3Items).map(item => { - const current = this.testKmItems[item.code]; - return { - code: item.code, - status: getCenterProjectStatus(current.status) - } - }) - - const arr = []; - for (let i = 0; i <= 4; i++) { - const temp = tempItems.slice(i * 4, (i + 1) * 4); - let tempArr = temp.map(item => item.status) - if (i === 4) { - tempArr = examSubject == 2 - //bit36-bit39保留 - ? tempArr.concat(['00', '00']) - //bit30-bit39保留 - : tempArr.concat(['00', '00','00']) - } - // if (i === 3 && examSubject == 3) { - // tempArr = tempArr.concat(['00']) - // } - - arr.push(tempArr.join('')); - } - return arr - } - // 获取考试项目详情 - getProjectInfo = (projectCode) => { - const judgeUI = this.judgeUI; - return judgeUI.projectsObj[projectCode] - } - // 获取模型数据 - getModelData = (modelName) => { - const modelPath = this.modelPath - const fileModel = this.fileModel; - const modelData = fileModel.getModelContent(modelPath, modelName); - return modelData - } - // 过程照片拍照 - getPhoto = async (empty?: boolean) => { - const singlePlay = globalThis.singlePlay - //单机模式返回空照片 - if (singlePlay) { - return '' - } else { - const {filePhoto} = this; - const photoBase64 = await filePhoto.getPhoto(); - console.info(judgeTag, '拍照完成') - return photoBase64 - } - } - //人工操作项目 - public setJudgeItem = async (itemno, type: 1 | 2) => { - const {fileLog} = this; - await examJudgeArtificialItem(itemno * 1, type); - await fileLog.setExamJudgeData({ - method: 'examJudgeArtificialItem', - itemno: itemno * 1, - type - }) - console.info(judgeTag, `人工评判${type == 1 ? '进入' : '取消'}项目-${itemno}`) - } - - //人工扣分 - public setJudgeMark = async (itemno, serial, type = 1) => { - const {fileLog} = this - await examJudgeArtificialMark(itemno * 1, serial, type); - console.info(judgeTag, `进入人工扣分-${itemno}-${serial}`) - await fileLog.setExamJudgeData({ - method: 'examJudgeArtificialMark', - itemno: itemno * 1, - serial, - type - }) - - console.info(judgeTag, `人工扣分-${itemno}-${serial}`) - } - // 断网数据补传 - uploadDisConnectData = async () => { - const {isJudgeDisConnect,fileLog,fileUtil} = this; - if (!isJudgeDisConnect) { - return - } - const folderPath = fileLog.folderPath - const examDataStr = await fileUtil.readFile(`${folderPath}/wuxi_dis_progress_data.txt`); - const examDataArr = examDataStr.split('\n'); - for (let examDataStr of examDataArr) { - const examData = JSON.parse(examDataStr) - const code = await writeObjectOut(examData); - } - } - //上传无锡所过程数据 - uploadProgressData = async () => { - const {judgeUI,fileUtil,fileLog} = this; - const {idCard,startFullTime} = judgeUI - const carInfo = globalThis.carInfo; - const {carId,examinationRoomId} = carInfo - const folderPath = fileLog.folderPath - const base64 = new util.Base64(); - const time = await getCurrentTime(); - const endTime = await getCurrentTime(1) - let examDataBase64 - //@ts-ignore - //TODO try catch报错待优化 - const examDataStr: string = await fileUtil.readFile(`${folderPath}/wuxi_progress_data.txt`); - try { - let tempBuff = buffer.alloc(examDataStr.length, examDataStr) - let examData: Uint8Array = new Uint8Array(tempBuff.buffer) - examDataBase64 = base64.encodeToStringSync(examData) - } catch (e) { - console.info(judgeTag, JSON.stringify(e)) - } - console.info(judgeTag, '过程数据文件上传 start') - await uploadExamProgressData({ - time, - carId, - examinationRoomId, - examData: examDataBase64, - type: 1, - cardNo: idCard, - examStartTime: startFullTime, - examEndTime: endTime, - }) - console.info(judgeTag, '过程数据文件上传 end') - } - //获取科目三的评判初始化配置 - getKm3JudgeInitConfig = async () => { - const {judgeUI,getModelData} = this; - const {mapPointArr,mapPointItemArr} = judgeUI; - return { - map_point: mapPointArr, - map_point_item: mapPointItemArr, - //科目三暂时为空 - iteminfo: [], - roads: getModelData('km3/Roads.txt'), - sharps: getModelData('km3/Sharps.txt') - } - } - // 处理udp plc信号 - handleUdp = async (msg) => { - console.info('plc信号', msg) - const {fileLog,getPlcData,usbService,isUdpEnd,isExamEnd,judgeUI} = this - const stachArr = msg.split(',') - if (stachArr[0] != '#DN_GD' || isUdpEnd) { - return - } - const plcData = await getPlcData(msg); - // 4.过程数据 - await fileLog.setExamJudgeData(plcData) - //检测到有无锡所设备接入,需要发送特定的数据,供检测 - if (usbService.isWXUSBDevice) { - const str = await senorToWXDataStr(msg); - usbService.sendUSB(str) - } - // this.judgeUI.isDwztRight = (plcData.gps.dwzt == 4 && plcData.gps.jdzt == 3); - const param350 = judgeUI.judgeConfigObj['350'] - //@ts-ignore - this.judgeUI.sd = ((param350 == 0? plcData.gps.sd :plcData.sensor.cs) as number * 1.852).toFixed(0) + '' - this.judgeUI.dw = (Math.floor(plcData.sensor.dw as number) || 0) + '' - //TODO 暂时关闭差分检测异常 - // await this.checkDwzt(plcData.gps.dwzt,plcData.gps.jdzt); - if(!isExamEnd){ - await examJudgeRealExam(plcData) - } - const udpIndex = globalThis.udpIndex; - let [prevJd,preWd] = [0,0] - if (udpIndex % 5 === 0 && !isUdpEnd) { - const judgeUdp = globalThis.judgeUdp - const bytes = await this.getMessageHeartbeat(isExamEnd); - judgeUdp.send(bytes) - } - globalThis.udpIndex += 1 - } - // 处理特殊参数配置 - handleSEP = async (code: number) => { - const {judgeUI:{ - judgeConfigObj - },avPlayer} = this; - const {examSubject} = globalThis.carInfo; - - switch (code) { - //结束考试方式 - case 306: - if (judgeConfigObj[code] == 5) { - //靠边停车 - avPlayer.playAudio(['voice/406001.mp3']) - } - break; - } - } - // 获取plc数据 - getPlcData = async (plc: string) => { - const {fileLog,mndgStr,rmndg} = this; - await fileLog.setPlcProgressData(plc) - //plc字符串转化成评判初始化数据 - const tempData = await plcStrToJson(plc); - //模拟灯光回放时刻 - tempData.sensor.rmndg = rmndg; - //模拟灯灯光灯光项目 - tempData.sensor.mndg = mndgStr; - //plc字符串转化成无锡所过程数据 - const wuXiDataStr = await plcStrToWXJson(plc) - this.plcData = tempData - await fileLog.setExamJudgeWuxiProgressData(wuXiDataStr) - this.tempData = tempData - this.plcStr = plc; - this.mndgStr = ''; - this.rmndg = 0; - globalThis.msgStr = plc - - return tempData - } - - // 处理轨迹plc信号 - handleTrajectoryUdp = async (strArr) => { - const {fileLog,setJudgeItem,setJudgeMark,endExam} = this; - let num = 2; - const judgeTimer = setInterval(async () => { - const msgStr = strArr[num]; - if(msgStr == ''){ - console.info(judgeTag, '模拟数据考试结束') - globalThis.windowClass.setWindowSystemBarEnable(['navigation']) - clearInterval(judgeTimer) - this.checkExamIsEnd(true) + elements.map(ele =>{ + const _elements = ele._elements + if(ele._type === 'element'){ + if(_elements==undefined){ return } - const msg = JSON.parse(strArr[num]); - num++ - // 4.过程数据 - this.tempData = msg - this.judgeUI.isDwztRight = (msg?.gps?.dwzt == 4 && msg?.gps?.jdzt == 3); - this.judgeUI.sd = Math.floor(msg?.gps?.sd * 1.852) + ''; - this.judgeUI.dw = Math.floor(msg?.sensor?.dw) + '' - this.plcData = msg - // this.judgeUI.isDwztRight = msg.gps.dwzt == 4; - globalThis.msgStr = '' - if (msg.method === 'examJudgeArtificialItem') { - setJudgeItem(msg.itemno, msg.type) - } - if (msg.method === 'examJudgeArtificialMark') { - setJudgeItem(msg.itemno, msg.serial) - } - await examJudgeRealExam(msg) - const bytes = await this.getMessageHeartbeat(); - bytes && globalThis.judgeUdp.send(bytes) - - }, 200) - - globalThis.judgeTimer = judgeTimer; - } - // 统计必考项目、所有项目、已考数量 - setCountItems = async () => { - const carInfo = globalThis.carInfo; - const { examSubject} = carInfo; - const {projectsObj} = this.judgeUI; - //必考项目数量 必考项目已考数量 - let projectNum = 0, endProjectsNum = 0; - // 所有考试项目数量 项目已考项目数量 - let allProjectNum = 0, allEndProjectsNum = 0; - Reflect.ownKeys(projectsObj).forEach(projectKey => { - const {type,isRequired} = projectsObj[projectKey]; - allProjectNum += 1; - if (type == 3 || type == 4) { - allEndProjectsNum += 1; - } - - if (isRequired) { - projectNum += 1; - if (type == 3 || type == 4) { - endProjectsNum += 1; + const thisJson = json[ele._name] + if(_elements && _elements.length === 1 && _elements[0]._type === 'text'){ + // 如果值存在了 + if(thisJson){ + handleCommonArr(_elements[0]._text) + }else{ + json[ele._name] = _elements[0]._text + } + }else{ + if(thisJson){ + handleCommonArr( deeml(ele._elements,ele._name) ) + }else{ + json[ele._name] = deeml(ele._elements,ele._name) } } - }) - console.info(judgeTag,'项目状态projectsObj:' + JSON.stringify(projectsObj)); - console.info(judgeTag,'所有考试项目数量:' + allProjectNum) - console.info(judgeTag,'必考项目数量:' + projectNum) - console.info(judgeTag,'必考项目已考数量:' + endProjectsNum) - //必考项目除靠边停车是否全部完成 - this.judgeUI.isRequiredProjectsEnd = (projectNum - endProjectsNum === 0) - this.judgeUI.isAllProjectsEnd = (allProjectNum - allEndProjectsNum === 0) - } - // 模拟灯光 - setMndg = async (mndgStr: string) => { - this.mndgStr = mndgStr - } - // 检测差分状态 - checkDwzt = async (type) => { - const {avPlayer} = this; - const judgeConfig = this.judgeUI.judgeConfig; - switch (type){ - case 0: - this.judgeUI.isDwztRight = true; - break; - - case 1: - this.judgeUI.dwztErrorVisible = true; - avPlayer.playAudio([`voice/差分状态异常.mp3`],true) - setTimeout(()=>{ - router.back() - },3000) - break; - - case 2: - avPlayer.playAudio([`voice/差分状态异常.mp3`],true); - - break; - case 3: - this.judgeUI.dwztErrorVisible = true; - avPlayer.playAudio([`voice/差分状态异常.mp3`],true); - break; - - case 4: - this.judgeUI.isDwztRight = false; - //差分异常上报 - break; + //通用处理重复标签 + function handleCommonArr(obj){ + if(thisJson){ + if(Array.isArray(thisJson)){ + json[ele._name].push(obj) + }else{ + json[ele._name] = [json[ele._name],obj] + } + }else{ + json[ele._name] = obj + } + }0 + }else{ + //标签上有属性 + if(ele._attributes){ + json[_name] = { + value: ele._text, + attributes:ele.__attributes + } + } } - } + }); + return json +}; - closeAllFiles = ()=>{ - setTimeout(()=>{ - this.fileLog.closeAllFiles() - },1000) - } - - public plcStr: string - private judgeUI - private fileLog - private filePath - private totalScore: number - private prevJd: number = 0 - private prevWd: number = 0 - private dwztNum:number = 0 - private folderPath: string - private modelPath: string - private avPlayer - private carztStr: string - private rmndg: 0 | 1 - private mndgStr: string | undefined - private xmmcStr: string - private xmmcCode: string - private xmmcSingleCode: number - private xmmcEndCode?:number - private xmdm: string | number - private xmxh: string - private fileModel: FileModel - private filePhoto: FilePhoto - private usbService: UsbService - //是否是考试模式 - private isExam: boolean - //考试是否结束了 - private isExamEnd: boolean - // 是否发送udp - private isUdpEnd: boolean = false - //是否手动结束考试 - private isManual: boolean - //UDP服务序列号 - private serialIndex: number - private fileUtil: FileUtil - private judgeTask: JudgeTask - private tempData: any - private performInfo: any - private isEndTip:boolean = false; - private deductedPopShowTimer:number = 0; - private ksjs: { - // 累计前进距离 - qjjl: number, - // 累计倒车距离 - dcjl: number - d1: number - d2: number - d3: number - d4: number - d5: number - d6: number - } - private kfArr: { - //项目名称 - xmmcStr: string, - xmdm: string | number, - //扣分描述 - desc: string, - //扣分 - score: string - //无锡所扣分代码 - markcatalog: string - markserial: string - kfxh: string - type: 0| 1 | 2 - }[] - private km2ItemsStatus: any[] - //所有的科目考试项目(大车&小车) - private testKmItems: any - - private plcData: any - - //当前科目二的考试项目 - private currentKm2ItemsObj: any - //本地轨迹回放地址 - private trajectoryPath: string - private isTrajectoryOpen: boolean; - // 调代理接口是否断网了 - private isJudgeDisConnect: boolean; - private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11] - private lane: LANE = { - road: '', num: 0, count: 0 - } - private videoData:any - private disConnectNum:number = 0; - -} \ No newline at end of file +function isEmpty(param) { + return!Object.keys(param).length; +} diff --git a/entry/src/main/ets/pages/judgeSDK/judge.ts b/entry/src/main/ets/pages/judgeSDK/judge.ts index 75446b8a..18983a79 100644 --- a/entry/src/main/ets/pages/judgeSDK/judge.ts +++ b/entry/src/main/ets/pages/judgeSDK/judge.ts @@ -1,249 +1,1798 @@ -import http from '@ohos.net.http'; -import convertxml from '@ohos.convertxml'; -import prompt from '@ohos.prompt' -import { sendGreen } from '../../pages/judgeSDK/utils/judgeCommon'; -import {GlobalConfig} from '../../config/index' +import systemTime from '@ohos.systemDateTime'; +import router from '@ohos.router'; +import util from '@ohos.util'; +import buffer from '@ohos.buffer'; +import { testKm2Items,testKm3Items, testMarkRules } from './dataTest/index'; +import { EXAMDATA, SOUND, KSJS } from './api/judgeSDK'; +import VoiceAnnounce from './utils/voiceAnnouncements'; +import FileModel from './utils/fileModel'; +import FilePhoto from './utils/filePhoto'; import FileUtil from '../../common/utils/File'; -import { dateFormat } from '../utils/tools' +import FileLog from './utils/fileLog'; +import JudgeTask from './utils/judgeTask'; +import { judgeConfig } from './utils/judgeConfig'; +import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; +import UsbService from '../../common/service/usbService'; +import { LANE,KF } from '../judgeSDK/api/judgeSDK.d'; +import {saveStartRecordVideo,endRecordVideo} from '../../common/service/videoService' +import { + Array2Byte, + convertGpsCoord2, + deepClone, + fillZero, + getCurrentTime, + string2Bytes, + stringToASC +} from '../../common/utils/tools'; -const config = { - host:GlobalConfig.host, -} +import { + getCarStatus, + getCarStatusType, + getDwStatusType, + getCenterProjectStatus, + getKmProjectVoice, + getTranslateSignals, + plcStrToJson, + plcStrToWXJson, + promptWxCode, + senorToWXDataStr, + getKmProjectCancelVoice +} from './utils/judgeCommon'; -/** - * @author: Renjun Su - * @date: 2023/2/20 - * @desc 接口请求封装 - * @param {method} - * @param {xml} xml请求的数据 xml是字符串 - * @param {data} post请求的数据 - * @param {params} get请求的数据 - * - */ -// let httpRequest = http.createHttp(); +import { + examJudgeArtificialItem, + examJudgeArtificialMark, + examJudgeBeginExam, + examJudgeEndExam, + examJudgeInit, + examJudgeSoundEnd, + examJudgeRealExam, + examJudgeSetLogCallback, + examJudgeSetPerformCallback, + examJudgeSetRealExamCallback, + examCalcGpsDistance, + examJudgeVersion +} from './api/index'; -export default async function request(req: any) { - const {url,params = {},data = {},xml,method = 'get',host,isNewCenter = false} = req; - let httpRequest = http.createHttp(); - const options = { - method: http.RequestMethod[method.toUpperCase()], - header: { - 'Content-Type': xml ? 'text/xml' : 'application/json' - }, - extraData: xml ? data : JSON.stringify(data), - //15秒超时 - connectTimeout:15 * 1000 - } - //params转url拼接参数 - let paramsStr = Reflect.ownKeys(params).reduce((p: string, n: string) => (`${p}${n}=${params[n]}&`), '?') || ''; - paramsStr = paramsStr.toString(); - paramsStr = paramsStr.substring(0, paramsStr.length-1) - try { - let baseUrl=host?host:globalThis.host - // let baseUrl=host?config.csptHost:config.host' - console.log('响应头地址1' + baseUrl,url,options.extraData.length) - const {result,responseCode} = await httpRequest.request(`${baseUrl}${url}${paramsStr}`, {...options}); - // fileUtil.editFile(`${folderPath}/request.txt`, JSON.stringify(arrList)) - // writeLog({ - // time:dateFormat(new Date()), - // url, - // result:JSON.stringify(result), - // extraData: JSON.stringify(data), - // state:'end' - // }) - console.log('响应头地址' + JSON.stringify(result)) - let res:any = xml ? xmlToJson(result,url) : result; - console.log('响应头地址' + JSON.stringify(res)) +const judgeTag = 'SURENJUN_JUDGE' +import { getSyncData, upDateTableByArray } from '../../common/service/initable'; +export default class Judge { + constructor(judgeUI) { + this.serialIndex = 1; + this.judgeUI = judgeUI + //语音播放工具 + this.avPlayer = new VoiceAnnounce(); + //模型工具 + this.fileModel = new FileModel(judgeUI.context); + //文件工具 + this.fileUtil = new FileUtil(judgeUI.context) + this.judgeTask = new JudgeTask() + this.usbService = new UsbService(); + this.filePhoto = new FilePhoto(judgeUI.context); + this.kfArr = judgeUI.kfArr + this.xmmcStr = ''; + this.xmmcCode = ''; + this.xmmcEndCode = undefined; + this.carztStr = ''; + this.testKmItems = {}; + // 考试回放配置 + const {isTrajectoryOpen,modelPath,trajectoryPath} = judgeConfig + this.isTrajectoryOpen = isTrajectoryOpen; + this.modelPath = modelPath; + this.trajectoryPath = trajectoryPath; - let resObj = null; - if(typeof res === "string"){ - res=JSON.parse(res) - } - //处理中心服务code - if(res.Envelope){ - const msgXml = res.Envelope.Body.writeObjectOutResponse.return; - //Envelope.Body.writeObjectOutResponse.return - const dd = handleCenterCode(msgXml,isNewCenter); - httpRequest.destroy(); - return dd - } + this.isExam = !this.judgeUI.singlePlay; + const {projectsCenterObj,examSubject} = judgeUI; - if(!xml){ - if(res.head.resultCode === '0'){ - return res - }else{ - const resultMessage = res?.body?.resultMessage || res?.head?.resultMessage - prompt.showToast({ - message: decodeURIComponent(resultMessage), - duration: 3000 - }); - return false + (examSubject ==2 ? testKm2Items : testKm3Items ).forEach(item => { + const projectCenterObj = projectsCenterObj[item.code] + this.testKmItems[item.code] = item; + //考试项目存在 + this.testKmItems[item.code] = { + code: item.code, + status: projectCenterObj === undefined + ? 0 + : ( projectCenterObj.isEnd ? 3 : 1 ) } - } - for( let i in res ) { - resObj = res[i].head - } - console.info('jiangsong:res in request' + url + JSON.stringify(resObj)) - if(resObj.resultCode === '0') { - httpRequest.destroy(); - return res - }else { - prompt.showToast({ - message: decodeURIComponent(resObj.resultMessage), - duration: 3000 - }); - httpRequest.destroy(); - return res - } - } catch (e) { - console.info('test-error' + url + ' error:resp: '+ JSON.stringify(e)) - if(!e||!(e?.message)){ - httpRequest.destroy(); - return {code:-1} - } - const code = e?.code; - prompt.showToast({ - message: e?.message, - duration: 5000 + }) + + console.info(judgeTag+'testKmItems',JSON.stringify(this.testKmItems)) + this.isExamEnd = false; + } + + public async onJudgeFn(fn: Function) { + await this.judging(fn) + } + + //开始评判 + private async judging(callBack: Function) { + const {judgeUI} = this; + const { name, lsh, idCard,kssycs,manualMarkRules} = judgeUI; + const fileLog = new FileLog(judgeUI.context); + const filePath = await fileLog.initFileLogo({ + name, lsh, idCard }); - httpRequest.destroy(); - switch (code){ - //断网 - case 2300007: return {code:2300007} - // 超时 - case 2300028: return {code:2300028} + this.fileLog = fileLog; + this.filePath = filePath; + + const {getJudgeBeginData,handleUdp,handDistance,fileUtil,handleTrajectoryUdp,isTrajectoryOpen,trajectoryPath,avPlayer} = this; + const isJudgeInitBool = globalThis.isJudgeInitBool; + let strArr = []; + if (isTrajectoryOpen) { + const folderPath = await this.fileUtil.initFolder(trajectoryPath); + const str = await fileUtil.readFile(folderPath) + strArr = str.split('\n') + } + //日志回调 + console.info(judgeTag, '1.进入评判入口') + await examJudgeSetLogCallback(3, async (level, info, len) => { + console.log('评判日志:' + info) + await fileLog.setExamJudgeLogData(info); + }) + + console.info(judgeTag, '2.注册日志回调完成') + + let initInfo = isTrajectoryOpen ? JSON.parse(strArr[0]) : await this.getJudgeInitData(); + await fileLog.setExamJudgeData(initInfo) + //相关评判初始化只做一次 + if (!isJudgeInitBool) { + const tempJudge = await examJudgeInit(initInfo); + globalThis.isJudgeInitBool = true + console.info(judgeTag, '4.评判初始化完成') + } + + globalThis.isJudge = true + // 2.评判过程回调 + await examJudgeSetRealExamCallback(async (strData, len) => { + await fileLog.setExamJudgeCallbackData(strData) + console.info('评判回调数据', strData) + this.handleRealExam(strData, callBack) + }) + + await examJudgeSetPerformCallback(async (info) => { + console.info('评判实时数据', info) + const performInfo = JSON.parse(info) + this.performInfo = performInfo + const jl = Math.floor((performInfo.qjjl + performInfo.dcjl) / 100); + if(jl > this.judgeUI.examMileage){ + this.checkExamIsEnd() + } + this.judgeUI.jl = jl + //TODO 待优化 跨组件传值不生效 + globalThis.laneData = performInfo.lane; + }) + + // 3.开始考试 + let beginExamInfo = isTrajectoryOpen ? { + ...JSON.parse(strArr[1]), + replay: 1, + } : await getJudgeBeginData() + + await fileLog.setExamJudgeData(beginExamInfo) + await examJudgeBeginExam(beginExamInfo); + console.info(judgeTag, '6.开始考试注册完成') + avPlayer.playAudio([globalThis.singlePlay ? 'voice/ksks.wav' : 'voice/监管成功.mp3']) + + if(!globalThis.singlePlay){ + this.videoData = await saveStartRecordVideo(`${name}_${kssycs}`) + } + + const {examSubject,projectsObj} = this.judgeUI + // if(examSubject == 3){ + // //不做模拟灯光,需要做上车准备 =>(请上车准备) + // if(projectsObj[41]?.type == 3 && projectsObj[1]?.type != 3){ + // avPlayer.playAudio(['voice/上车准备.mp3']) + // } + // //不做模拟灯光,不做上车准备 =>(请起步,完成考试) + // if(projectsObj[41]?.type == 3 && projectsObj[1]?.type == 3){ + // avPlayer.playAudio(['voice/402001.mp3']) + // } + // } + + this.judgeUI.draw = true + // 处理轨迹plc信息 + if (isTrajectoryOpen) { + handleTrajectoryUdp(strArr); + return + } + // 处理实时udp里的plc信号 + // globalThis.udpClient.closeMessage_1(); + globalThis.udpClient.onMessage_1(async (msg) => { + console.info('socketTag[PLC.UdpClient]', '收到udp回调数据') + handleUdp(msg) + const udpIndex = globalThis.udpIndex; + if (udpIndex % 5 === 0) { + handDistance(); + } + }); + + // this.checkExamIsEnd() + + //监听远程结束考试 + globalThis.udpEvent.onEndExam(async ()=>{ + this.checkExamIsEnd(true); + }) + + console.info(judgeTag,JSON.stringify(manualMarkRules)) + //监听远程扣分 + globalThis.udpEvent.onKfExam(async (content)=>{ + console.info('评判收到远程扣分项目内容' + JSON.stringify(content)) + const { kfxh , directives } = content.data; + console.info(judgeTag ,'评判收到远程扣分项目内容,扣分序号:' + `kfxh=>${kfxh}; directives=>${directives}`) + //根据扣分序号找扣分代码 + const currentKf = manualMarkRules.filter(mark => mark.kfxh == kfxh)[0]; + console.info(judgeTag, '扣分项目:' + JSON.stringify(currentKf)) + this.setJudgeMark(currentKf.itemno, currentKf.markserial, 2); + globalThis.judgeUdp.confirmKf(directives , 1) + }) + + } + //实时计算gps经纬度距离 + handDistance= async ()=>{ + const {jd,wd,hxj,dwzt,jdzt} = this.tempData.gps; + const tJD = convertGpsCoord2(jd) + const tWD = convertGpsCoord2(wd) + const {prevJd,prevWd} = this + if(prevJd && dwzt == 4 && jdzt == 3){ + const distance = await examCalcGpsDistance({ + jd1:prevJd, + wd1:prevWd, + jd2:tJD, + wd2:tWD, + h:hxj || 1, + }) + //@ts-ignore + globalThis.distanceClass?.setTimeData(((distance / 100).toFixed(2)) * 1) + } + this.prevJd = tJD; + this.prevWd = tWD; + } + + // 获取评判初始化数据 + getJudgeInitData = async () => { + const {getModelData,getKm3JudgeInitConfig} = this + const carInfo = globalThis.carInfo; + const { examSubject,plateNo,carId } = carInfo; + const judgeUI = this.judgeUI + const {projectsObj,itemInfoObj,markRuleListObj,carType,carName,systemparmArr,carinfoArr} = judgeUI + const examType = examSubject == 2 ? 'km2' : 'km3' + + let allitems = []; + if (examSubject == 2) { + allitems = Reflect.ownKeys(itemInfoObj).map(cdsbKey => { + const cdsb = itemInfoObj[cdsbKey]; + const {xmdm,xmxh,modelKey} = cdsb + return { + xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`) + } + }) + } + //获取版本号 + const sdkver = await examJudgeVersion(); + const initInfo = { + sdkver, + appver:globalThis.version, + kskm: examSubject * 1, + kchp: plateNo, + kchm: carId * 1, + kscx: carType, + cxcode: '1', + name: carName, + carmodel: getModelData(`${examType}/${carType}.txt`), + allitems, + iteminfo: [], + systemparm: systemparmArr, + mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, + sysset: judgeUI.judgeConfig, + itemInfoObj, + carlist:judgeUI.carlist, + carinfo: carinfoArr, + }; + let km3Config = {} + + if (examSubject == 3) { + km3Config = await getKm3JudgeInitConfig(); + } + // 获取科目三的评判配置 + console.info(judgeTag, '3.获取评判初始化数据完成') + return { + ...initInfo, + ...km3Config, + } + } + + // 获取开始考试数据 + getJudgeBeginData = async () => { + const {code,name:examinerName} = globalThis.examinerInfo; + let currentParams: any = router.getParams(); + const {sczb,kfdm} = currentParams; + const {isExam} = this; + const judgeUI = this.judgeUI + const {projects,carType,kssycs,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr,passingScore} = judgeUI; + const beginInfo = { + kgid: '012', + kgxm: decodeURI(examinerName || ''), + exam: isExam ? 1 : 0, + //是否回放 + replay: 0, + //生成的轨迹文件 + track: '', + xm: judgeUI.name, + sex: 0, + kslsh: judgeUI.lsh, + sfzmhm: judgeUI.idCard, + ksyy: '', + kscx: carType, + kkcs: Number(kssycs) || 2 , + sfyk: 0, + ykkkcs: 1, + wayno: judgeUI.wayno * 1, + czlx: 0, + kskssj: await systemTime.getCurrentTime(), + passing:passingScore * 1, + ksxm: projects.map(project => { + return { + xmdm: project.projectCode * 1, + xmxh: '', + } + }), + //断点续考 + ddxk: isDdxk ? 1 : 0, + ddkssj: ddxkTime || 0, + ykxm: (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) || [], + kfxm: isDdxk ? (ddxkKfArr?.map(kf => { + const [xmdm, kfdm] = kf.split(',') + return {xmdm: xmdm * 1,kfdm} + })) : [], + //TODO 已考里程待修改 + yklc: 0, + special: [], + //TODO 科目三参数临时写死 + sczb: (sczb === undefined || sczb == 0) ? 0 : 1, + sczbkf: kfdm, + dmndg: false, + mfxx: false, + mfxxn: false + } + console.info(judgeTag, '5.获取开始考试数据完成') + return beginInfo + } + + //处理评判过程回调 + handleRealExam = async (strData, callBack) => { + let examData: EXAMDATA = JSON.parse(strData); + const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,avPlayer,fileLog,judgeUI} = this; + const {carzt,xmks,kf,event,xmjs,xmqx,ksjs,sound,mndg,lane,precast,nongps} = examData + const param512 = (judgeUI.judgeConfigObj['512'] || '').split(','); + //获取项目结束、项目开始代码 + const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm + const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; + const isManualProjectIn = this.artSubject3ProjectsCodesArr.includes(xmdm); + const {examSubject,projects,judgeConfigObj} = this.judgeUI; + const param611 = judgeConfigObj['611'] || ''; + switch (event) { + //项目开始 + case 1: + judgeUI.projectsObj[xmdm].type = '2'; + if (isManualProjectIn) { + //手动项目是否在进行中 + this.judgeUI.isManualProjectIn = true + } + if (xmdm == 41 && examSubject == 3) { + this.rmndg = 1 + } + this.judgeUI.currentXmdm = xmdm; + const xmmcStr = judgeUI.projectsObj[xmdm].name; + const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; + const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; + this.testKmItems[xmmcCode].status = 2; + this.xmmcStr = xmmcStr; + this.xmmcCode = xmmcCode; + this.xmmcSingleCode = xmmcSingleCode + this.xmmcEndCode = xmmcCode + this.xmdm = xmdm; + this.xmxh = xmxh; + this.judgeUI.isProjectIn = true + break; + + //项目结束 + case 2: { + const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; + judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3'); + //计算项目是否全部结束 + this.judgeUI.isProjectIn = (Reflect.ownKeys(judgeUI.projectsObj).filter( + projectKey => judgeUI.projectsObj[projectKey].type == '2').length + ) > 0; + if (isManualProjectIn) { + this.judgeUI.isManualProjectIn = false + } + this.testKmItems[xmmcCode].status = 3; + //统计必考项目数量 + this.xmmcStr = '无'; + this.xmmcCode = ''; + this.xmdm = ''; + this.judgeUI.currentXmdm = undefined; + break; + } + + //扣分 + case 3: + const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`) + //扣分信息 + this.kfArr.push({ + //扣分项目名称 + xmmcStr: getDqxmStr(kf.xmdm), + xmdm: kf.xmdm, + //扣分描述 + desc: thisKf.desc, + //扣分分数 + score: thisKf.score, + // 扣分无锡所代码 + markcatalog: thisKf.markcatalog, + markserial: thisKf.markserial, + kfxh: thisKf.kfxh, + //扣分类型 + type: kf.type + }) + this.judgeUI.totalScore += thisKf.score * 1; + if(kf.xmdm != 20){ + const type = judgeUI.projectsObj[kf.xmdm].type; + judgeUI.projectsObj[kf.xmdm].type = (type == 3 || type == 4) ? '4' : '5'; + } + break; + + //考车状态 + case 4: + this.carztStr = getCarStatus(carzt); + break; + + //考试结束 + case 5: + this.ksjs = ksjs; + await fileLog.setExamJudgeData({ + method: 'examJudgeEndExam', + }) + break; + + //项目取消 + case 6:{ + console.info(judgeTag,'项目取消'); + const {examSubject} = this.judgeUI + const xmdm = xmqx.xmdm; + const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; + const voiceCode = getKmProjectCancelVoice(examSubject,xmmcCode); + // avPlayer.playAudio([`voice/${voiceCode}.mp3`],true) + this.judgeUI.projectsObj[xmdm].type = '1'; + this.testKmItems[xmmcCode].status = '1'; + break; + } + + //语音播放和提示 + case 7: + goJudgeVoice(sound) + break; + + //模拟灯光事件 + case 8: + setMndg(mndg) + break; + + //车道和路段变化 + case 9: + this.judgeUI.lane = lane + this.lane = lane; + break; + + //预进项目事件 + case 10:{ + const param611 = judgeConfigObj['611'] || ''; + const [f,s] = param611.split('/') + const {xmdm,xmxh} = precast; + const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; + const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; + // if(examSubject == 2 && ((xmdm == 0 && f == 1) || (xmdm == 1 && s == 1) || xmdm == 3)){ + // //倒车入库/桩考/侧方停车 + // avPlayer.playAudio([`voice/${xmmcCode}.mp3`],false) + // } + this.testKmItems[xmmcCode].status = 2; + this.xmmcStr = xmmcStr; + this.xmmcCode = xmmcCode; + this.xmdm = xmdm; + this.xmxh = xmxh; + this.xmmcSingleCode = xmmcSingleCode; + judgeUI.projectsObj[xmdm].type = '2'; + } + break; + + //差分事件 + case 11:{ + const {type}= nongps + this.checkDwzt(type) + } default: + break; + + } + + const {xmmcStr,carztStr,kfArr} = this; + + await callBack({ + //项目名称 考车状态 扣分arr + xmmcStr, carztStr, kfArr + }); + + //语音播报 + this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs, ksjs,xmxh) + //更新UI + if (event == 1 || event == 2 || event == 3 || event == 6) { + const copyProjectsObj = this.judgeUI.projectsObj; + judgeUI.projectsObj = deepClone(copyProjectsObj); } - return {code:e.code} } -} -async function writeLog(param){ - const fileUtil = new FileUtil(globalThis.context) - const folderPath = await fileUtil.initFolder(`/errorMsg/`); - fileUtil.editFile(`${folderPath}/request.txt`, JSON.stringify(param)+`\n`) + // 更改考试状态 + goVoiceAnnounce = async (event, xmdm, kf, xmjs, ksjs,xmxh) => { + const { + beginProject, + pointsDedute, + endProject, + avPlayer, + uploadProgressPhoto, + judgeTask, + handEndExam, + judgeUI, + checkExamIsEnd, + checkProjectIsStart, + lane, + closeAllFiles + } = this; -} + const {projectsObj,judgeConfigObj,examSubject,examMileage,jl,isAllProjectsEnd} = judgeUI; + const kfLen = kf.length; + //不报语音的项目列表 + const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') + const param611 = judgeConfigObj['611'] || ''; + const param512 = (judgeConfigObj['512'] || '').split(','); + const [f,s] = param611.split('/') + switch (event) { + // 项目开始 + case 1: + const code = projectsObj[xmdm].projectCodeCenter; + const isEnd = projectsObj[xmdm].isEnd; + const kmCode = getKmProjectVoice(code, 1, judgeConfigObj, lane,xmxh) + // if (!ignoreVoiceCodeArr.includes(code)) { + // if(examSubject == 2 && ((xmdm == 0 && f == 2) || (xmdm == 1 && s == 2) || xmdm == 3)){ + // //倒出入库、桩考\进项目语音控制 + // }else{ + // kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`],true) + // } + // } + setTimeout(()=>{if(param512[7] != 0){ + clearTimeout(this.deductedPopShowTimer) + this.judgeUI.isDeductedPopShow = true + }},200) + //项目已考不上传监管信息 + if (!isEnd) { + judgeTask.addTask(async () => { + console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`) + await beginProject(xmdm) + },{isDelay: true}) + judgeTask.addTask(async () => { + console.info(judgeTag, `项目-${xmdm}-上传照片 start`) + await uploadProgressPhoto(xmdm) + },{isDelay: true}) + this.judgeUI.projectsObj[xmdm].isUpload = true; + } + break; + // 项目结束 + case 2:{ + const endCode = projectsObj[xmdm].projectCodeCenter; + const projectIsEnd = projectsObj[xmdm].isEnd; + const endKmCode = getKmProjectVoice(endCode, 2, judgeConfigObj, lane,xmxh) + // if (!ignoreVoiceCodeArr.includes(endCode) && examSubject == 3) { + // endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) + // } + const isStart = await checkProjectIsStart(xmdm,1); + if(isStart){ + //项目结束了就不再生成数据 + console.info(judgeTag + ' projectIsEnd =>',projectIsEnd) + if (!projectIsEnd) { + judgeTask.addTask(async () => { + console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`) + await endProject(xmdm); + this.xmmcSingleCode = 0; + this.xmmcEndCode = undefined; + }, {isDelay: true}) + } + } + if(!this.judgeUI.isProjectIn){ + this.deductedPopShowTimer = setTimeout(()=>{ + this.judgeUI.isDeductedPopShow = false + },(param512[5] || 0) * 1000) + } + judgeUI.projectsObj[xmdm].isEnd = true; + break; + } -//xml格式转JSON -function xmlToJson(result,url) { - console.log("xmlToJson begin",url); - let xmlOptions = {trim : false, declarationKey:"_declaration", - instructionKey : "_instruction", attributesKey : "_attributes", - textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", - commentKey : "_comment", parentKey : "_parent", typeKey : "_type", - nameKey : "_name", elementsKey : "_elements", "skipPreprocess" : true} + // 扣分 + case 3: + console.info('surenjun','扣分开始') + //扣分时实时播报语音(0-否+1-是) + const currentKf = kf[kfLen -1]; + if (judgeConfig.kfVoiceOpen ||(examSubject == 2 && judgeConfigObj['618'] == '1') || (examSubject== 3&& judgeConfigObj['418'] == '1') ) { + avPlayer.playAudio([`voice/${currentKf.markcatalog}.mp3`,`voice/mark_${Math.abs(currentKf.score)}.mp3`]) + } + const isStart = await checkProjectIsStart(currentKf.xmdm,2,currentKf); + if(isStart){ + await judgeTask.addTask(async () => { + console.info(judgeTag, `项目扣分-${currentKf.markcatalog}-${currentKf.desc}`) + await pointsDedute(currentKf.xmdm, currentKf) + }, {isDelay: true}) + } + break; - let strXml = result.toString(); - let conv = new convertxml.ConvertXML(); + // 考车状态 + case 4: + break - console.log("xmlToJson result.length = " + result.length); - console.log("xmlToJson result content = " + result); - // @ts-ignore - let {_elements:xmlArr} = conv.convertToJSObject(strXml, xmlOptions); - console.log("xmlToJson deeml begin"); - let res = deeml(xmlArr); - console.log("xmlToJson end",url); - return res -} + // 考试结束 + case 5: + console.info(judgeTag, '考试结束') + //关闭录像 + if(!globalThis.singlePlay){ + await endRecordVideo(this.videoData) + } + judgeTask.addTask(async () => { + console.info(judgeTag, '考试结束 start') + globalThis.isJudge = false; + await handEndExam(ksjs) + }) + clearInterval(globalThis.judgeTimer) + break + default: + break + } + if (event == 2 || event == 3) { + setTimeout(() => { + this.judgeUI.kfArrScroller.scrollTo({ + yOffset: 999999, xOffset: 0 + }) + },500) + //统计必考项目完成数量 + await this.setCountItems(); + await checkExamIsEnd() + } + } -//处理中心服务code -function handleCenterCode(msgXml,isNewCenter){ - //新监管 - if(isNewCenter){ - const msg = JSON.parse(msgXml); - const result = msg?.data[0]?.result; - if(result){ - const {code,message,retval} = result - if(code != '1'){ - const rMessage = decodeURIComponent(message as string) - // globalThis.title=rMessage - // globalThis.type='1' - // globalThis.errorDialog.open() - prompt.showToast({ - message:rMessage, - duration: 3000 - }); - return {code,message} - }else{ - return { code ,keystr:retval} + // 检测扣分、结束项目时该项目是否开始 + checkProjectIsStart = async(xmdm,currentType:1|2,kf?:KF) => { + if(xmdm == 20){ + return true + } + const {judgeTask,beginProject,pointsDedute,uploadProgressPhoto,endProject,checkExamIsEnd,totalScore} = this; + const {projectsObj,passingScore:passingGrade} = this.judgeUI + const {isUpload} = projectsObj[xmdm]; + //如果项目没有开始 + console.info('surenjun isUpload=>',isUpload) + if(!isUpload){ + console.info(judgeTag,'项目补传开始') + //项目开始补传 + judgeTask.addTask(async ()=>{await beginProject(xmdm)},{isDelay:true}) + judgeTask.addTask(async ()=>{await uploadProgressPhoto(xmdm)},{isDelay:true}) + this.judgeUI.projectsObj[xmdm].isUpload = true; + //扣分补传 + if(currentType == 2){ + judgeTask.addTask(async ()=>{await pointsDedute(xmdm,kf)},{isDelay:true}) + } + //扣分补传判断是否合格 不合格补传项目结束 + if(currentType == 1 || (currentType == 2 && totalScore < passingGrade)){ + judgeTask.addTask(async ()=>{await endProject(xmdm)},{isDelay:true}) + this.judgeUI.projectsObj[xmdm].isEnd = true; + } + judgeTask.addTask(async ()=>{ + checkExamIsEnd() + }) + return false; + }else{ + return true + } + } + + // 项目开始接口同步 + beginProject = async (ksxm) => { + const carInfo = globalThis.carInfo; + const { examSubject,plateNo } = carInfo; + const {judgeUI,fileLog,getSbbm,xmxh,filePath} = this; + const {lsh,idCard,serialNumber,projectsObj,ksdd,kslx,xldm} = judgeUI + const time = await getCurrentTime(); + const project = projectsObj[ksxm] + const sbxh = getSbbm(ksxm, xmxh) + const data = { + //系统类别 接口序列号 接口标识 + xtlb: '17', jkxlh: serialNumber, jkid: '17C52', + drvexam: { + // 考试科目 身份证号码 + lsh, + kskm: examSubject, + sfzmhm: idCard, + ksxm: project.projectCodeCenter, + sbxh, + ksxl:xldm, + kchp: encodeURI(plateNo), + // 开始时间 + ksdd: encodeURI(ksdd), + kslx: encodeURI(kslx) || '', + kssj: time } } + const {code} = await this.sendWriteObjectOut(data,filePath) + console.info(judgeTag, '项目开始 end') + if (code === 2300007) { + this.isJudgeDisConnect = true; + } + promptWxCode('17C52', code) } - //正则匹配code message字段 - const [code,message,keystr] = [/(.*)<\/code>/i,/(.*)<\/message>/i,/(.*)<\/keystr>/i].map(pattern=>{ - const patternArr = pattern.exec(msgXml); - return patternArr && patternArr[1] - }); + // 项目结束接口同步 + endProject = async (ksxm) => { + const carInfo = globalThis.carInfo; + const deviceNo = globalThis.deviceNo; + const { examSubject,plateNo,carNo } = carInfo; + const {judgeUI,fileLog,getSbxh,xmxh,getSbbm,filePath} = this; + const {lsh,idCard,serialNumber,projectsObj,cdsbInfoObj,ksdd,kslx,xldm,} = judgeUI + const time = await getCurrentTime(); + const project = projectsObj[ksxm] + const sbxh = examSubject == 3 ? undefined : getSbbm(ksxm, xmxh) - if(code != '1'){ - prompt.showToast({ - message: decodeURIComponent(message as string), - duration: 3000 - }); - // globalThis.type='1' - // globalThis.title=decodeURIComponent(message as string) - // globalThis.errorDialog.open() - return {code,message:decodeURIComponent(message)} - }else{ - return { code ,keystr, message } + const data = { + xtlb: '17', jkxlh: serialNumber, jkid: '17C55', + drvexam: { + lsh, + kskm: examSubject, + sfzmhm: idCard, + ksxm: project.projectCodeCenter, + sbxh, + //TODO 操作类型 1:正常 0:撤销该考试记录 + czlx: '1', + ksxl:xldm, + kchp: encodeURI(plateNo), + ksdd: encodeURI(ksdd), + kslx: encodeURI(kslx) || '', + jssj: time + } + } + const {code} = await this.sendWriteObjectOut(data,filePath) + if (code === 2300007) { + this.isJudgeDisConnect = true; + } + console.info(judgeTag, '项目结束 end') + promptWxCode('17C55', code) } -} -//JSON转xml格式 -const deeml = (elements,_name?)=>{ - const json = {} + // 考试扣分 + pointsDedute = async (ksxm, kf) => { + const carInfo = globalThis.carInfo; + const deviceNo = globalThis.deviceNo; + const { examSubject,plateNo,carNo } = carInfo; + const {judgeUI,getProjectInfo,fileLog,xmmcSingleCode,xmmcEndCode,filePath} = this; + const {lsh,idCard,serialNumber,ksdd,projectsObj} = judgeUI + const time = await getCurrentTime(); + const project = getProjectInfo(ksxm); + //科目三夜间行驶.模拟灯光、上车准备出现通用评判,ksxm为当前进行的项目 + const checkProjects = ['17', '41', '1']; + //获取正在进行的项目 + const inProjects = Reflect.ownKeys(projectsObj).filter(projectKey => projectsObj[projectKey].type == 2); - elements.map(ele =>{ - const _elements = ele._elements - if(ele._type === 'element'){ - if(_elements==undefined){ + let commonKsxm = ''; + checkProjects.forEach(projectCode=>{ + if(inProjects.includes(projectCode)){ + commonKsxm = projectCode + } + }) + + const data = { + xtlb: '17', jkxlh: serialNumber, jkid: '17C53', + drvexam: { + lsh, + kskm: examSubject, + ksxm: project == undefined + ? (commonKsxm + ? (projectsObj[commonKsxm].projectCodeCenter) + : (examSubject == 3 ? 30000 : (xmmcEndCode == undefined ? 10000 : xmmcEndCode))) + : project.projectCodeCenter , + kfxm: kf.markcatalog, + kfxmmx: `${ksxm},${kf.markserial}`, + sfzmhm: idCard, + kchp: encodeURI(carInfo.plateNo), + //扣分方式 + kffs: kf.type == 0 ? 1 : 2, + ksdd: encodeURI(ksdd), + kfsj: time + } + } + console.info(judgeTag + 'ksxm=>',data.drvexam.ksxm) + + const {code} = await this.sendWriteObjectOut(data,filePath); + if (code == 2300007) { + this.isJudgeDisConnect = true + } + console.info(judgeTag, '项目扣分 end') + promptWxCode('17C53', code) + } + + //调用监管接口 + sendWriteObjectOut = async (data,filePath)=>{ + const temp = await writeObjectOut(data,filePath); + //断网&网络超时次数计算 + if(temp.code == 2300007 || temp.code == 2300008){ + this.disConnectNum += 1; + if(this.disConnectNum < 5){ + return await this.sendWriteObjectOut(data,filePath) + } + } + + if(this.disConnectNum >= 5){ + console.info('surenjun','123') + this.judgeUI.errorMsg = '当前的考试过程信息网络传输异常,程序点击确认将重启!'; + this.judgeUI.disConnectErrorOpen = true + } + + this.disConnectNum= 0 + return temp + } + + // 考试过程照片 + uploadProgressPhoto = async (ksxm) => { + const time = await getCurrentTime(); + const {judgeUI,plcData,getPhoto,fileLog,filePath} = this; + const photoBase64 = await getPhoto(); + const carInfo = globalThis.carInfo; + const { examSubject,plateNo,carNo } = carInfo; + const {lsh,idCard,serialNumber,projectsObj,ksdd,judgeConfigObj} = judgeUI; + const {sensor,gps} = plcData + const project = projectsObj[ksxm] + + const data = { + xtlb: '17', jkxlh: serialNumber, jkid: '17C54', + drvexam: { + lsh, + kskm: examSubject, + ksxm: project.projectCodeCenter, + sfzmhm: idCard, + kchp: encodeURI(plateNo), + zpsj: time, + //@ts-ignore + zp: photoBase64, + cs: Math.floor((judgeConfigObj['350'] == 0?gps.sd:sensor.cs) * 1.852), + ksdd: encodeURI(ksdd) + } + }; + const {code} = await this.sendWriteObjectOut(data,filePath); + if (code === 2300007) { + this.isJudgeDisConnect = true + } + promptWxCode('17C54', code) + console.info(judgeTag, '上传照片 end') + } + + // 评判语音提示 + goJudgeVoice = async (sound: SOUND) => { + const {avPlayer,fileLog} = this; + const {xmdm,code,type} = sound; + console.info('surenjun code=>',JSON.stringify(code)) + //判断是不是模拟灯光语音 + if (type == 1) { + avPlayer.playAudio([`voice/${code[0]}.mp3`], false, () => { + examJudgeSoundEnd({ + itemno: xmdm, code:code[0], type + }) + fileLog.setExamJudgeData({ + method: 'examJudgeSoundEnd', + itemno: xmdm, + code:code[0], + type, + }) + }) + }else{ + avPlayer.playAudio([`voice/${code[0]}.mp3`]) + } + } + + // 校验考试是否结束 + checkExamIsEnd = + async (isManual?: boolean) => { + const {judgeUI,avPlayer,isExamEnd,isEndTip,ksjs} = this; + const {isAllProjectsEnd,examSubject,singlePlay,totalScore,judgeConfigObj,passingScore,examMileage,jl} = judgeUI; + + if (isExamEnd) { return } - const thisJson = json[ele._name] - if(_elements && _elements.length === 1 && _elements[0]._type === 'text'){ - // 如果值存在了 - if(thisJson){ - handleCommonArr(_elements[0]._text) - }else{ - json[ele._name] = _elements[0]._text - } - }else{ - if(thisJson){ - handleCommonArr( deeml(ele._elements,ele._name) ) - }else{ - json[ele._name] = deeml(ele._elements,ele._name) - } - } + //及格分 + let passingGrade = passingScore + if (isManual) { + // 考试不合格 + await examJudgeEndExam() + this.isExamEnd = true + this.isManual = true + } else { + const param302 = judgeConfigObj['302']; + const param342 = judgeConfigObj['342']; + const param512 = (judgeConfigObj['512'] || '').split(','); - //通用处理重复标签 - function handleCommonArr(obj){ - if(thisJson){ - if(Array.isArray(thisJson)){ - json[ele._name].push(obj) - }else{ - json[ele._name] = [json[ele._name],obj] + //单机模式 + if (singlePlay) { + console.info(judgeTag + ' isAllProjectsEnd => ',isAllProjectsEnd) + if (isAllProjectsEnd && jl >= examMileage) { + //成绩合格 + if(totalScore >= passingGrade && !isEndTip) { + if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) { + if(param512[7] != 0){ + clearTimeout(this.deductedPopShowTimer) + avPlayer.playAudio(['voice/综合评判.mp3']) + this.judgeUI.isDeductedPopShow = true + this.judgeUI.defaultTabIndex = 1 + this.isEndTip = true + return + } + } else { + await examJudgeEndExam() + this.isExamEnd = true + return + } + }else{ + if(examSubject == 3 && (param302 == 4 || param302 == 5 || param302 == 7 || param302 == 8)){ + await examJudgeEndExam() + this.isExamEnd = true + return + } + } + await examJudgeEndExam() + this.isExamEnd = true + } + } else { + //成绩不合格 + if (totalScore < passingGrade) { + //科目三不合格报靠边停车 + if(examSubject == 3 && param302 ==1){ + avPlayer.playAudio([`voice/考试结束.mp3`]); + return + } + await examJudgeEndExam() + this.isExamEnd = true + return + } + + //成绩合格 + if (isAllProjectsEnd && totalScore >= passingGrade && !isEndTip) { + if(examSubject == 2){ + await examJudgeEndExam() + this.isExamEnd = true + return + } + + //考试里程判断 + if(examSubject == 3 && jl < examMileage){ + return + } + + //考试合格自动退出 + if(examSubject == 3 && (param302 == 4 || param302 == 7) || param302 == 8){ + await examJudgeEndExam() + this.isExamEnd = true + return + } + + if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) { + if(param512[7] != 0){ + clearTimeout(this.deductedPopShowTimer) + this.judgeUI.isDeductedPopShow = false + avPlayer.playAudio(['voice/综合评判.mp3']) + this.judgeUI.isDeductedPopShow = true + this.judgeUI.defaultTabIndex = 1 + this.isEndTip = true + } + } else { + await examJudgeEndExam() + this.isExamEnd = true + } } - }else{ - json[ele._name] = obj - } - }0 - }else{ - //标签上有属性 - if(ele._attributes){ - json[_name] = { - value: ele._text, - attributes:ele.__attributes } } } - }); - return json -}; + // 处理考试结束 + public handEndExam = async (ksjs: KSJS) => { + this.judgeUI.loadingPopupVisible = true; + this.judgeUI.endPopupVisible = false; + this.judgeUI.isDeductedPopShow = false; + const {qjjl,dcjl} = ksjs + const {judgeUI,endExam,handleSEP,kfArr,avPlayer,judgeTask,isManual,closeAllFiles} = this; + const {judgeConfigObj,examSubject,isAllProjectsEnd,totalScore,passingScore} = judgeUI; + //计算考试分数 + // this.judgeUI.totalScore = isAllProjectsEnd ? totalScore : 0; + const singlePlay = globalThis.singlePlay + const param302 = judgeConfigObj['302']; + // globalThis.windowClass.setWindowSystemBarEnable(['navigation']) -function isEmpty(param) { - return!Object.keys(param).length; -} + //自动退出待验证并且不合格 + if (!isManual && examSubject == 3 && (param302 == 1 || (singlePlay && param302 == 2)) && totalScore < passingScore) { + avPlayer.playAudio([`voice/考试结束.mp3`]) + } + //联网模式下手动结束的直接退出 + if (!singlePlay && isManual && !isAllProjectsEnd) { + avPlayer.playAudio(['voice/empty.mp3'], true, () => { + this.isUdpEnd = true; + closeAllFiles() + router.back(); + }) + return + } + if (examSubject == 3) { + const param302 = judgeConfigObj['302']; + if (totalScore < passingScore) { + //考试不合格;考试模式,自动退出; + if (param302 == 4 || param302 == 5 || param302 == 7 || param302 == 8) { + + } + } else { + //考试合格 + } + } + await handleSEP(306); + avPlayer.playAudio(['voice/exam_waiting.mp3'], globalThis.singlePlay, async () => { + try { + if (!singlePlay) { + const bytes = await this.getMessageHeartbeat(true); + globalThis.judgeUdp.send(bytes) + } + await endExam() + } catch (e) { + console.info(judgeTag,JSON.stringify(e)) + // setTimeout(() => { + // // avPlayer.avPlayerStop(); + // router.back(); + // }, 3000) + } + }); + + } + + // 考试结束 + public endExam = async (isManual?: Boolean) => { + const carInfo = globalThis.carInfo; + const singlePlay = globalThis.singlePlay + const { examSubject ,plateNo} = carInfo; + const {judgeUI,ksjs,getPhoto,uploadProgressData,uploadDisConnectData,avPlayer,kfArr,judgeTask,filePath,closeAllFiles} = this; + const {lsh,idCard,serialNumber,kssycs,totalScore,judgeConfigObj,isAllProjectsEnd,passingScore} = judgeUI + //TODO 断网考试结束补传 + // await uploadDisConnectData(); + const time = await getCurrentTime(); + const photoBase64 = await getPhoto(); + const {d1,d2,d3,d4,d5} = ksjs + const data = { + xtlb: '17', jkxlh: serialNumber, jkid: '17C56', + drvexam: { + lsh, + kchp: encodeURI(plateNo), + kskm: examSubject, + sfzmhm: idCard, + //@ts-ignore + zp: photoBase64, + jssj: time, + kscj: (totalScore * 1) > 0 ? totalScore : 0, + kslc: Math.ceil(((ksjs?.qjjl + ksjs?.dcjl) || 0) / 100), + // 1,22;2,560;3,128;4,0;5,0; + dwlc: [d1,d2,d3,d4,d5].map((d,index) => `${index+1},${Math.floor(d /100)}`).join(';'), + } + } + const {code,keystr,message} = await this.sendWriteObjectOut(data,filePath) ; + promptWxCode('17C56', code) + + if(code != 1){ + avPlayer.playAudio(['voice/监管失败.mp3']) + this.judgeUI.errorMsg = decodeURIComponent(message) + + if(code == 2300028 || code == 2300027){ + this.judgeUI.errorMsg = '当前的考试过程信息监管审核未通过,程序将退出!' + } + this.isUdpEnd = true; + closeAllFiles() + this.judgeUI.loadingPopupVisible = false; + return + } + + console.info(judgeTag, '考试结束 end') + const param302 = judgeConfigObj['302']; + judgeUI.loadingPopupVisible = true; + + let currentKssycs =0; + let voiceURL = '' + if (examSubject == 2) { + if (isAllProjectsEnd) { + voiceURL = (totalScore < passingScore ? `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav` : 'voice/qualified.mp3') + }else{ + voiceURL = `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav` + currentKssycs = kssycs == 1 ? 0 : 1 + } + switch (voiceURL){ + case 'voice/unqualified_one.wav': + currentKssycs = 0; + break; + + case 'voice/unqualified_two.wav': + currentKssycs = 1; + break; + + case 'voice/qualified.mp3': + currentKssycs = 0; + break; + } + } + if (examSubject == 3) { + if (isAllProjectsEnd) { + if (totalScore < passingScore) { + voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3` + currentKssycs = kssycs == 1 ? 0 : 1 + } else { + voiceURL = 'voice/exam_pass.mp3' + currentKssycs = 0 + } + } else { + voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3` + currentKssycs = kssycs == 1 ? 0 : 1 + } + switch (voiceURL){ + case 'voice/exam_no_pass_finish.mp3': + currentKssycs = 0; + break; + + case 'voice/exam_no_pass.mp3': + currentKssycs = 1; + break; + + case 'voice/exam_pass.mp3': + currentKssycs = 0; + break; + + } + } + + const USER = await getSyncData('USER'); + await upDateTableByArray('USER', [{ + ...USER[0], + kssycs:currentKssycs + }]) + + console.info(judgeTag, `考试成绩:${totalScore}`) + if(!singlePlay){ + await uploadProgressData(); + } + //语音播放扣分项 + let score = 0; + //结束考试时候是否播报一遍所有扣分 + const param634 = judgeConfigObj['634']; + if (kfArr.length && ((examSubject == 2 && param634 == 1) || examSubject == 3)) { + avPlayer.playAudio([`voice/kfdesc.mp3`], false, () => { + try { + kfArr.forEach((kf, index) => { + score += Math.abs(Number(kf.score)); + //TODO 考试分数待替换 + if (score <= (examSubject == 3 ? 10 : 20)) { + if (kfArr.length - 1 === index) { + avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`, voiceURL], false, () => { + this.isUdpEnd = true; + closeAllFiles() + router.back(); + }) + throw new Error('End Loop') + } + avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`]) + } else { + avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`, voiceURL], false, () => { + this.isUdpEnd = true; + closeAllFiles() + router.back(); + }) + throw new Error('End Loop') + } + }) + } catch (e) { + console.info(judgeTag,JSON.stringify(e)) + } + }) + } else { + avPlayer.playAudio([voiceURL], true, () => { + setTimeout(() => { + this.isUdpEnd = true + closeAllFiles() + router.back(); + }, param302 == 8 ? 3000 : 0) + }) + } + } + + // 当前项目转换 + getDqxmStr = (type) => { + const projectsObj = this.judgeUI.projectsObj + return projectsObj[type]?.abbreviation || '通用评判' + } + + // 扣分项目转换 + getKfStr = (code) => { + const markRuleListObj = this.judgeUI.markRuleListObj; + const thisMark = markRuleListObj[code] + return { + desc: thisMark.markshow, + score: thisMark.markreal, + markcatalog: thisMark.markcatalog, + markserial: thisMark.markserial, + kfxh: thisMark.kfxh + } + } + // 消息心跳发送 + getMessageHeartbeat = async (isEnd?: Boolean) => { + const carInfo = globalThis.carInfo; + const { examSubject,plateNo,ksyh } = carInfo; + const { + judgeUI, + isExam, + serialIndex, + tempData, + xmmcCode, + xmxh, + xmmcSingleCode, + xmdm, + performInfo, + kfArr, + getTranslateProject, + getSbxh, + fileLog, + } = this; + const singlePlay = globalThis.singlePlay + const {lsh,startHourTime,totalScore,examTime,judgeConfigObj} = judgeUI; + const {fourInOneScreen:{gpsDigit}} = judgeConfig + const examType = examSubject == 2?2:3 + const {sensor,gps} = tempData; + if(tempData.sensor === undefined){ + return + } + const {zfxd,yfxd,shtd,ygd,jgd,skd,dh1,dh2,lhq,jsc,ssc,fsc,lb,mkg,aqd,ygq,cs,fdjzs,dw} = sensor + const {jd,wd, hxj, fyj, hbg,sd} = gps; + + //过滤错误数据 + if(jd == 0){ + return + } + const translateProject = getTranslateProject(); + const sbxh = getSbxh(xmdm, xmxh) + const {carzt,dcjl,qjjl,dxjl,bxjl} = performInfo || {}; + const asclshArr = stringToASC( + fillZero((singlePlay ? (examSubject == 2 ? '0000000000000':'1111111111111') : lsh) || 0, 13) + ); + //13不足要补0 + const ascksyhArr = stringToASC(fillZero(ksyh || 0, 13)) + const ascsbxhArr = stringToASC(sbxh) + const translateSignals = getTranslateSignals( + [zfxd, yfxd, shtd, ygd, jgd, skd, dh1, dh2, lhq, jsc, ssc, fsc, lb, mkg, aqd].concat(getDwStatusType(dw)).concat(getCarStatusType(carzt)).concat([ygq, sensor.wd, 0]) + ) + //@ts-ignore + const translateJd = convertGpsCoord2(wd).toFixed(gpsDigit) * Math.pow(10, gpsDigit); + //@ts-ignore + const translateWd = convertGpsCoord2(jd).toFixed(gpsDigit) * Math.pow(10, gpsDigit) + //@ts-ignore + const translateProjects = translateProject.map(numStr => string2Bytes(parseInt(numStr, 2), 8)[0]) + + //@ts-ignore + let tempSd = ((judgeConfigObj['350'] ==0 ? sd : cs) * 1.852).toFixed(0) * 1 + if(tempSd < 1){ + tempSd = 0 + } + + const arr = [ + //考生号 + asclshArr.map(lsh => string2Bytes(lsh, 8)[0]), + //考试员号 + ascksyhArr.map(ksyh => string2Bytes(ksyh, 8)[0]), + //科目类型(0:未考试 1:科目二 2:科目三) + 考试开始时间 + string2Bytes(`${examType}${globalThis.startHourTime || startHourTime}`, 4 * 8), + // TODO 消息序号从1开始,0结束 + string2Bytes(isEnd ? 0 : serialIndex, 2 * 8), + /*左向灯 右向灯 双跳灯 远光灯 近光灯 视宽灯 点火1 点火2 离合器 脚刹 手刹 副刹 喇叭 门开关 安全带 档位 车辆状态 雨刮器 雾灯 0*/ + translateSignals, + //速度 发动机转速 GPS纬度 GPS经度 主天线位置 + //@ts-ignore + string2Bytes(tempSd * 100, 2 * 8), string2Bytes(fdjzs / 100, 8), string2Bytes(translateJd, 4 * 8), string2Bytes(translateWd, 4 * 8), string2Bytes(1, 8), + //GPS东向距离 + string2Bytes(dxjl < 0 ? (dxjl + 4294967296) : dxjl, 4 * 8), + //GPS北向距离 + string2Bytes(bxjl < 0 ? (bxjl + 4294967296) : bxjl, 4 * 8), + //航向角 俯仰角 高程(海拔) + string2Bytes((hxj) * 100, 2 * 8), string2Bytes(fyj * 100, 2 * 8), string2Bytes(hbg * 100, 4 * 8), + //项目状态 parseInt('01010010',2) 二进制转成10进制 + translateProjects, + //当前项目编号 + string2Bytes(xmmcSingleCode ? (xmmcSingleCode * 1 + 1) : 0, 8), + //场地设备编号 + ascsbxhArr.map(sbxh => string2Bytes(sbxh, 8)[0]), + //本次考试行驶距离 + string2Bytes(Math.floor((dcjl + qjjl) / 100), 2 * 8), + //扣分 + string2Bytes(100 - Math.abs(totalScore), 2 * 8), + //扣分项数量 + string2Bytes(kfArr.length, 8), + //n个扣分序号 + kfArr.map(kf => string2Bytes(kf.kfxh, 8)[0]), + //TODO 牵引车第二gps精度、纬度 + string2Bytes(0, 4 * 8), string2Bytes(0, 4 * 8), + //TODO 牵引车第二航向角 + string2Bytes(0, 2 * 8), + //TODO 摩托压线 Byte[20], + string2Bytes(0, 20 * 8), + //考试用时 + string2Bytes(examTime, 4 * 8), + //TODO 项目用时 + string2Bytes(fillZero(0,2), 2 * 8), + //TODO 设备信号状态 + string2Bytes(0, 4 * 8), + ] + + let tempArr = []; + arr.forEach(itemArr => { + tempArr = tempArr.concat(itemArr) + }) + this.serialIndex += 1; + fileLog.setFourAndOneLogData(`${lsh},${ksyh},${examType}${globalThis.startHourTime || startHourTime},`); + fileLog.setFourAndOneLogDataBytes(tempArr.toString()); + return Array2Byte(tempArr) + } + //获取场地序号 + getSbxh = (ksxm, xmxh) => { + const {judgeUI} = this; + const {cdsbInfoObj,projectsObj} = judgeUI; + const project = projectsObj[ksxm] + if(project == 3){ + return '0000000000' + } + if (project === undefined) { + return '0000000000' + } + const projectType = project.sbxh; + const projectKey = `${ksxm}_${xmxh}`; + const currentCdsb = cdsbInfoObj[projectKey] || {}; + const sbxh = currentCdsb.sbbh || '0000000000' + return sbxh + } + + getSbbm = (ksxm, xmxh) => { + const {judgeUI} = this; + const {cdsbInfoObj,projectsObj,examSubject} = judgeUI; + const project = projectsObj[ksxm] + //科目三不需要 + if(examSubject == 3){ + return undefined + } + if (project === undefined) { + return '00000000' + } + const projectKey = `${ksxm}_${xmxh}`; + const currentCdsb = cdsbInfoObj[projectKey] || {}; + const sbxh = currentCdsb.sbbm || '00000000' + return sbxh + } + // 中心所有项目转换 + getTranslateProject = () => { + const {examSubject} = this.judgeUI; + const tempItems = (examSubject == 2 ? testKm2Items:testKm3Items).map(item => { + const current = this.testKmItems[item.code]; + return { + code: item.code, + status: getCenterProjectStatus(current.status) + } + }) + + const arr = []; + for (let i = 0; i <= 4; i++) { + const temp = tempItems.slice(i * 4, (i + 1) * 4); + let tempArr = temp.map(item => item.status) + if (i === 4) { + tempArr = examSubject == 2 + //bit36-bit39保留 + ? tempArr.concat(['00', '00']) + //bit30-bit39保留 + : tempArr.concat(['00', '00','00']) + } + // if (i === 3 && examSubject == 3) { + // tempArr = tempArr.concat(['00']) + // } + + arr.push(tempArr.join('')); + } + return arr + } + // 获取考试项目详情 + getProjectInfo = (projectCode) => { + const judgeUI = this.judgeUI; + return judgeUI.projectsObj[projectCode] + } + // 获取模型数据 + getModelData = (modelName) => { + const modelPath = this.modelPath + const fileModel = this.fileModel; + const modelData = fileModel.getModelContent(modelPath, modelName); + return modelData + } + // 过程照片拍照 + getPhoto = async (empty?: boolean) => { + const singlePlay = globalThis.singlePlay + //单机模式返回空照片 + if (singlePlay) { + return '' + } else { + const {filePhoto} = this; + const photoBase64 = await filePhoto.getPhoto(); + console.info(judgeTag, '拍照完成') + return photoBase64 + } + } + //人工操作项目 + public setJudgeItem = async (itemno, type: 1 | 2) => { + const {fileLog} = this; + await examJudgeArtificialItem(itemno * 1, type); + await fileLog.setExamJudgeData({ + method: 'examJudgeArtificialItem', + itemno: itemno * 1, + type + }) + console.info(judgeTag, `人工评判${type == 1 ? '进入' : '取消'}项目-${itemno}`) + } + + //人工扣分 + public setJudgeMark = async (itemno, serial, type = 1) => { + const {fileLog} = this + await examJudgeArtificialMark(itemno * 1, serial, type); + console.info(judgeTag, `进入人工扣分-${itemno}-${serial}`) + await fileLog.setExamJudgeData({ + method: 'examJudgeArtificialMark', + itemno: itemno * 1, + serial, + type + }) + + console.info(judgeTag, `人工扣分-${itemno}-${serial}`) + } + // 断网数据补传 + uploadDisConnectData = async () => { + const {isJudgeDisConnect,fileLog,fileUtil} = this; + if (!isJudgeDisConnect) { + return + } + const folderPath = fileLog.folderPath + const examDataStr = await fileUtil.readFile(`${folderPath}/wuxi_dis_progress_data.txt`); + const examDataArr = examDataStr.split('\n'); + for (let examDataStr of examDataArr) { + const examData = JSON.parse(examDataStr) + const code = await writeObjectOut(examData); + } + } + //上传无锡所过程数据 + uploadProgressData = async () => { + const {judgeUI,fileUtil,fileLog} = this; + const {idCard,startFullTime} = judgeUI + const carInfo = globalThis.carInfo; + const {carId,examinationRoomId} = carInfo + const folderPath = fileLog.folderPath + const base64 = new util.Base64(); + const time = await getCurrentTime(); + const endTime = await getCurrentTime(1) + let examDataBase64 + //@ts-ignore + //TODO try catch报错待优化 + const examDataStr: string = await fileUtil.readFile(`${folderPath}/wuxi_progress_data.txt`); + try { + let tempBuff = buffer.alloc(examDataStr.length, examDataStr) + let examData: Uint8Array = new Uint8Array(tempBuff.buffer) + examDataBase64 = base64.encodeToStringSync(examData) + } catch (e) { + console.info(judgeTag, JSON.stringify(e)) + } + console.info(judgeTag, '过程数据文件上传 start') + await uploadExamProgressData({ + time, + carId, + examinationRoomId, + examData: examDataBase64, + type: 1, + cardNo: idCard, + examStartTime: startFullTime, + examEndTime: endTime, + }) + console.info(judgeTag, '过程数据文件上传 end') + } + //获取科目三的评判初始化配置 + getKm3JudgeInitConfig = async () => { + const {judgeUI,getModelData} = this; + const {mapPointArr,mapPointItemArr} = judgeUI; + return { + map_point: mapPointArr, + map_point_item: mapPointItemArr, + //科目三暂时为空 + iteminfo: [], + roads: getModelData('km3/Roads.txt'), + sharps: getModelData('km3/Sharps.txt') + } + } + // 处理udp plc信号 + handleUdp = async (msg) => { + console.info('plc信号', msg) + const {fileLog,getPlcData,usbService,isUdpEnd,isExamEnd,judgeUI} = this + const stachArr = msg.split(',') + if (stachArr[0] != '#DN_GD' || isUdpEnd) { + return + } + const plcData = await getPlcData(msg); + // 4.过程数据 + await fileLog.setExamJudgeData(plcData) + //检测到有无锡所设备接入,需要发送特定的数据,供检测 + if (usbService.isWXUSBDevice) { + const str = await senorToWXDataStr(msg); + usbService.sendUSB(str) + } + // this.judgeUI.isDwztRight = (plcData.gps.dwzt == 4 && plcData.gps.jdzt == 3); + const param350 = judgeUI.judgeConfigObj['350'] + //@ts-ignore + this.judgeUI.sd = ((param350 == 0? plcData.gps.sd :plcData.sensor.cs) as number * 1.852).toFixed(0) + '' + this.judgeUI.dw = (Math.floor(plcData.sensor.dw as number) || 0) + '' + //TODO 暂时关闭差分检测异常 + // await this.checkDwzt(plcData.gps.dwzt,plcData.gps.jdzt); + if(!isExamEnd){ + await examJudgeRealExam(plcData) + } + const udpIndex = globalThis.udpIndex; + let [prevJd,preWd] = [0,0] + if (udpIndex % 5 === 0 && !isUdpEnd) { + const judgeUdp = globalThis.judgeUdp + const bytes = await this.getMessageHeartbeat(isExamEnd); + judgeUdp.send(bytes) + } + globalThis.udpIndex += 1 + } + // 处理特殊参数配置 + handleSEP = async (code: number) => { + const {judgeUI:{ + judgeConfigObj + },avPlayer} = this; + const {examSubject} = globalThis.carInfo; + + switch (code) { + //结束考试方式 + case 306: + if (judgeConfigObj[code] == 5) { + //靠边停车 + avPlayer.playAudio(['voice/406001.mp3']) + } + break; + } + } + // 获取plc数据 + getPlcData = async (plc: string) => { + const {fileLog,mndgStr,rmndg} = this; + await fileLog.setPlcProgressData(plc) + //plc字符串转化成评判初始化数据 + const tempData = await plcStrToJson(plc); + //模拟灯光回放时刻 + tempData.sensor.rmndg = rmndg; + //模拟灯灯光灯光项目 + tempData.sensor.mndg = mndgStr; + //plc字符串转化成无锡所过程数据 + const wuXiDataStr = await plcStrToWXJson(plc) + this.plcData = tempData + await fileLog.setExamJudgeWuxiProgressData(wuXiDataStr) + this.tempData = tempData + this.plcStr = plc; + this.mndgStr = ''; + this.rmndg = 0; + globalThis.msgStr = plc + + return tempData + } + + // 处理轨迹plc信号 + handleTrajectoryUdp = async (strArr) => { + const {fileLog,setJudgeItem,setJudgeMark,endExam} = this; + let num = 2; + const judgeTimer = setInterval(async () => { + const msgStr = strArr[num]; + if(msgStr == ''){ + console.info(judgeTag, '模拟数据考试结束') + globalThis.windowClass.setWindowSystemBarEnable(['navigation']) + clearInterval(judgeTimer) + this.checkExamIsEnd(true) + return + } + const msg = JSON.parse(strArr[num]); + num++ + // 4.过程数据 + this.tempData = msg + this.judgeUI.isDwztRight = (msg?.gps?.dwzt == 4 && msg?.gps?.jdzt == 3); + this.judgeUI.sd = Math.floor(msg?.gps?.sd * 1.852) + ''; + this.judgeUI.dw = Math.floor(msg?.sensor?.dw) + '' + this.plcData = msg + // this.judgeUI.isDwztRight = msg.gps.dwzt == 4; + globalThis.msgStr = '' + if (msg.method === 'examJudgeArtificialItem') { + setJudgeItem(msg.itemno, msg.type) + } + if (msg.method === 'examJudgeArtificialMark') { + setJudgeItem(msg.itemno, msg.serial) + } + await examJudgeRealExam(msg) + const bytes = await this.getMessageHeartbeat(); + bytes && globalThis.judgeUdp.send(bytes) + + }, 200) + + globalThis.judgeTimer = judgeTimer; + } + // 统计必考项目、所有项目、已考数量 + setCountItems = async () => { + const carInfo = globalThis.carInfo; + const { examSubject} = carInfo; + const {projectsObj} = this.judgeUI; + //必考项目数量 必考项目已考数量 + let projectNum = 0, endProjectsNum = 0; + // 所有考试项目数量 项目已考项目数量 + let allProjectNum = 0, allEndProjectsNum = 0; + Reflect.ownKeys(projectsObj).forEach(projectKey => { + const {type,isRequired} = projectsObj[projectKey]; + allProjectNum += 1; + if (type == 3 || type == 4) { + allEndProjectsNum += 1; + } + + if (isRequired) { + projectNum += 1; + if (type == 3 || type == 4) { + endProjectsNum += 1; + } + } + }) + console.info(judgeTag,'项目状态projectsObj:' + JSON.stringify(projectsObj)); + console.info(judgeTag,'所有考试项目数量:' + allProjectNum) + console.info(judgeTag,'必考项目数量:' + projectNum) + console.info(judgeTag,'必考项目已考数量:' + endProjectsNum) + //必考项目除靠边停车是否全部完成 + this.judgeUI.isRequiredProjectsEnd = (projectNum - endProjectsNum === 0) + this.judgeUI.isAllProjectsEnd = (allProjectNum - allEndProjectsNum === 0) + } + // 模拟灯光 + setMndg = async (mndgStr: string) => { + this.mndgStr = mndgStr + } + + // 检测差分状态 + checkDwzt = async (type) => { + const {avPlayer} = this; + const judgeConfig = this.judgeUI.judgeConfig; + switch (type){ + case 0: + this.judgeUI.isDwztRight = true; + break; + + case 1: + this.judgeUI.dwztErrorVisible = true; + avPlayer.playAudio([`voice/差分状态异常.mp3`],true) + setTimeout(()=>{ + router.back() + },3000) + break; + + case 2: + avPlayer.playAudio([`voice/差分状态异常.mp3`],true); + + break; + case 3: + this.judgeUI.dwztErrorVisible = true; + avPlayer.playAudio([`voice/差分状态异常.mp3`],true); + break; + + case 4: + this.judgeUI.isDwztRight = false; + //差分异常上报 + break; + } + } + + + closeAllFiles = ()=>{ + setTimeout(()=>{ + this.fileLog.closeAllFiles() + },1000) + } + + public plcStr: string + private judgeUI + private fileLog + private filePath + private totalScore: number + private prevJd: number = 0 + private prevWd: number = 0 + private dwztNum:number = 0 + private folderPath: string + private modelPath: string + private avPlayer + private carztStr: string + private rmndg: 0 | 1 + private mndgStr: string | undefined + private xmmcStr: string + private xmmcCode: string + private xmmcSingleCode: number + private xmmcEndCode?:number + private xmdm: string | number + private xmxh: string + private fileModel: FileModel + private filePhoto: FilePhoto + private usbService: UsbService + //是否是考试模式 + private isExam: boolean + //考试是否结束了 + private isExamEnd: boolean + // 是否发送udp + private isUdpEnd: boolean = false + //是否手动结束考试 + private isManual: boolean + //UDP服务序列号 + private serialIndex: number + private fileUtil: FileUtil + private judgeTask: JudgeTask + private tempData: any + private performInfo: any + private isEndTip:boolean = false; + private deductedPopShowTimer:number = 0; + private ksjs: { + // 累计前进距离 + qjjl: number, + // 累计倒车距离 + dcjl: number + d1: number + d2: number + d3: number + d4: number + d5: number + d6: number + } + private kfArr: { + //项目名称 + xmmcStr: string, + xmdm: string | number, + //扣分描述 + desc: string, + //扣分 + score: string + //无锡所扣分代码 + markcatalog: string + markserial: string + kfxh: string + type: 0| 1 | 2 + }[] + private km2ItemsStatus: any[] + //所有的科目考试项目(大车&小车) + private testKmItems: any + + private plcData: any + + //当前科目二的考试项目 + private currentKm2ItemsObj: any + //本地轨迹回放地址 + private trajectoryPath: string + private isTrajectoryOpen: boolean; + // 调代理接口是否断网了 + private isJudgeDisConnect: boolean; + private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11] + private lane: LANE = { + road: '', num: 0, count: 0 + } + private videoData:any + private disConnectNum:number = 0; + +} \ No newline at end of file