import systemTime from '@ohos.systemDateTime'; import router from '@ohos.router'; import util from '@ohos.util'; import buffer from '@ohos.buffer'; import { testKmItems, testMarkRules } from './dataTest/index'; import { EXAMDATA, SOUND } from './api/judgeSDK'; import VoiceAnnounce from './utils/voice-announcements'; import FileModel from './utils/file-model'; import FilePhoto from './utils/file-photo'; import FileUtil from '../../common/utils/File'; import FileLog from '../judgeSDK/utils/file-log'; import JudgeTask from './utils/judge-task'; import SimulateLights from './utils/simulate-lights'; import { judgeConfig } from './utils/judge-config'; import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; import { Array2Byte, convertGpsCoord2, deepClone, fillZero, getCurrentTime, string2Bytes, stringToASC } from '../../common/utils/tools'; import { getCarStatus, getCarStatusType, getCenterProjectStatus, getKmProjectVoice, getTranslateSignals, plcStrToJson, plcStrToWXJson, promptWxCode, senorToWXDataStr } from './utils/judge-common'; import { examJudgeArtificialItem, examJudgeArtificialMark, examJudgeBeginExam, examJudgeEndExam, examJudgeInit, examJudgeMapSetParam, examJudgeMapSetScaling, examJudgeRealExam, examJudgeSetLogCallback, examJudgeSetPerformCallback, examJudgeSetRealExamCallback } from './api/index'; import UsbService from '../../common/service/usbService'; import Prompt from '@system.prompt'; const judgeTag = 'SURENJUN_JUDGE' export default class Judge { // 过程照片拍照 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) => { const {fileLog} = this await examJudgeArtificialItem(itemno * 1); await fileLog.setExamJudgeData({ method: 'examJudgeArtificialItem', itemno: itemno * 1, type: 1 }) console.info(judgeTag, `人工评判进入项目-${itemno}`) } //人工扣分 public setJudgeMark = async (itemno, serial) => { const {fileLog} = this await examJudgeArtificialMark(itemno * 1, serial); await fileLog.setExamJudgeData({ method: 'examJudgeArtificialMark', itemno: itemno * 1, serial }) 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 {carinfoArrr,mapPointArr,mapPointItemArr,systemparmArr} = judgeUI; return { carinfo: carinfoArrr, map_point: mapPointArr, systemparm: systemparmArr, 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} = this const stachArr = msg.split(',') const {isEnd} = this; if (stachArr[0] != '#DN_GD' || isEnd) { return } const plcData = await getPlcData(msg); // 4.过程数据 await fileLog.setExamJudgeData(plcData) await examJudgeRealExam(plcData) const udpIndex = globalThis.udpIndex; if (udpIndex % 5 === 0) { const judgeUdp = globalThis.judgeUdp const bytes = await this.getMessageHeartbeat(); 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; } } public plcStr: string private judgeUI // 更改考试状态 goVoiceAnnounce = async (event, xmdm, kf, xmjs) => { const {projectsObj,judgeConfigObj} = this.judgeUI; const {beginProject,pointsDedute,endProject,avPlayer,uploadProgressPhoto,judgeTask,handEndExam} = this; const xmhg = xmjs.xmhg const kfLen = kf.length //不报语音的项目列表 const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') switch (event) { // 项目开始 case 1: const code = projectsObj[xmdm].projectCodeCenter; const kmCode = getKmProjectVoice(code, 1) if (!ignoreVoiceCodeArr.includes(code)) { kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`]) } await judgeTask.addTask(async () => { console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`) await beginProject(xmdm) // console.info(judgeTag,'上传照片 start') await uploadProgressPhoto(xmdm) }) break; // 项目结束 case 2: const endCode = projectsObj[xmdm].projectCodeCenter; const endKmCode = getKmProjectVoice(endCode, 2) if (!ignoreVoiceCodeArr.includes(endCode)) { endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) } await judgeTask.addTask(async () => { console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`) await endProject(xmdm) }) break; // 扣分 case 3: avPlayer.playAudio([`voice/${kf[kfLen -1].markcatalog}.mp3`]) await judgeTask.addTask(async () => { console.info(judgeTag, `项目扣分-${kf[kfLen -1].markcatalog}-${kf[kfLen -1].desc}`) await pointsDedute(kf[kfLen -1].xmdm, kf[kfLen -1]) }) break; // 考车状态 case 4: break // 考试结束 case 5: clearInterval(globalThis.judgeTimer) await judgeTask.addTask(async () => { console.info(judgeTag, '考试结束 start') await handEndExam() }) break default: break } } private fileLog private totalScore: number private folderPath: string private modelPath: string private avPlayer private carztStr: string private rmndg: 0 | 1 private wav: 0 | 1 private mndgStr: string | undefined // 模拟灯光 setMndg = async (mndgStr: string) => { this.mndgStr = mndgStr this.rmndg = 1; } private xmmcStr: string private xmmcCode: string private xmmcSingleCode: number private xmdm: string | number private xmxh: string private fileModel: FileModel private filePhoto: FilePhoto private usbService: UsbService //是否是考试模式 private isExam: boolean //考试是否结束了 private isEnd: boolean //UDP服务序列号 private serialIndex: number private fileUtil: FileUtil private judgeTask: JudgeTask private tempData: any private performInfo: any private ksjs: { // 累计前进距离 qjjl: number, // 累计倒车距离 dcjl: number } private kfArr: { //项目名称 xmmcStr: string, xmdm: string | number, //扣分描述 desc: string, //扣分 score: string //无锡所扣分代码 markcatalog: string markserial: string kfxh: string }[] private plcData: any // 获取plc数据 getPlcData = async (plc: string) => { const {fileLog,mndgStr,rmndg,wav} = this; await fileLog.setPlcProgressData(plc) //plc字符串转化成评判初始化数据 const tempData = await plcStrToJson(plc); //模拟灯光回放时刻 tempData.sensor.rmndg = rmndg; //模拟灯光单个灯光结束时刻 tempData.sensor.wav = wav; //模拟灯灯光灯光项目 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; this.wav = 0; globalThis.msgStr = plc return tempData } // 处理轨迹plc信号 handleTrajectoryUdp = async (strArr) => { const {fileLog} = this; let num = 2; const {usbService} = this; const judgeTimer = setInterval(async () => { const msg = JSON.parse(strArr[num]); await fileLog.setExamJudgeData(msg) if (!msg) { console.info(judgeTag, '模拟数据考试结束') examJudgeEndExam(); globalThis.windowClass.setWindowSystemBarEnable(['navigation']) clearInterval(judgeTimer) return } // 4.过程数据 this.tempData = msg this.plcData = msg globalThis.msgStr = '' const str = await senorToWXDataStr(msg); //检测到有无锡所设备接入,需要发送特定的数据,供检测 if (usbService.isWXUSBDevice) { usbService.sendUSB(str) } await examJudgeRealExam(msg) num++ }, 200) globalThis.judgeTimer = judgeTimer; } private km2ItemsStatus: any[] //所有的科目考试项目(大车&小车) private testKmItems: any //处理评判过程回调 handleRealExam = async (strData, callBack) => { // console.log('过程数据:' + strData); let examData: EXAMDATA = JSON.parse(strData); const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,judgeUI} = this; const {carzt,xmks,kf,event,xmjs,ksjs,sound,mndg} = examData //获取项目结束、项目开始代码 const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; switch (event) { //项目开始 case 1: judgeUI.projectsObj[xmdm].type = '2'; 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.xmdm = xmdm; this.xmxh = xmxh; break; //项目结束 case 2: judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3'); this.xmmcStr = '无'; this.xmmcCode = ''; this.xmmcSingleCode = 0; this.xmdm = ''; 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 }) this.judgeUI.totalScore += thisKf.score * 1; break; //考车状态 case 4: this.carztStr = getCarStatus(carzt); break; //考试结束 case 5: this.ksjs = ksjs; break; //项目取消 case 6: break; //语音播放和提示 case 7: goJudgeVoice(sound) break; //模拟灯光事件 case 8: setMndg(mndg) break; default: ;break; } const {xmmcStr,carztStr,kfArr} = this; await callBack({ //项目名称 考车状态 扣分arr xmmcStr, carztStr, kfArr }); //语音播报 this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs) //更新UI if (event == 1 || event == 2 || event == 3) { const copyProjectsObj = this.judgeUI.projectsObj; judgeUI.projectsObj = deepClone(copyProjectsObj) } } //当前科目二的考试项目 private currentKm2ItemsObj: any //本地轨迹回放地址 private trajectoryPath: string private isTrajectoryOpen: boolean; // 调代理接口是否断网了 private isJudgeDisConnect: boolean; // 项目开始接口同步 beginProject = async (ksxm) => { const carInfo = globalThis.carInfo; const { examSubject,plateNo } = carInfo; const {judgeUI,fileLog,getSbbm,xmxh} = this; const {lsh,idCard,serialNumber,projectsObj,ksdd,kslx} = 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, kchp: encodeURI(plateNo), // 开始时间 ksdd: encodeURI(ksdd), ksxl: encodeURI(kslx) || '', kssj: time } } const code = await writeObjectOut(data) // console.info(judgeTag,'项目开始 end') if (code === 2300007) { this.isJudgeDisConnect = true; } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) 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} = this; const {lsh,idCard,serialNumber,projectsObj,cdsbInfoObj,ksdd,kslx} = judgeUI const time = await getCurrentTime(); const project = projectsObj[ksxm] const sbxh = getSbbm(ksxm, xmxh) const data = { xtlb: '17', jkxlh: serialNumber, jkid: '17C55', drvexam: { lsh, kskm: examSubject, sfzmhm: idCard, ksxm: project.projectCodeCenter, sbxh, //操作类型 1:正常 0:撤销该考试记录 czlx: '1', kchp: encodeURI(plateNo), ksdd: encodeURI(ksdd), ksxl: encodeURI(kslx) || '', jssj: time } } const code = await writeObjectOut(data) if (code === 2300007) { this.isJudgeDisConnect = true; } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) // 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} = this; const {lsh,idCard,serialNumber,ksdd} = judgeUI const time = await getCurrentTime(); const project = getProjectInfo(ksxm); const data = { xtlb: '17', jkxlh: serialNumber, jkid: '17C53', drvexam: { lsh, kskm: examSubject, // 通用评判科二10000,科三30000 ksxm: project ? project.projectCodeCenter : 10000, kfxm: kf.markcatalog, kfxmmx: `${ksxm},${kf.markserial}`, sfzmhm: idCard, kchp: encodeURI(carInfo.plateNo), //1:自动 2:人工 kffs: 1, ksdd: encodeURI(ksdd), kfsj: time } } const code = await writeObjectOut(data); if (code === 2300007) { this.isJudgeDisConnect = true } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) console.info(judgeTag, '项目扣分 end') promptWxCode('17C53', code) } // 考试过程照片 uploadProgressPhoto = async (ksxm) => { const time = await getCurrentTime(); const {judgeUI,plcData,getPhoto,fileLog} = this; const photoBase64 = await getPhoto(); const carInfo = globalThis.carInfo; const { examSubject,plateNo,carNo } = carInfo; const {lsh,idCard,serialNumber,projectsObj,ksdd} = 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: encodeURIComponent(photoBase64), cs: Math.ceil(gps.sd * 1.852), ksdd: encodeURI(ksdd) } }; const code = await writeObjectOut(data); if (code === 2300007) { this.isJudgeDisConnect = true } promptWxCode('17C54', code) fileLog.setExamJudgeWuxiData(data) console.info(judgeTag, '上传照片 end') } constructor(judgeUI) { this.serialIndex = 1; this.judgeUI = judgeUI //语音播放工具 this.avPlayer = new VoiceAnnounce(); new SimulateLights(this.avPlayer) //模型工具 this.fileModel = new FileModel(judgeUI.context); //文件工具 this.fileUtil = new FileUtil(judgeUI.context) this.judgeTask = new JudgeTask() const mediaTest = new FilePhoto(judgeUI.context); this.usbService = new UsbService(); this.filePhoto = mediaTest this.kfArr = judgeUI.kfArr this.xmmcStr = ''; this.xmmcCode = ''; this.carztStr = ''; this.testKmItems = {}; // 考试回放配置 const {isTrajectoryOpen,modelPath,trajectoryPath} = judgeConfig this.isTrajectoryOpen = isTrajectoryOpen; this.modelPath = modelPath; this.trajectoryPath = trajectoryPath; this.isExam = !globalThis.singlePlay; const {projectsCenterObj} = judgeUI //科目三待修改 testKmItems.forEach(item => { this.testKmItems[item.code] = item; //考试项目存在 if (projectsCenterObj[item.code]) { this.testKmItems[item.code] = { code: item.code, status: 1 } } }) this.isEnd = false; } public async onJudgeFn(fn: Function) { await this.judging(fn) } // 评判语音提示 goJudgeVoice = async (sound: SOUND) => { const {avPlayer} = this; const {xmdm,code} = sound; //判断是不是模拟灯光语音 const isLight = code.slice(0, 3) === '417'; if (isLight) { console.info(judgeTag, '模拟灯光开始播放:' + code) } avPlayer.playAudio([`voice/${code}.mp3`], true, () => { if (isLight) { console.info(judgeTag, '播放结束:' + code) setTimeout(() => { this.wav = 1; }) } }) } // 处理考试结束 public handEndExam = async (isManual?: Boolean) => { const {isExam,judgeUI,endExam,handleSEP,avPlayer} = this; const {judgeConfigObj,totalScore} = judgeUI if (judgeConfigObj['344'] == 1) { Prompt.showToast({ message: '考试未结束,不允许手动退出!', duration: 4000 }); return } await handleSEP(306); avPlayer.playAudio(['voice/exam_waiting.mp3'], true) this.isEnd = true try { const bytes = await this.getMessageHeartbeat(true); const singlePlay = globalThis.singlePlay singlePlay || globalThis.judgeUdp.send(bytes) //结束评判函数 await examJudgeEndExam(); globalThis.isJudge = false await endExam(isManual) } catch (e) { setTimeout(() => { router.back(); }, 3000) } } // 当前项目转换 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 } } // 考试结束 public endExam = async (isManual?: Boolean) => { const carInfo = globalThis.carInfo; const deviceNo = globalThis.deviceNo; const { examSubject ,plateNo} = carInfo; const {judgeUI,fileLog,ksjs,getPhoto,uploadProgressData,uploadDisConnectData,avPlayer} = this; const {lsh,idCard,serialNumber,kssycs,totalScore} = judgeUI await uploadDisConnectData(); const time = await getCurrentTime(); const photoBase64 = await getPhoto(); const data = { xtlb: '17', jkxlh: serialNumber, jkid: '17C56', drvexam: { lsh, kchp: encodeURI(plateNo), kskm: examSubject, sfzmhm: idCard, //@ts-ignore zp: encodeURIComponent(photoBase64), jssj: time, kscj: (totalScore * 1) > 0 ? totalScore : 0, kslc: (ksjs?.qjjl + ksjs?.dcjl) || 0, dwlc: '', } } const code = await writeObjectOut(data); promptWxCode('17C56', code) console.info(judgeTag, '考试结束 end') if (!isManual) { if (totalScore < 80) { judgeUI.loadingPopupVisible = true if (kssycs == 1) { avPlayer.playAudio(['voice/unqualified_one.wav'], true) } else { avPlayer.playAudio(['voice/unqualified_two.wav'], true) } } else { avPlayer.playAudio(['voice/qualified.mp3'], true) } } console.info(judgeTag, `考试成绩:${totalScore}`) fileLog.setExamJudgeWuxiData(data) await uploadProgressData(); setTimeout(() => { router.back(); }, 3000) } // 获取评判初始化数据 getJudgeInitData = async () => { const {getModelData,getKm3JudgeInitConfig} = this const carInfo = globalThis.carInfo; const { examSubject,plateNo,carId } = carInfo; const {fileLog} = this const judgeUI = this.judgeUI const {projectsObj,cdsbInfoObj,markRuleListObj,carType,carName} = judgeUI const examType = examSubject == 2 ? 'km2' : 'km3' let allitems = []; if (examSubject == 2) { allitems = Reflect.ownKeys(cdsbInfoObj).map(cdsbKey => { const cdsb = cdsbInfoObj[cdsbKey]; const {xmdm,xmxh,modelKey} = cdsb return { xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`) } }) } const initInfo = { kskm: examSubject * 1, kchp: plateNo, kchm: carId * 1, kscx: carType, cxcode: '1', name: carName, carmodel: getModelData(`${examType}/${carType}.txt`), allitems, mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, sysset: judgeUI.judgeConfig, }; let km3Config = {} if (examSubject) { km3Config = await getKm3JudgeInitConfig(); } // 获取科目三的评判配置 console.info(judgeTag, '3.获取评判初始化数据完成') return { ...initInfo, ...km3Config, } } // 消息心跳发送 getMessageHeartbeat = async (isEnd?: Boolean) => { console.log('kkkkkkmmm') const carInfo = globalThis.carInfo; const { examSubject,plateNo,ksyh } = carInfo; // const ksyh='0000000000000' // const ksyh=globalThis.ksyh ||'0000000000000' const { judgeUI, isExam, serialIndex, tempData, xmmcCode, xmxh, xmmcSingleCode, xmdm, performInfo, kfArr, getTranslateProject, getSbxh } = this; const {lsh,startHourTime,totalScore} = judgeUI; const examType = isExam ? examSubject : 0; const {sensor,gps} = tempData; const {zfxd,yfxd,shtd,ygd,jgd,skd,dh1,dh2,lhq,jsc,ssc,fsc,lb,mkg,aqd,ygq,cs,fdjzs} = sensor const {jd,wd, hxj, fyj, hbg,} = gps const translateProject = getTranslateProject(); const sbxh = getSbxh(xmdm, xmxh) console.log('sbxhsbxh', sbxh) const {carzt,dcjl,qjjl,dxjl,bxjl} = performInfo; console.log('performInfo', JSON.stringify(performInfo)) // const asclshArr = stringToASC(lsh); const asclshArr = stringToASC(fillZero('0000000000000' || 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, 0, 0, 0, 0].concat(getCarStatusType(carzt)).concat([ygq, sensor.wd, 0]) ) console.log('jinweidu111jdwd0') //@ts-ignore const translateJd = convertGpsCoord2(wd).toFixed(7) * Math.pow(10, 7); //@ts-ignore const translateWd = convertGpsCoord2(jd).toFixed(7) * Math.pow(10, 7) console.log('jinweidu111jdwd') //@ts-ignore const translateProjects = translateProject.map(numStr => string2Bytes(parseInt(numStr, 2), 8)[0]) //@ts-ignore // const translateProjects= translateProject.map(num => string2Bytes(p,8)[0]) console.log('jinweidu2222', `${examType}${startHourTime}`) const arr = [ //考生号 TODO 考试员号 asclshArr.map(lsh => string2Bytes(lsh, 8)[0]), //考试员号 ascksyhArr.map(ksyh => string2Bytes(ksyh, 8)[0]), //科目类型(0:未考试 1:科目二 2:科目三) + 考试开始时间 string2Bytes(`${examType}${startHourTime}`, 4 * 8), // TODO 消息序号从1开始,0结束 string2Bytes(isEnd ? 0 : serialIndex, 2 * 8), /*左向灯 右向灯 双跳灯 远光灯 近光灯 视宽灯 点火1 点火2 离合器 脚刹 手刹 副刹 喇叭 门开关 安全带 档位 车辆状态 雨刮器 雾灯 0*/ translateSignals, //速度 发动机转速 GPS纬度 GPS经度 主天线位置 //@ts-ignore string2Bytes(cs, 2 * 8), string2Bytes(fdjzs / 60, 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 + 90) * 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), //扣分数 //todo扣分值/扣分项 string2Bytes(0, 2 * 8), //扣分项数量 string2Bytes(kfArr.length, 8), //n个扣分序号 kfArr.map(kf => string2Bytes(kf.kfxh, 8)[0]) ] let tempArr = []; arr.forEach(itemArr => { tempArr = tempArr.concat(itemArr) }) this.serialIndex += 1; return Array2Byte(tempArr) } // 获取开始考试数据 getJudgeBeginData = async () => { const {code,name:examinerName} = globalThis.examinerInfo; const {isExam,isTrajectoryOpen} = this; const judgeUI = this.judgeUI const {projects,carType,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr} = 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: 1, sfyk: 0, ykkkcs: 1, //TODO 考试路线待修改 wayno: 3, czlx: 0, kskssj: await systemTime.getCurrentTime(), ksxm: projects.map(project => { return { xmdm: project.projectCode * 1, xmxh: '', } }), //断点续考 ddxk: isDdxk ? 1 : 0, ddkssj: ddxkTime, ykxm: isDdxk ? (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) : [], kfxm: isDdxk ? (ddxkKfArr?.map(kf => { const [xmdm, kfdm] = kf.split(',') return { xmdm: xmdm * 1, kfdm } })) : [], yklc: 0, special: [], //TODO 科目三参数临时写死 sczb: 0, sczbkf: [], dmndg: false, nitem1: false, nitem41: false, mfxx: false, mfxxn: false } console.info(judgeTag, '5.获取开始考试数据完成') return beginInfo } //获取场地序号 getSbxh = (ksxm, xmxh) => { const {judgeUI} = this; const {cdsbInfoObj,projectsObj} = judgeUI; const project = projectsObj[ksxm] if (project === undefined) { return '00000000' } const projectType = project.sbxh; const projectKey = `${ksxm}_${xmxh}`; const currentCdsb = cdsbInfoObj[projectKey] || {}; const sbxh = currentCdsb.sbbh || '00000000' return sbxh } getSbbm = (ksxm, xmxh) => { const {judgeUI} = this; const {cdsbInfoObj,projectsObj} = judgeUI; const project = projectsObj[ksxm] if (project === undefined) { return '00000000' } const projectKey = `${ksxm}_${xmxh}`; const currentCdsb = cdsbInfoObj[projectKey] || {}; const sbxh = currentCdsb.sbbm || '00000000' return sbxh } // 中心所有项目转换 getTranslateProject = () => { // const {testKmItems} = this; const tempItems = testKmItems.map(item => { const current = this.testKmItems[item.code]; return { code: item.code, status: getCenterProjectStatus(current.status) } }) const len = Math.floor(tempItems.length / 8); const arr = []; for (let i = 0; i <= len; i++) { const temp = tempItems.slice(i * 8, (i + 1) * 8); let tempArr = temp.map(item => item.status) if (i === 4) { tempArr = tempArr.concat(['00', '00']) } arr.push(tempArr.join('')); } return arr.map(numStr => parseInt(numStr, 2)); } // 获取考试项目详情 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 } //开始评判 private async judging(callBack: Function) { const {judgeUI} = this; const { name, lsh, idCard} = judgeUI; const fileLog = new FileLog(judgeUI.context); const filePath = await fileLog.initFileLogo({ name, lsh, idCard }); this.fileLog = fileLog; const {getJudgeBeginData,handleUdp,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(); //相关评判初始化只做一次 if (!isJudgeInitBool) { await fileLog.setExamJudgeData(initInfo) const tempJudge = await examJudgeInit(initInfo); globalThis.isJudgeInitBool = true console.info(judgeTag, '4.评判初始化完成') } else { await fileLog.setExamJudgeData(initInfo) } 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 this.judgeUI.jl = Math.ceil((performInfo.qjjl + performInfo.dcjl) / 100) }) // 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(['voice/ksks.WAV']) await examJudgeMapSetParam(640, 480); //设置参数宽、高 await examJudgeMapSetScaling(120); //设置缩放比例,一般默认填100(就是100%的意思) ,数字越大视野越大,数字越小视野越小,不能为0 this.judgeUI.draw = true // 处理轨迹plc信息 if (isTrajectoryOpen) { handleTrajectoryUdp(strArr); return } // 处理实时udp里的plc信号 globalThis.udpClient.onMessage(async (msg) => { handleUdp(msg) }) } }