From b82d3ff6bcd25e556b1e3bd1ad26c4cc80b6daf8 Mon Sep 17 00:00:00 2001 From: wangzhongjie Date: Tue, 2 Jul 2024 10:42:53 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=86=99=E6=B3=95=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/pages/UserInfo.ets | 125 +- entry/src/main/ets/pages/judgeSDK/judge.ts | 1506 ++++++++++---------- 2 files changed, 852 insertions(+), 779 deletions(-) diff --git a/entry/src/main/ets/pages/UserInfo.ets b/entry/src/main/ets/pages/UserInfo.ets index 91763253..fe4bae67 100644 --- a/entry/src/main/ets/pages/UserInfo.ets +++ b/entry/src/main/ets/pages/UserInfo.ets @@ -1,22 +1,21 @@ -import { getExaminationItem, getExaminationStudentInfo, examinationStuAbsent, getPhotosForOther } from '../api/userInfo' -import router from '@ohos.router' -import TopLogo from './compontents/TopLogo' +import { examinationStuAbsent, getExaminationItem, getExaminationStudentInfo } from '../api/userInfo'; +import router from '@ohos.router'; +import TopLogo from './compontents/TopLogo'; import Md5 from '../common/utils/md5'; import AccountTable from '../common/database/tables/AccountTable'; import USER from '../common/constants/USER'; -import { dateFormat, getCurrentTime } from '../common/utils/tools'; +import { dateFormat, getCurrentTime, string2Bytes } from '../common/utils/tools'; import MA_SYSSET from '../common//constants/MA_SYSSET'; -import FaceCompare from './compontents/FaceCompare' +import FaceCompare from './compontents/FaceCompare'; // import { initJudgeUdp } from '../common/utils/UdpJudge' -import { writeObjectOut } from '../api/judge' -import testNapi from "@ohos.idcard"; +import { writeObjectOut } from '../api/judge'; +import testNapi from '@ohos.idcard'; import common from '@ohos.app.ability.common'; -import { User } from './interfaces' -import WebRTCVoice from './webRTC/' -import promptAction from '@ohos.promptAction' -import { CandidateData, EmptyCandidateObject } from "../mock/CandidateData" -import {string2Bytes} from '../common/utils/tools' -import { getSyncData } from '../common/service/initable' +import { User } from './interfaces'; +import WebRTCVoice from './webRTC/'; +import promptAction from '@ohos.promptAction'; +import { CandidateData, EmptyCandidateObject } from '../mock/CandidateData'; + @Entry @Component struct UserInfo { @@ -38,9 +37,6 @@ struct UserInfo { @State currentUser: User = EmptyCandidateObject @State dataList: Array = [] @State list: Array = [] - private AccountTable = new AccountTable(() => { - }, USER); - private context = getContext(this) as common.UIAbilityContext; @State name: string = 'initName'; @State sex: string = ''; @State callBackFlag: boolean = false; @@ -57,9 +53,20 @@ struct UserInfo { @State signNum: number = 0; @State isCanClick: boolean = true; @State faceFlag: string = '0'; - @State FaceOpenStatue: string = '0';//是否开启人脸识别 + @State FaceOpenStatue: string = '0'; //是否开启人脸识别 subscriber; @State faceCatchImg: string = '' + private AccountTable = new AccountTable(() => { + }, USER); + private context = getContext(this) as common.UIAbilityContext; + private labelBlocks = [ + { label: '考生姓名', key: 'xm' }, + { label: '身份证号', key: 'sfzmhm' }, + { label: ' 流 水 号 ', key: 'lsh' }, + { label: '考试路线', key: 'kslx' }, + { label: '待考次数', key: 'kssycs' }, + { label: '考官姓名', key: 'ksy1' }, + ] async onPageShow() { //语音功能 @@ -75,8 +82,9 @@ struct UserInfo { this.heartMsg() } + //身份证读卡器初始化 - openDeviceByIDCard(){ + openDeviceByIDCard() { globalThis.indexComponent = this; // 应用启动时打开读卡设备 let ret = testNapi.OpenDevice(); @@ -86,11 +94,13 @@ struct UserInfo { console.error("zzctest Failed to Open Device"); } } - stopDeviceById(){ - if(this.faceFlag=='1'){ - testNapi&&testNapi.StopReadCard() + + stopDeviceById() { + if (this.faceFlag == '1') { + testNapi && testNapi.StopReadCard() } } + // 通过身份证获取当前学员 getCurrentStudent(id) { let flag = false @@ -126,6 +136,7 @@ struct UserInfo { }); } } + onReadCard(ret) { console.info(`zzctest xx Read Card ret =${ret.status}`) let thisVar = globalThis.indexComponent; @@ -182,7 +193,8 @@ struct UserInfo { changeQkfn() { this.qkFn() } - initData(){ + + initData() { this.stepFlag = false this.faceCompareSucess = 0 this.showFaceCompare = false @@ -207,21 +219,22 @@ struct UserInfo { } async heartMsg() { - globalThis.udpClient2&globalThis.udpClient2.setMsgCallBack((val)=>{ - if(val.id=='32'){ - globalThis.signNum=val.body[1] - if(val.body[0]=='7'){ + globalThis.udpClient2 & globalThis.udpClient2.setMsgCallBack((val) => { + if (val.id == '32') { + globalThis.signNum = val.body[1] + if (val.body[0] == '7') { //缺考处理 this.getqkFn() - this.signNum=val.body[1] + this.signNum = val.body[1] } - }else if(val.id=='42'){ + } else if (val.id == '42') { //收到中心缺考确认消息 - console.log('qkfnqkfn',val.body[0]) + console.log('qkfnqkfn', val.body[0]) this.qkFn() } }) } + //考点端查询缺考指令内容消息请求 getqkFn() { let tmpList = []; @@ -236,8 +249,6 @@ struct UserInfo { globalThis.udpClient2.sendMsg(param, this.context) } - - async initSysset() { const that = this; const db = new AccountTable(() => { @@ -251,13 +262,13 @@ struct UserInfo { const studentRefreshParam = syssetParams.filter(sys => sys.v_no === '452') that.studentRefreshStatue = studentRefreshParam?.[0]?.v_value || '0' const faceParam = syssetParams.filter(sys => sys.v_no === '2313') - that.FaceOpenStatue =faceParam?.[0]?.v_value=='3'? '1':'0' + that.FaceOpenStatue = faceParam?.[0]?.v_value == '3' ? '1' : '0' that.FaceOpenStatue = '0' - console.log('that.FaceOpenStatue',that.FaceOpenStatue) + console.log('that.FaceOpenStatue', that.FaceOpenStatue) // faceParam?.[0]?.v_value || // 1身份证读卡器 2指纹 3人脸 - this.faceFlag=faceParam?.[0]?.v_value ||'0' - if(faceParam?.[0]?.v_value=='1'){ + this.faceFlag = faceParam?.[0]?.v_value || '0' + if (faceParam?.[0]?.v_value == '1') { that.openDeviceByIDCard() } //0不自动更新 1自动更新(不限次数) 2没有考生更新2次 @@ -276,18 +287,19 @@ struct UserInfo { that.getExaminationStudentInfoFn() } }, 5000) - }else{ + } else { this.getExaminationItemFn() } }) }) } -//人脸比对窗口关闭 + + //人脸比对窗口关闭 changeFaceCompareSuccess() { console.log('this.faceCompareSuces', this.faceCompareSucess, JSON.stringify(this.currentUser)) if (this.faceCompareSucess > 0) { - //人脸比对通过 + //人脸比对通过 this.sfbdinterfaceFn() } } @@ -307,7 +319,8 @@ struct UserInfo { this.pageIndex--; this.dataList = this.list.slice(this.pageIndex * 4, this.pageIndex * 4 + 4) } -//获取下载考生 + + //获取下载考生 getExaminationStudentInfoFn() { if (globalThis.singlePlay) { return @@ -360,6 +373,7 @@ struct UserInfo { console.log('error12error' + error) }) } + qkFn() { this.faceCompareSucess = 0 if (globalThis.singlePlay) { @@ -396,9 +410,10 @@ struct UserInfo { }) } - async getExaminationItemFn(){ + + async getExaminationItemFn() { console.info('surenjun', this.currentUser.lsh) - if(!this.currentUser.lsh||globalThis.singlePlay){ + if (!this.currentUser.lsh || globalThis.singlePlay) { return } const carInfo = globalThis.carInfo; @@ -409,14 +424,15 @@ struct UserInfo { lsh: this.currentUser.lsh || '', examinationRoomId }); - if(examItems?.getExaminationItemRsp?.body?.kssycs!=0){ + if (examItems?.getExaminationItemRsp?.body?.kssycs != 0) { this.getExaminationStudentInfoFn() - }else{ - this.dataList=[] + } else { + this.dataList = [] this.currentUser = EmptyCandidateObject } } + //身份比对 async sfbdinterfaceFn() { this.stepFlag = true @@ -441,7 +457,7 @@ struct UserInfo { ksxtbh: this.ksxtbh || '222', sfzmhm: this.currentUser.sfzmhm || '', ksysfzmhm: this.currentUser.ksy1sfzmhm || '', - zp: encodeURIComponent((this.faceCatchImg||this.currentUser.kszp.substr(22)) || ''), + zp: encodeURIComponent((this.faceCatchImg || this.currentUser.kszp.substr(22)) || ''), kssj: dateFormat(date) || '', kchp: decodeURI(plateNo), Ksy2sfzmhm: this.currentUser.ksy2sfzmhm || '' @@ -491,14 +507,18 @@ struct UserInfo { this.stepFlag = false } } + aboutToDisappear() { this.outClick() } + outClick() { clearInterval(this.interval) this.stopDeviceById() - globalThis.udpClient2&&globalThis.udpClient2?.setMsgCallBack(()=>{}) + globalThis.udpClient2 && globalThis.udpClient2?.setMsgCallBack(() => { + }) } + // 几个按钮公共样式 @Styles commStyle(){ @@ -509,15 +529,6 @@ struct UserInfo { .margin({ bottom: 12 * this.ratio }) } - private labelBlocks = [ - { label: '考生姓名', key: 'xm' }, - { label: '身份证号', key: 'sfzmhm' }, - { label: ' 流 水 号 ', key: 'lsh' }, - { label: '考试路线', key: 'kslx' }, - { label: '待考次数', key: 'kssycs' }, - { label: '考官姓名', key: 'ksy1' }, - ] - build() { Column() { TopLogo({ outFlag: $outFlag }).margin({ bottom: 10 }) @@ -656,9 +667,9 @@ struct UserInfo { }) return } - if(this.FaceOpenStatue!='0'){ + if (this.FaceOpenStatue != '0') { this.showFaceCompare = true - }else{ + } else { this.sfbdinterfaceFn() } }) diff --git a/entry/src/main/ets/pages/judgeSDK/judge.ts b/entry/src/main/ets/pages/judgeSDK/judge.ts index 94997e4c..d554fe58 100644 --- a/entry/src/main/ets/pages/judgeSDK/judge.ts +++ b/entry/src/main/ets/pages/judgeSDK/judge.ts @@ -3,175 +3,382 @@ import router from '@ohos.router'; import util from '@ohos.util'; import buffer from '@ohos.buffer'; -import {testMarkRules,testKmItems} from './dataTest/index' -import {SOUND,EXAMDATA} from './api/judgeSDK' +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 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 JudgeTask from './utils/judge-task'; +import SimulateLights from './utils/simulate-lights'; +import { judgeConfig } from './utils/judge-config'; -import {writeObjectOut,uploadExamProgressData} from '../../api/judge' -import {deepClone,getCurrentTime,stringToASC,string2Bytes,fillZero,Array2Byte,convertGpsCoord2} from '../../common/utils/tools' -import {getTranslateSignals,getCarStatus,getCarStatusType,getCenterProjectStatus,plcStrToJson,plcStrToWXJson,promptWxCode,getKmProjectVoice,senorToWXDataStr} from './utils/judge-common' +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 { - examJudgeSetLogCallback, - examJudgeBeginExam, - examJudgeInit, - examJudgeRealExam, - examJudgeSetRealExamCallback, - examJudgeSetPerformCallback, - examJudgeEndExam, - examJudgeArtificialMark, examJudgeArtificialItem, + examJudgeArtificialMark, + examJudgeBeginExam, + examJudgeEndExam, + examJudgeInit, + examJudgeMapSetParam, examJudgeMapSetScaling, - examJudgeMapSetParam -} from './api/index' -import UsbService from '../../common/service/usbService' + 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{ - - 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); - const usbService = new UsbService(); - this.usbService = 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; +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); - //开始评判 - 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); + await fileLog.setExamJudgeData({ + method: 'examJudgeArtificialItem', + itemno: itemno * 1, + type: 1 }) - console.info(judgeTag,'2.注册日志回调完成') + console.info(judgeTag, `人工评判进入项目-${itemno}`) - let initInfo = isTrajectoryOpen ? JSON.parse(strArr[0]):await this.getJudgeInitData(); + } + //人工扣分 + public setJudgeMark = async (itemno, serial) => { + const {fileLog} = this + await examJudgeArtificialMark(itemno * 1, serial); - //相关评判初始化只做一次 - 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 fileLog.setExamJudgeData({ + method: 'examJudgeArtificialMark', + itemno: itemno * 1, + serial }) - 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); + console.info(judgeTag, `人工扣分-${itemno}-${serial}`) + } + // 断网数据补传 + uploadDisConnectData = async () => { + const {isJudgeDisConnect,fileLog,fileUtil} = this; + if (!isJudgeDisConnect) { return } - - - // 处理实时udp里的plc信号 - globalThis.udpClient.onMessage(async (msg) => { - handleUdp(msg) + 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') } - - public async onJudgeFn(fn:Function){ - await this.judging(fn) + //获取科目三的评判初始化配置 + 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) => { + handleRealExam = async (strData, callBack) => { // console.log('过程数据:' + strData); - let examData:EXAMDATA = JSON.parse(strData); + let examData: EXAMDATA = JSON.parse(strData); const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,judgeUI} = this; const {carzt,xmks,kf,event,xmjs,ksjs,sound,mndg} = examData @@ -179,7 +386,7 @@ export default class Judge{ const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; - switch (event){ + switch (event) { //项目开始 case 1: judgeUI.projectsObj[xmdm].type = '2'; @@ -207,31 +414,36 @@ export default class Judge{ //扣分 case 3: const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`) - //扣分信息 + //扣分信息 this.kfArr.push({ //扣分项目名称 - xmmcStr:getDqxmStr(kf.xmdm), - xmdm:kf.xmdm, + xmmcStr: getDqxmStr(kf.xmdm), + xmdm: kf.xmdm, //扣分描述 - desc:thisKf.desc, + desc: thisKf.desc, //扣分分数 - score:thisKf.score, + score: thisKf.score, // 扣分无锡所代码 - markcatalog:thisKf.markcatalog, - markserial:thisKf.markserial, - kfxh:thisKf.kfxh + markcatalog: thisKf.markcatalog, + markserial: thisKf.markserial, + kfxh: thisKf.kfxh }) - this.judgeUI.totalScore += thisKf.score*1; + this.judgeUI.totalScore += thisKf.score * 1; break; //考车状态 - case 4: this.carztStr = getCarStatus(carzt);break; + case 4: + this.carztStr = getCarStatus(carzt); + break; //考试结束 - case 5: this.ksjs = ksjs;break; + case 5: + this.ksjs = ksjs; + break; //项目取消 - case 6: break; + case 6: + break; //语音播放和提示 case 7: @@ -241,9 +453,10 @@ export default class Judge{ //模拟灯光事件 case 8: setMndg(mndg) - break; + break; - default:;break; + default: + ;break; } @@ -251,205 +464,62 @@ export default class Judge{ await callBack({ //项目名称 考车状态 扣分arr - xmmcStr, carztStr, kfArr + xmmcStr, carztStr, kfArr }); //语音播报 - this.goVoiceAnnounce(event,xmdm, this.kfArr,xmjs) + this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs) //更新UI - if(event == 1 || event == 2 || event == 3){ + if (event == 1 || event == 2 || event == 3) { const copyProjectsObj = this.judgeUI.projectsObj; judgeUI.projectsObj = deepClone(copyProjectsObj) } } - - // 评判语音提示 - 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; - }) - } - }) - - - } - - // 模拟灯光 - setMndg = async (mndgStr:string) => { - this.mndgStr = mndgStr - this.rmndg = 1; - } - - // 更改考试状态 - 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 - } - } - - // 处理考试结束 - 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) - } - - } - - // 过程照片拍照 - 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 - } - } - - // 当前项目转换 - 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 - } - } - + //当前科目二的考试项目 + private currentKm2ItemsObj: any + //本地轨迹回放地址 + private trajectoryPath: string + private isTrajectoryOpen: boolean; + // 调代理接口是否断网了 + private isJudgeDisConnect: boolean; // 项目开始接口同步 - beginProject = async(ksxm) => { + 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 sbxh = getSbbm(ksxm, xmxh) const data = { //系统类别 接口序列号 接口标识 - xtlb:'17', jkxlh:serialNumber, jkid:'17C52', - drvexam:{ + xtlb: '17', jkxlh: serialNumber, jkid: '17C52', + drvexam: { // 考试科目 身份证号码 - lsh, kskm:examSubject, sfzmhm:idCard, ksxm:project.projectCodeCenter,sbxh, kchp:encodeURI(plateNo), + lsh, + kskm: examSubject, + sfzmhm: idCard, + ksxm: project.projectCodeCenter, + sbxh, + kchp: encodeURI(plateNo), // 开始时间 - ksdd:encodeURI(ksdd), ksxl:encodeURI(kslx) || '', kssj:time + ksdd: encodeURI(ksdd), + ksxl: encodeURI(kslx) || '', + kssj: time } } const code = await writeObjectOut(data) // console.info(judgeTag,'项目开始 end') - if(code === 2300007){this.isJudgeDisConnect = true;} + if (code === 2300007) { + this.isJudgeDisConnect = true; + } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) - promptWxCode('17C52',code) + promptWxCode('17C52', code) } - // 项目结束接口同步 - endProject = async(ksxm) =>{ + endProject = async (ksxm) => { const carInfo = globalThis.carInfo; const deviceNo = globalThis.deviceNo; const { examSubject,plateNo,carNo } = carInfo; @@ -457,30 +527,35 @@ export default class Judge{ const {lsh,idCard,serialNumber,projectsObj,cdsbInfoObj,ksdd,kslx} = judgeUI const time = await getCurrentTime(); const project = projectsObj[ksxm] - const sbxh = getSbbm(ksxm,xmxh) + const sbxh = getSbbm(ksxm, xmxh) const data = { - xtlb:'17',jkxlh:serialNumber,jkid:'17C55', - drvexam:{ - lsh,kskm:examSubject,sfzmhm:idCard, - ksxm:project.projectCodeCenter, + 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 + czlx: '1', + kchp: encodeURI(plateNo), + ksdd: encodeURI(ksdd), + ksxl: encodeURI(kslx) || '', + jssj: time } } const code = await writeObjectOut(data) - if(code === 2300007){this.isJudgeDisConnect = true;} + if (code === 2300007) { + this.isJudgeDisConnect = true; + } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) // console.info(judgeTag,'项目结束 end') - promptWxCode('17C55',code) + promptWxCode('17C55', code) } - // 考试扣分 - pointsDedute= async (ksxm,kf) => { + pointsDedute = async (ksxm, kf) => { const carInfo = globalThis.carInfo; const deviceNo = globalThis.deviceNo; const { examSubject,plateNo,carNo } = carInfo; @@ -489,27 +564,31 @@ export default class Judge{ const time = await getCurrentTime(); const project = getProjectInfo(ksxm); const data = { - xtlb:'17',jkxlh:serialNumber,jkid:'17C53', - drvexam:{ - lsh,kskm:examSubject, + 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), + 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 + kffs: 1, + ksdd: encodeURI(ksdd), + kfsj: time } } const code = await writeObjectOut(data); - if(code === 2300007){this.isJudgeDisConnect = true} + if (code === 2300007) { + this.isJudgeDisConnect = true + } const isJudgeDisConnect = this.isJudgeDisConnect isJudgeDisConnect ? fileLog.setExamJudgeDisWuxiProgressData(data) : fileLog.setExamJudgeWuxiData(data) - console.info(judgeTag,'项目扣分 end') - promptWxCode('17C53',code) + console.info(judgeTag, '项目扣分 end') + promptWxCode('17C53', code) } - // 考试过程照片 uploadProgressPhoto = async (ksxm) => { const time = await getCurrentTime(); @@ -522,25 +601,151 @@ export default class Judge{ 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, + 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) + 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) + if (code === 2300007) { + this.isJudgeDisConnect = true + } + promptWxCode('17C54', code) fileLog.setExamJudgeWuxiData(data) - console.info(judgeTag,'上传照片 end') + 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) => { + public endExam = async (isManual?: Boolean) => { const carInfo = globalThis.carInfo; const deviceNo = globalThis.deviceNo; const { examSubject ,plateNo} = carInfo; @@ -551,119 +756,44 @@ export default class Judge{ const photoBase64 = await getPhoto(); const data = { - xtlb:'17',jkxlh:serialNumber,jkid:'17C56', - drvexam:{ - lsh,kchp:encodeURI(plateNo),kskm:examSubject,sfzmhm:idCard, + 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:'', + 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){ + 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) + 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) + } else { + avPlayer.playAudio(['voice/qualified.mp3'], true) } } - console.info(judgeTag,`考试成绩:${totalScore}`) + console.info(judgeTag, `考试成绩:${totalScore}`) fileLog.setExamJudgeWuxiData(data) await uploadProgressData(); - setTimeout(()=>{ + setTimeout(() => { router.back(); - },3000) + }, 3000) } - //人工进入项目 - 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') - } - // 获取评判初始化数据 getJudgeInitData = async () => { const {getModelData,getKm3JudgeInitConfig} = this @@ -673,92 +803,89 @@ export default class Judge{ const judgeUI = this.judgeUI const {projectsObj,cdsbInfoObj,markRuleListObj,carType,carName} = judgeUI - const examType = examSubject == 2?'km2':'km3' + const examType = examSubject == 2 ? 'km2' : 'km3' let allitems = []; - if(examSubject == 2){ - allitems = Reflect.ownKeys(cdsbInfoObj).map(cdsbKey=>{ + 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`) + 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`), + 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, + mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules, + sysset: judgeUI.judgeConfig, }; let km3Config = {} - if(examSubject){ - km3Config = await getKm3JudgeInitConfig(); + if (examSubject) { + km3Config = await getKm3JudgeInitConfig(); } // 获取科目三的评判配置 - console.info(judgeTag,'3.获取评判初始化数据完成') + console.info(judgeTag, '3.获取评判初始化数据完成') return { ...initInfo, ...km3Config, } } - //获取科目三的评判初始化配置 - 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') - } - } - // 消息心跳发送 - getMessageHeartbeat = async (isEnd?:Boolean) => { + 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 { + judgeUI, + isExam, + serialIndex, + tempData, + xmmcCode, + xmxh, + xmmcSingleCode, + xmdm, + performInfo, + kfArr, + getTranslateProject, + getSbxh + } = this; const {lsh,startHourTime,totalScore} = judgeUI; - const examType = isExam?examSubject:0; + 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 sbxh = getSbxh(xmdm, xmxh) + console.log('sbxhsbxh', sbxh) const {carzt,dcjl,qjjl,dxjl,bxjl} = performInfo; - console.log('performInfo',JSON.stringify(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 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 ]) + [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); + 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') @@ -767,49 +894,51 @@ export default class Judge{ //@ts-ignore // const translateProjects= translateProject.map(num => string2Bytes(p,8)[0]) - console.log('jinweidu2222',`${examType}${startHourTime}`) + console.log('jinweidu2222', `${examType}${startHourTime}`) const arr = [ //考生号 TODO 考试员号 - asclshArr.map(lsh => string2Bytes(lsh,8)[0]), + asclshArr.map(lsh => string2Bytes(lsh, 8)[0]), //考试员号 - ascksyhArr.map(ksyh => string2Bytes(ksyh,8)[0]), + ascksyhArr.map(ksyh => string2Bytes(ksyh, 8)[0]), //科目类型(0:未考试 1:科目二 2:科目三) + 考试开始时间 - string2Bytes(`${examType}${startHourTime}`,4 * 8), + string2Bytes(`${examType}${startHourTime}`, 4 * 8), // TODO 消息序号从1开始,0结束 - string2Bytes(isEnd ? 0 : serialIndex,2 * 8), + 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), + 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), + string2Bytes(dxjl < 0 ? (dxjl + 4294967296) : dxjl, 4 * 8), //GPS北向距离 - string2Bytes(bxjl < 0 ? (bxjl+4294967296) : bxjl,4*8), + string2Bytes(bxjl < 0 ? (bxjl + 4294967296) : bxjl, 4 * 8), //航向角 俯仰角 高程(海拔) - string2Bytes((hxj+90) * 100,2*8), string2Bytes(fyj*100,2*8), string2Bytes(hbg*100,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), + string2Bytes(xmmcSingleCode ? (xmmcSingleCode * 1 + 1) : 0, 8), //场地设备编号 - ascsbxhArr.map(sbxh => string2Bytes(sbxh,8)[0]), + ascsbxhArr.map(sbxh => string2Bytes(sbxh, 8)[0]), //本次考试行驶距离 - string2Bytes(Math.floor((dcjl + qjjl)/100),2*8), + string2Bytes(Math.floor((dcjl + qjjl) / 100), 2 * 8), //扣分 - string2Bytes(100 - Math.abs(totalScore),2*8), + string2Bytes(100 - Math.abs(totalScore), 2 * 8), //扣分数 //todo扣分值/扣分项 string2Bytes(0, 2 * 8), //扣分项数量 - string2Bytes(kfArr.length,8), + string2Bytes(kfArr.length, 8), //n个扣分序号 - kfArr.map(kf => string2Bytes(kf.kfxh,8)[0]) + kfArr.map(kf => string2Bytes(kf.kfxh, 8)[0]) ] let tempArr = []; - arr.forEach(itemArr =>{ tempArr = tempArr.concat(itemArr)}) + arr.forEach(itemArr => { + tempArr = tempArr.concat(itemArr) + }) this.serialIndex += 1; return Array2Byte(tempArr) } @@ -818,87 +947,67 @@ export default class Judge{ getJudgeBeginData = async () => { const {code,name:examinerName} = globalThis.examinerInfo; const {isExam,isTrajectoryOpen} = this; - const judgeUI = this.judgeUI + const judgeUI = this.judgeUI const {projects,carType,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr} = judgeUI; const beginInfo = { - kgid:'012', - kgxm:decodeURI(examinerName || ''), - exam:isExam?1:0, + kgid: '012', + kgxm: decodeURI(examinerName || ''), + exam: isExam ? 1 : 0, //是否回放 - replay:0, + replay: 0, //生成的轨迹文件 - track:'', - xm:judgeUI.name, - sex:0, - kslsh:judgeUI.lsh, - sfzmhm:judgeUI.idCard, - ksyy:'', - kscx:carType, - kkcs:1, - sfyk:0, - ykkkcs:1, + 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=>{ + wayno: 3, + czlx: 0, + kskssj: await systemTime.getCurrentTime(), + ksxm: projects.map(project => { return { - xmdm:project.projectCode*1, - xmxh:'', + 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(',') + 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, + xmdm: xmdm * 1, kfdm } - })):[], - yklc:0, - special:[], + })) : [], + yklc: 0, + special: [], //TODO 科目三参数临时写死 - sczb:0,sczbkf:[],dmndg:false,nitem1:false,nitem41:false,mfxx:false,mfxxn:false + sczb: 0, + sczbkf: [], + dmndg: false, + nitem1: false, + nitem41: false, + mfxx: false, + mfxxn: false } - console.info(judgeTag,'5.获取开始考试数据完成') + console.info(judgeTag, '5.获取开始考试数据完成') return beginInfo } - // 获取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 - } - //获取场地序号 - getSbxh = (ksxm,xmxh) => { + getSbxh = (ksxm, xmxh) => { const {judgeUI} = this; const {cdsbInfoObj,projectsObj} = judgeUI; const project = projectsObj[ksxm] - if(project === undefined){ + if (project === undefined) { return '00000000' } const projectType = project.sbxh; @@ -908,11 +1017,11 @@ export default class Judge{ return sbxh } - getSbbm = (ksxm,xmxh) => { + getSbbm = (ksxm, xmxh) => { const {judgeUI} = this; const {cdsbInfoObj,projectsObj} = judgeUI; const project = projectsObj[ksxm] - if(project === undefined){ + if (project === undefined) { return '00000000' } const projectKey = `${ksxm}_${xmxh}`; @@ -922,26 +1031,26 @@ export default class Judge{ } // 中心所有项目转换 - getTranslateProject = () => { + getTranslateProject = () => { // const {testKmItems} = this; - const tempItems = testKmItems.map(item=>{ + const tempItems = testKmItems.map(item => { const current = this.testKmItems[item.code]; return { - code:item.code, - status:getCenterProjectStatus(current.status) + 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 ); + 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']) + if (i === 4) { + tempArr = tempArr.concat(['00', '00']) } arr.push(tempArr.join('')); } - return arr.map(numStr => parseInt(numStr,2)); + return arr.map(numStr => parseInt(numStr, 2)); } // 获取考试项目详情 @@ -954,140 +1063,93 @@ export default class Judge{ getModelData = (modelName) => { const modelPath = this.modelPath const fileModel = this.fileModel; - const modelData = fileModel.getModelContent(modelPath,modelName); + const modelData = fileModel.getModelContent(modelPath, modelName); return modelData } - // 处理轨迹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 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; - // 处理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) { + 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 } - 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 + + + // 处理实时udp里的plc信号 + globalThis.udpClient.onMessage(async (msg) => { + handleUdp(msg) + }) + + } - - // 处理特殊参数配置 - 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; - - - } - } - - private judgeUI - 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 - - 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 - public plcStr:string - 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 - private km2ItemsStatus:any[] - - //所有的科目考试项目(大车&小车) - private testKmItems:any - //当前科目二的考试项目 - private currentKm2ItemsObj:any - //本地轨迹回放地址 - private trajectoryPath:string - private isTrajectoryOpen:boolean; - // 调代理接口是否断网了 - private isJudgeDisConnect:boolean; } \ No newline at end of file