import systemTime from '@ohos.systemDateTime'; import router from '@ohos.router'; import util from '@ohos.util'; import buffer from '@ohos.buffer'; import { testKm2Items, testKm3Items } from './dataTest/index'; import { KSJS } from './api/judgeSDK'; import VoiceAnnounce from './utils/voiceAnnouncements'; import FileModel from './utils/fileModel'; import FilePhoto from './utils/filePhoto'; import FileLog from './utils/fileLog'; import JudgeTask from './utils/judgeTask'; import { JudgeConfig } from './utils/judgeConfig'; import { LANE } from '../judgeSDK/api/judgeSDK.d'; import { GetSyncData, SqlInsertTable } from '../../utils/table/Operation'; import { getCarStatus, getCenterProjectStatus, plcStrToJson, plcStrToWXJson, promptWxCode } from './utils/judgeCommon'; import { examCalcGpsDistance, examJudgeArtificialItem, examJudgeArtificialMark, examJudgeBeginExam, examJudgeEndExam, examJudgeInit, examJudgeRealExam, examJudgeSetLogCallback, examJudgeSetPerformCallback, examJudgeSetRealExamCallback, examJudgeSoundEnd, examJudgeVersion } from './api/index'; import { uploadExamProgressData, writeObjectOut } from '../../api/judge'; import { endRecordVideo, saveStartRecordVideo } from '../../utils/Video'; import common from '@ohos.app.ability.common'; import { convertGpsCoord2, deepClone } from './utils/Common'; import { GetCurrentTime } from '../../utils/Common'; import UsbService from '../../utils/USB'; import FileUtils from '../../utils/FileUtils'; import { BaseInfoType, CarInfoType, CDSBInfo, DrvexamType, ExaminerInfoType, ItemInfo, JudgeBeginObj, JudgeCallBackData, JudgeConfigObj, JudgeConfigObjKmItems, JudgeEventKf, JudgeInitObj, JudgeKFXM, JudgeKSJS, JudgeKSXM, JudgePerformInfo, JudgeSound, JudgeUI, JudgeXMJS, Km3JudgeInitConfig, KmItem, MarkRule, Plc, ProjectInfo, RecordHandleType, RegulatoryInterfaceParams, RouteParamsType, TKmItem, User, WR } from '../../model'; import { DrivingDataStorage } from '../../utils/business/DrivingDataStorage'; const judgeTag = 'SURENJUN_JUDGE' type GetKm3JudgeInitConfig = () => Promise type GetgSbbm = (ksxm: number, xmxh: string) => string type SendWriteObjectOut = (data: RegulatoryInterfaceParams, filePath: string) => Promise type GetKfStr = (code: string) => MarkRule type GetDqxmStr = (xmdm: number) => string type TJudgeBeginObj = JudgeBeginObj export default class Judge { public plcStr: string public judgeUI: JudgeUI //获取科目三的评判初始化配置 getKm3JudgeInitConfig: GetKm3JudgeInitConfig = async () => { return { map_point: this.judgeUI.mapPointArr, map_point_item: this.judgeUI.mapPointItemArr, //科目三暂时为空 iteminfo: [], roads: this.getModelData('km3/Roads.txt'), sharps: this.getModelData('km3/Sharps.txt') } } private context: common.UIAbilityContext private fileLog: FileLog //人工扣分 public setJudgeMark = async (itemno: string, serial: string, type = 1) => { await examJudgeArtificialMark(Number(itemno), serial, type); console.info(judgeTag, `进入人工扣分-${itemno}-${serial}`) const str = JSON.stringify({ method: 'examJudgeArtificialMark', itemno: Number(itemno), serial, type }) await this.fileLog.setExamJudgeData(str) console.info(judgeTag, `人工扣分-${itemno}-${serial}`) } //人工操作项目 public setJudgeItem = async (itemno: string, type: 1 | 2) => { // const { fileLog } = this; await examJudgeArtificialItem(Number(itemno), type); const str = JSON.stringify({ method: 'examJudgeArtificialItem', itemno: Number(itemno), type }) await this.fileLog.setExamJudgeData(str) console.info(judgeTag, `人工评判${type == 1 ? '进入' : '取消'}项目-${itemno}`) } private filePath: string private totalScore: number private prevJd: number = 0 private prevWd: number = 0 private dwztNum: number = 0 private folderPath: string private modelPath: string private avPlayer: VoiceAnnounce // 处理特殊参数配置 handleSEP = async (code: number) => { const judgeConfigObj = this.judgeUI.judgeConfigObj const avPlayer = this.avPlayer switch (code) { //结束考试方式 case 306: if (judgeConfigObj[code] == 5) { //靠边停车 avPlayer.playAudio(['voice/406001.mp3']) } break; } } private carztStr: string private rmndg: 0 | 1 private mndgStr: string | undefined // 模拟灯光 setMndg = async (mndgStr: string) => { this.mndgStr = mndgStr } private xmmcStr: string private xmmcCode: string private xmmcSingleCode: string private xmmcEndCode?: string private xmdm: string | number private xmxh: string private fileModel: FileModel private filePhoto: FilePhoto // 过程照片拍照 getPhoto = async (empty?: boolean) => { const singlePlay: boolean = AppStorage.get('singlePlay') //单机模式返回空照片 if (singlePlay) { return '' } else { const photoBase64 = await this.filePhoto.getPhoto(); console.info(judgeTag, '拍照完成') return photoBase64 } } private usbService: UsbService //是否是考试模式 private isExam: boolean //考试是否结束了 private isExamEnd: boolean // 是否发送udp private isUdpEnd: boolean = false //是否手动结束考试 private isManual: boolean //UDP服务序列号 private serialIndex: number private fileUtil: FileUtils //上传无锡所过程数据 uploadProgressData = async () => { const carInfo = AppStorage.get('carInfo') const judgeUI = this.judgeUI const fileUtil = this.fileUtil const fileLog = this.fileLog const carId = carInfo.carId const examinationRoomId = carInfo.examinationRoomId const folderPath = fileLog.folderPath const base64 = new util.Base64(); const time = GetCurrentTime(); const endTime = GetCurrentTime(1) let examDataBase64: string = '' //TODO try catch报错待优化 const examDataStr: string = await this.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') try { await uploadExamProgressData({ carId, examinationRoomId, type: 1, time, cardNo: judgeUI.idCard, examData: examDataBase64, examStartTime: judgeUI.startFullTime, examEndTime: endTime, }) } catch (e) { console.info(judgeTag, '过程数据文件上传失败:' + JSON.stringify(e)) } console.info(judgeTag, '过程数据文件上传 end') } private judgeTask: JudgeTask // 检测扣分、结束项目时该项目是否开始 checkProjectIsStart = async (xmdm: number, currentType: 1 | 2, kf?: JudgeEventKf) => { if (xmdm == 20) { return true } const judgeUI = this.judgeUI; const judgeTask = this.judgeTask; const projectsObj = this.judgeUI.projectsObj const currentProject: ProjectInfo = Reflect.get(projectsObj, xmdm) const isUpload = currentProject.isUpload //如果项目没有开始 console.info('surenjun isUpload=>', isUpload) if (!isUpload) { console.info(judgeTag, '项目补传开始') //项目开始补传 judgeTask.addTask(async () => { await this.beginProject(xmdm) }, { isDelay: true }) judgeTask.addTask(async () => { await this.uploadProgressPhoto(xmdm) }, { isDelay: true }) currentProject.isUpload = true; Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) //扣分补传 if (currentType == 2) { judgeTask.addTask(async () => { await this.pointsDedute(xmdm, kf) }, { isDelay: true }) } //扣分补传判断是否合格 不合格补传项目结束 if (currentType == 1 || (currentType == 2 && this.totalScore < judgeUI.passingScore)) { judgeTask.addTask(async () => { await this.endProject(xmdm) }, { isDelay: true }) currentProject.isEnd = true; Reflect.set(this.judgeUI.projectsObj, xmdm, currentProject) } judgeTask.addTask(async () => { this.checkExamIsEnd() }) return false; } else { return true } } private tempData: Plc //实时计算gps经纬度距离 handDistance = async () => { const dwzt = this.tempData.gps.dwzt; const jdzt = this.tempData.gps.jdzt; const tJD = convertGpsCoord2(this.tempData.gps.jd) const tWD = convertGpsCoord2(this.tempData.gps.wd) if (this.prevJd && dwzt == 4 && jdzt == 3) { const distance = await examCalcGpsDistance({ jd1: this.prevJd, wd1: this.prevWd, jd2: tJD, wd2: tWD, h: (this.tempData.gps.hxj) || 1, }) // const distanceClass = AppStorage.get('distanceClass') // distanceClass?.setTimeData(Number(((distance / 100).toFixed(2)))) DrivingDataStorage.setDrivingProcessData(Number(((distance / 100).toFixed(2)))) } this.prevJd = tJD; this.prevWd = tWD; } private performInfo?: JudgePerformInfo private isEndTip: boolean = false; private deductedPopShowTimer: number = 0; // 校验考试是否结束 checkExamIsEnd = async (isManual?: boolean) => { const judgeUI = this.judgeUI const avPlayer = this.avPlayer const isExamEnd = this.isExamEnd const isEndTip = this.isEndTip const isAllProjectsEnd = judgeUI.isAllProjectsEnd const examSubject = judgeUI.examSubject const singlePlay = judgeUI.singlePlay const totalScore = Number(judgeUI.totalScore) const judgeConfigObj = judgeUI.judgeConfigObj const examMileage = Number(judgeUI.examMileage) const passingScore = Number(judgeUI.examMileage) const jl = judgeUI.jl if (isExamEnd) { return } //及格分 let passingGrade = passingScore if (isManual) { // 考试不合格 await examJudgeEndExam() this.isExamEnd = true this.isManual = true } else { const param302: number = Reflect.get(judgeConfigObj, '302') const param342: number = Reflect.get(judgeConfigObj, '342') const param512: number[] = (Reflect.get(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 } } } } } private ksjs: JudgeKSJS private kfArr: JudgeEventKf[] //所有的科目考试项目(大车&小车) private kmItems: JudgeConfigObjKmItems private plcData: Plc // 获取plc数据 getPlcData = async (plc: string) => { await this.fileLog.setPlcProgressData(plc) //plc字符串转化成评判初始化数据 const tempData = await plcStrToJson(plc); //模拟灯光回放时刻 tempData.sensor.rmndg = this.rmndg; //模拟灯灯光灯光项目 tempData.sensor.mndg = this.mndgStr; //plc字符串转化成无锡所过程数据 const wuXiDataStr = await plcStrToWXJson(plc) this.plcData = tempData await this.fileLog.setExamJudgeWuxiProgressData(wuXiDataStr) this.tempData = tempData this.plcStr = plc; this.mndgStr = ''; this.rmndg = 0; AppStorage.setOrCreate('msgStr', plc) return tempData } // 处理udp plc信号 handleUdp = async (msg: string) => { console.info('plc信号', msg) const stachArr = msg.split(',') if (stachArr[0] != '#DN_GD' || this.isUdpEnd) { return } const plcData = await this.getPlcData(msg); // 4.过程数据 await this.fileLog.setExamJudgeData(JSON.stringify(plcData)) //检测到有无锡所设备接入,需要发送特定的数据,供检测 // if (this.usbService.isWXUSBDevice) { // const str = await senorToWXDataStr(msg); // this.usbService.sendUSB(str) // } const param350: number = Reflect.get(this.judgeUI.judgeConfigObj, '350') 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 (!this.isExamEnd) { await examJudgeRealExam(plcData) } let udpIndex = AppStorage.get('udpIndex'); if (udpIndex % 5 === 0 && !this.isUdpEnd) { // TODO UPD缺失 // const judgeUdp = globalThis.judgeUdp // const bytes = await this.getMessageHeartbeat(this.isExamEnd); // judgeUdp.send(bytes) } AppStorage.setOrCreate('udpIndex', udpIndex++) } // 处理轨迹plc信号 handleTrajectoryUdp = async (strArr: string[]) => { // const { fileLog, setJudgeItem, setJudgeMark, endExam } = this; let num = 2; const judgeTimer = setInterval(async () => { const msgStr = strArr[num]; if (msgStr == '') { console.info(judgeTag, '模拟数据考试结束') clearInterval(judgeTimer) this.checkExamIsEnd(true) return } const msg: Plc = 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; AppStorage.setOrCreate('msgStr', '') if (msg.method === 'examJudgeArtificialItem') { this.setJudgeItem(msg.itemno, msg.type) } if (msg.method === 'examJudgeArtificialMark') { this.setJudgeItem(msg.itemno, msg.serial) } await examJudgeRealExam(msg) // const bytes = await this.getMessageHeartbeat(); // bytes && globalThis.judgeUdp.send(bytes) }, 200) // TODO 定时器缺失 // globalThis.judgeTimer = judgeTimer; } //本地轨迹回放地址 private trajectoryPath: string //当前科目二的考试项目 // private currentKm2ItemsObj: any private isTrajectoryOpen: boolean; // 调代理接口是否断网了 private isJudgeDisConnect: boolean; // 断网数据补传 uploadDisConnectData = async () => { if (!this.isJudgeDisConnect) { return } const folderPath = this.fileLog.folderPath const examDataStr = await this.fileUtil.readFile(`${folderPath}/wuxi_dis_progress_data.txt`); const examDataArr = examDataStr.split('\n'); for (let examDataStr of examDataArr) { const code = await writeObjectOut(JSON.parse(examDataStr)); } } // 项目开始接口同步 beginProject = async (ksxm: number) => { const carInfo = AppStorage.get('carInfo'); const judgeUI = this.judgeUI const time = GetCurrentTime(); const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm) const sbxh = this.getSbbm(ksxm, this.xmxh) const drvexam: DrvexamType = { lsh: judgeUI.lsh, kskm: carInfo.examSubject, sfzmhm: judgeUI.idCard, ksxm: project.projectCodeCenter, sbxh, ksxl: judgeUI.xldm, kchp: encodeURI(carInfo.plateNo), ksdd: encodeURI(judgeUI.ksdd), kslx: encodeURI(judgeUI.kslx) || '', kssj: time } const data: RegulatoryInterfaceParams = { //系统类别 接口序列号 接口标识 xtlb: '17', jkxlh: judgeUI.serialNumber, jkid: '17C52', drvexam } const temp: WR = await this.sendWriteObjectOut(data, this.filePath) console.info(judgeTag, '项目开始 end') if (temp.code === 2300007) { this.isJudgeDisConnect = true; } promptWxCode('17C52', temp.code) } // 项目结束接口同步 endProject = async (ksxm: number) => { const carInfo = AppStorage.get('carInfo'); const judgeUI = this.judgeUI; const time = GetCurrentTime(); const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm) const sbxh = judgeUI.examSubject == '3' ? undefined : this.getSbbm(ksxm, this.xmxh) const drvexam: DrvexamType = { lsh: judgeUI.lsh, kskm: carInfo.examSubject, sfzmhm: judgeUI.idCard, ksxm: project.projectCodeCenter, sbxh, //TODO 操作类型 1:正常 0:撤销该考试记录 czlx: '1', ksxl: judgeUI.xldm, kchp: encodeURI(carInfo.plateNo), ksdd: encodeURI(judgeUI.ksdd), kslx: encodeURI(judgeUI.kslx) || '', jssj: time } const data: RegulatoryInterfaceParams = { xtlb: '17', jkxlh: judgeUI.serialNumber, jkid: '17C55', drvexam } const temp: WR = await this.sendWriteObjectOut(data, this.filePath) if (temp.code === 2300007) { this.isJudgeDisConnect = true; } console.info(judgeTag, '项目结束 end') promptWxCode('17C55', temp.code) } private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11] private lane: LANE = { road: '', num: 0, count: 0 } private videoData: RecordHandleType private disConnectNum: number = 0; //调用监管接口 sendWriteObjectOut: SendWriteObjectOut = async (data, filePath) => { const temp = await writeObjectOut(data, filePath); console.log("wzj", JSON.stringify(temp)) //断网&网络超时次数计算 if (temp.code == 2300007 || temp.code == 2300028) { 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: number) => { const time = GetCurrentTime(); const judgeUI = this.judgeUI const plcData = this.plcData const photoBase64 = await this.getPhoto(); const carInfo = AppStorage.get('carInfo'); const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, ksxm) const judgeConfig_305: number = Reflect.get(judgeUI.judgeConfigObj, '305') const drvexam: DrvexamType = { lsh: judgeUI.lsh, kskm: carInfo.examSubject, ksxm: project.projectCodeCenter, sfzmhm: judgeUI.idCard, kchp: encodeURI(carInfo.plateNo), zpsj: time, zp: photoBase64, cs: Math.floor((judgeConfig_305 == 0 ? plcData.gps.sd : plcData.sensor.cs) * 1.852), ksdd: encodeURI(judgeUI.ksdd) } const data: RegulatoryInterfaceParams = { xtlb: '17', jkxlh: judgeUI.serialNumber, jkid: '17C54', drvexam }; const temp: WR = await this.sendWriteObjectOut(data, this.filePath); if (temp.code === 2300007) { this.isJudgeDisConnect = true } promptWxCode('17C54', temp.code) console.info(judgeTag, '上传照片 end') } constructor(judgeUI: JudgeUI) { this.serialIndex = 1; this.judgeUI = judgeUI //语音播放工具 this.avPlayer = new VoiceAnnounce(this.context); //模型工具 this.fileModel = new FileModel(judgeUI.context); //文件工具 this.fileUtil = new FileUtils(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.kmItems = {}; // 考试回放配置 this.isTrajectoryOpen = JudgeConfig.isTrajectoryOpen; this.modelPath = JudgeConfig.modelPath; this.trajectoryPath = JudgeConfig.trajectoryPath; this.isExam = !this.judgeUI.singlePlay; (judgeUI.examSubject == '2' ? testKm2Items : testKm3Items).forEach(item => { const projectCenterObj: ProjectInfo = Reflect.get(judgeUI.projectsCenterObj, item.code) const currentItem: KmItem = Reflect.get(this.kmItems, item.code) currentItem.code = item.code currentItem.status = projectCenterObj === undefined ? 0 : (projectCenterObj.isEnd ? 3 : 1) Reflect.set(this.kmItems, item.code, currentItem) }) console.info(judgeTag + 'testKmItems', JSON.stringify(this.kmItems)) this.isExamEnd = false; } public async onJudgeFn(fn: Function) { await this.judging(fn) } // 获取评判初始化数据 getJudgeInitData = async () => { const carInfo = AppStorage.get('carInfo'); const judgeUI = this.judgeUI const projectsObj = judgeUI.projectsObj const itemInfoObj = judgeUI.itemInfoObj const markRuleListObj = judgeUI.markRuleListObj const carType = judgeUI.carType const carName = judgeUI.carName const systemparmArr = judgeUI.systemparmArr const carinfoArr = judgeUI.carinfoArr const examType = carInfo.examSubject == '2' ? 'km2' : 'km3' let allitems: ItemInfo[] = []; if (judgeUI.examSubject == '2') { allitems = Reflect.ownKeys(itemInfoObj).map(cdsbKey => { const cdsb: CDSBInfo = Reflect.get(itemInfoObj, cdsbKey); const model = this.getModelData(`${examType}/${cdsb.modelKey}.txt`) const temp: ItemInfo = { xmdm: cdsb.xmdm, xmxh: cdsb.xmxh, model } return temp }) } //获取版本号 const mark: MarkRule[] = Reflect.ownKeys(markRuleListObj).map(ruleKey => { const current: MarkRule = Reflect.get(markRuleListObj, ruleKey) return current }) const initInfo: JudgeInitObj = { sdkver: await examJudgeVersion(), appver: AppStorage.get('baseInfo').version, kskm: Number(carInfo.examSubject), kchp: carInfo.plateNo, kchm: Number(carInfo.carId), kscx: carType, cxcode: '1', name: carName, carmodel: this.getModelData(`${examType}/${carType}.txt`), allitems, iteminfo: [], systemparm: systemparmArr, mark, sysset: judgeUI.judgeConfig, itemInfoObj, carlist: judgeUI.carlist, carinfo: carinfoArr, }; let km3Config: Km3JudgeInitConfig = {} if (judgeUI.examSubject == '3') { km3Config = await this.getKm3JudgeInitConfig(); initInfo.map_point = km3Config.map_point initInfo.map_point_item = km3Config.map_point_item initInfo.iteminfo = km3Config.iteminfo initInfo.roads = km3Config.roads initInfo.sharps = km3Config.sharps } // 获取科目三的评判配置 console.info(judgeTag, '3.获取评判初始化数据完成') return initInfo } // 获取开始考试数据 getJudgeBeginData = async () => { const examinerInfo = AppStorage.get('examinerInfo') const code = examinerInfo.code const examinerName = examinerInfo.name let currentParams: RouteParamsType = router.getParams() as RouteParamsType; const sczb = currentParams.sczb; const kfdm = currentParams.kfdm; const isExam = this.isExam; const judgeUI = this.judgeUI const projects = judgeUI.projects const carType = judgeUI.carType const kssycs = judgeUI.kssycs const isDdxk = judgeUI.isDdxk const ddxkTime = judgeUI.ddxkTime const projectsCenterObj = judgeUI.projectsCenterObj const ddxkKsxmArr = judgeUI.ddxkKsxmArr const ddxkKfArr = judgeUI.ddxkKfArr const passingScore = judgeUI.passingScore const ksxm: JudgeKSXM[] = projects.map(project => { const temp: JudgeKSXM = { xmdm: Number(project.projectCode), xmxh: '' } return temp }) const ykxm: number[] = (ddxkKsxmArr?.map(projectCenterCode => { const currentProject: ProjectInfo = Reflect.get(projectsCenterObj, projectCenterCode) return Number(currentProject.projectCode) })) || []; const kfxm: JudgeKFXM[] = isDdxk ? (ddxkKfArr?.map(kf => { return { xmdm: Number(kf.split(',')[0]), kfdm: kf.split(',')[1] } as JudgeKFXM })) : [] const beginInfo: JudgeBeginObj = { 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: Number(judgeUI.wayno), czlx: 0, kskssj: await systemTime.getCurrentTime(), passing: Number(passingScore), ksxm, //断点续考 ddxk: isDdxk ? 1 : 0, ddkssj: ddxkTime || 0, ykxm, kfxm, //TODO 已考里程待修改 yklc: 0, special: [], sczb: (sczb === undefined || sczb == '0') ? 0 : 1, sczbkf: kfdm, dmndg: false, mfxx: false, mfxxn: false } console.info(judgeTag, '5.获取开始考试数据完成') return beginInfo } //处理评判过程回调 handleRealExam = async (strData: string, callBack: Function) => { let examData: JudgeCallBackData = JSON.parse(strData); const getDqxmStr = this.getDqxmStr; const getKfStr = this.getKfStr; const goJudgeVoice = this.goJudgeVoice; const setMndg = this.setMndg; const avPlayer = this.avPlayer; const fileLog = this.fileLog; const judgeUI = this.judgeUI; const carzt = examData.carzt const xmks = examData.xmks const kf = examData.kf const event = examData.event const xmjs = examData.xmjs const xmqx = examData.xmqx const ksjs = examData.ksjs const sound = examData.sound const mndg = examData.mndg const lane = examData.lane const precast = examData.precast const nongps = examData.nongps //获取项目结束、项目开始代码 const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh; const isManualProjectIn = this.artSubject3ProjectsCodesArr.includes(xmdm); const examSubject = this.judgeUI.examSubject const projects = this.judgeUI.projects const judgeConfigObj = this.judgeUI.judgeConfigObj switch (event) { //项目开始 case 1: const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm) project.type = '2'; if (isManualProjectIn) { //手动项目是否在进行中 this.judgeUI.isManualProjectIn = true } if (xmdm == 41 && examSubject == '3') { this.rmndg = 1 } this.judgeUI.currentXmdm = xmdm; const xmmcStr = project.name; const xmmcCode = project.projectCodeCenter; const xmmcSingleCode = project.projectCode; const kmItem: KmItem = Reflect.get(this.kmItems, xmmcCode) kmItem.status = 2; this.xmmcStr = xmmcStr; this.xmmcCode = xmmcCode; this.xmmcSingleCode = xmmcSingleCode this.xmmcEndCode = xmmcCode this.xmdm = xmdm; this.xmxh = xmxh; this.judgeUI.isProjectIn = true Reflect.set(this.judgeUI.projectsObj, xmdm, project) Reflect.set(this.kmItems, xmmcCode, kmItem) break; //项目结束 case 2: { const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm) const xmmcCode = project.projectCodeCenter; project.type = (xmjs.xmhg === 0 ? '4' : '3') //计算项目是否全部结束 this.judgeUI.isProjectIn = (Reflect.ownKeys(judgeUI.projectsObj).filter((projectKey) => { const fillProject: ProjectInfo = Reflect.get(judgeUI.projectsObj, projectKey) return fillProject.type == '2' }).length) > 0; if (isManualProjectIn) { this.judgeUI.isManualProjectIn = false } const kmItem: KmItem = Reflect.get(this.kmItems, xmmcCode) kmItem.status = 3; //统计必考项目数量 this.xmmcStr = '无'; this.xmmcCode = ''; this.xmdm = ''; this.judgeUI.currentXmdm = undefined; Reflect.set(this.judgeUI.projectsObj, xmdm, project) Reflect.set(this.kmItems, xmmcCode, kmItem) break; } //扣分 case 3: const thisKf = this.getKfStr(`${kf.xmdm}_${kf.kfdm}`) const kfObj: JudgeEventKf = { //扣分项目名称 xmmcStr: this.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.kfArr.push(kfObj) this.judgeUI.totalScore += thisKf.score * 1; if (kf.xmdm != 20) { const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, kf.xmdm) const type = project.type; project.type = (type == '3' || type == '4') ? '4' : '5' Reflect.set(this.judgeUI.projectsObj, kf.xmdm, project) } break; //考车状态 case 4: this.carztStr = getCarStatus(carzt); break; //考试结束 case 5: this.ksjs = ksjs; await fileLog.setExamJudgeData(JSON.stringify({ method: 'examJudgeEndExam' })) break; //项目取消 case 6: { console.info(judgeTag, '项目取消'); const xmdm = xmqx.xmdm; const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm) // const examSubject = this.judgeUI.examSubject const xmmcCode = project.projectCodeCenter; // const voiceCode = getKmProjectCancelVoice(examSubject, xmmcCode); // avPlayer.playAudio([`voice/${voiceCode}.mp3`],true) project.type = '1' const kmItem: KmItem = Reflect.get(this.kmItems, xmmcCode) Reflect.set(this.judgeUI.projectsObj, xmdm, project) kmItem.status = 1 Reflect.set(this.kmItems, xmmcCode, kmItem) break; } //语音播放和提示 case 7: this.goJudgeVoice(sound) break; //模拟灯光事件 case 8: this.setMndg(mndg) break; //车道和路段变化 case 9: this.judgeUI.lane = lane this.lane = lane; break; //预进项目事件 case 10: { const param611: JudgeConfigObj = Reflect.get(judgeConfigObj, '611') || '' const xmdm = precast.xmdm const xmxh = precast.xmxh const project: ProjectInfo = Reflect.get(judgeUI.projectsObj, xmdm) const xmmcCode = project.projectCodeCenter const projectCode = project.projectCode // const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter; // const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode; const kmItem: KmItem = Reflect.get(this.kmItems, xmmcCode) kmItem.status = 2; Reflect.set(this.kmItems, xmmcCode, project) this.xmmcStr = xmmcStr; this.xmmcCode = xmmcCode; this.xmdm = xmdm; this.xmxh = xmxh; this.xmmcSingleCode = xmmcSingleCode; project.type = '2'; Reflect.set(this.judgeUI.projectsObj, xmdm, project) } break; //差分事件 case 11: { this.checkDwzt(nongps.type) } default: break; } await callBack({ //项目名称 考车状态 扣分arr xmmcStr: this.xmmcStr, carztStr: this.carztStr, kfArrt: this.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: number, xmdm: number, kf: JudgeEventKf[], xmjs: JudgeXMJS, ksjs: JudgeKSJS, xmxh: string) => { const beginProject = this.beginProject const pointsDedute = this.pointsDedute const endProject = this.endProject const avPlayer = this.avPlayer const uploadProgressPhoto = this.uploadProgressPhoto const judgeTask = this.judgeTask const handEndExam = this.handEndExam const judgeUI = this.judgeUI const checkExamIsEnd = this.checkExamIsEnd const checkProjectIsStart = this.checkProjectIsStart const lane = this.lane const closeAllFiles = this.closeAllFiles const projectsObj = judgeUI.projectsObj const judgeConfigObj = judgeUI.judgeConfigObj const examSubject = judgeUI.examSubject const jl = judgeUI.jl const isAllProjectsEnd = judgeUI.isAllProjectsEnd const kfLen = kf.length; //不报语音的项目列表 // const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',') // const param611 = judgeConfigObj['611'] || ''; // const [f, s] = param611.split('/') switch (event) { // 项目开始 case 1: const param512: JudgeConfigObj = (Reflect.get(judgeConfigObj, '512') || '').split(','); const project: ProjectInfo = Reflect.get(projectsObj, xmdm) const code = project.projectCodeCenter; const isEnd = project.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 (Reflect.get(param512, 7) != 0) { clearTimeout(this.deductedPopShowTimer) this.judgeUI.isDeductedPopShow = true } }, 200) //项目已考不上传监管信息 if (!isEnd) { judgeTask.addTask(async () => { console.info(judgeTag, `项目开始-${xmdm}-${project.name}`) await beginProject(xmdm) }, { isDelay: true }) judgeTask.addTask(async () => { console.info(judgeTag, `项目-${xmdm}-上传照片 start`) await uploadProgressPhoto(xmdm) }, { isDelay: true }) project.isUpload = true; Reflect.set(this.judgeUI.projects, xmdm, project) } break; // 项目结束 case 2: { const project: ProjectInfo = Reflect.get(projectsObj, xmdm) const endCode = project.projectCodeCenter; const projectIsEnd = project.isEnd; // const endKmCode = getKmProjectVoice(endCode, 2, judgeConfigObj, lane, xmxh) // if (!ignoreVoiceCodeArr.includes(endCode) && examSubject == 3) { // endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`]) // } const isStart = await this.checkProjectIsStart(xmdm, 1); if (isStart) { //项目结束了就不再生成数据 console.info(judgeTag + ' projectIsEnd =>', projectIsEnd) if (!projectIsEnd) { judgeTask.addTask(async () => { console.info(judgeTag, `项目结束-${xmdm}-${project.name}`) await endProject(xmdm); this.xmmcSingleCode = '0'; this.xmmcEndCode = undefined; }, { isDelay: true }) } } if (!this.judgeUI.isProjectIn) { this.deductedPopShowTimer = setTimeout(() => { this.judgeUI.isDeductedPopShow = false }, (Reflect.get(param512, 5) || 0) * 1000) } project.isEnd = true; Reflect.set(this.judgeUI.projects, xmdm, project) 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, '考试结束') //关闭录像 const singlePlay = AppStorage.get('singlePlay') if (!singlePlay) { await endRecordVideo(this.videoData) } judgeTask.addTask(async () => { console.info(judgeTag, '考试结束 start') AppStorage.setOrCreate('isJudge', false) await handEndExam(ksjs) }) // TODO待修改 // 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() } } // 考试扣分 pointsDedute = async (ksxm: number, kf: JudgeEventKf) => { const carInfo = AppStorage.get('carInfo'); const examSubject = carInfo.examSubject const plateNo = carInfo.plateNo const carNo = carInfo.carNo const judgeUI = this.judgeUI const getProjectInfo = this.getProjectInfo const fileLog = this.fileLog const xmmcSingleCode = this.xmmcSingleCode const xmmcEndCode = this.xmmcEndCode const filePath = this.filePath const lsh = judgeUI.lsh const idCard = judgeUI.idCard const serialNumber = judgeUI.serialNumber const ksdd = judgeUI.ksdd const projectsObj = judgeUI.projectsObj const time = GetCurrentTime(); const project = this.getProjectInfo(ksxm); //科目三夜间行驶.模拟灯光、上车准备出现通用评判,ksxm为当前进行的项目 const checkProjects = ['17', '41', '1']; //获取正在进行的项目 const inProjects = Reflect.ownKeys(projectsObj).filter(projectKey => { const project: ProjectInfo = Reflect.get(projectsObj, projectKey) return project.type == '2' }); let commonKsxm = ''; checkProjects.forEach(projectCode => { if (inProjects.includes(projectCode)) { commonKsxm = projectCode } }) const ksxmD: string = project == undefined ? (commonKsxm ? (project.projectCodeCenter) : (examSubject == '3' ? '30000' : (xmmcEndCode == undefined ? '10000' : xmmcEndCode))) : project.projectCodeCenter const drvexam: DrvexamType = { lsh, kskm: examSubject, ksxm: ksxmD, kfxm: kf.markcatalog, kfxmmx: `${ksxm},${kf.markserial}`, sfzmhm: idCard, kchp: encodeURI(carInfo.plateNo), //扣分方式 kffs: kf.type == 0 ? 1 : 2, ksdd: encodeURI(ksdd), kfsj: time } const data: RegulatoryInterfaceParams = { xtlb: '17', jkxlh: serialNumber, jkid: '17C53', drvexam } console.info(judgeTag + 'ksxm=>', data.drvexam.ksxm) const temp = await this.sendWriteObjectOut(data, filePath); if (temp.code == 2300007) { this.isJudgeDisConnect = true } console.info(judgeTag, '项目扣分 end') promptWxCode('17C53', temp.code) } // 评判语音提示 goJudgeVoice = async (sound: JudgeSound) => { const avPlayer = this.avPlayer const fileLog = this.fileLog console.info('surenjun code=>', JSON.stringify(sound.code)) //判断是不是模拟灯光语音 if (sound.type == 1) { avPlayer.playAudio([`voice/${sound.code[0]}.mp3`], false, () => { examJudgeSoundEnd({ xmdm: sound.xmdm, code: sound.code[0], type: sound.type }) fileLog.setExamJudgeData(JSON.stringify({ method: 'examJudgeSoundEnd', itemno: sound.xmdm, code: sound.code[0], type: sound.type, })) }) } else { avPlayer.playAudio([`voice/${sound.code[0]}.mp3`]) } } // 处理考试结束 public handEndExam = async (ksjs: KSJS) => { this.judgeUI.loadingPopupVisible = true; this.judgeUI.endPopupVisible = false; this.judgeUI.isDeductedPopShow = false; const judgeUI = this.judgeUI const endExam = this.endExam const handleSEP = this.handleSEP const kfArr = this.kfArr const avPlayer = this.avPlayer const judgeTask = this.judgeTask const isManual = this.isManual const closeAllFiles = this.closeAllFiles const judgeConfigObj = judgeUI.judgeConfigObj const examSubject = judgeUI.examSubject const isAllProjectsEnd = judgeUI.isAllProjectsEnd const totalScore = judgeUI.totalScore const passingScore = judgeUI.passingScore //计算考试分数 // this.judgeUI.totalScore = isAllProjectsEnd ? totalScore : 0; const singlePlay = AppStorage.get('singlePlay') const param302: string = Reflect.get(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') { if (totalScore < passingScore) { //考试不合格;考试模式,自动退出; if (param302 == '4' || param302 == '5' || param302 == '7' || param302 == '8') { } } else { //考试合格 } } await handleSEP(306); avPlayer.playAudio(['voice/exam_waiting.mp3'], AppStorage.get('singlePlay'), async () => { try { if (!singlePlay) { // TODO const bytes = await this.getMessageHeartbeat(true); // TODO globalThis.judgeUdp.send(bytes) } } catch (e) { console.info(judgeTag, JSON.stringify(e)) } await endExam() }); } // 考试结束 public endExam = async (isManual?: Boolean) => { const carInfo = AppStorage.get('carInfo'); const singlePlay = AppStorage.get('singlePlay') const examSubject = carInfo.examSubject const plateNo = carInfo.plateNo const judgeUI = this.judgeUI const ksjs = this.ksjs const getPhoto = this.getPhoto const avPlayer = this.avPlayer const kfArr = this.kfArr const filePath = this.filePath const closeAllFiles = this.closeAllFiles const lsh = judgeUI.lsh; const idCard = judgeUI.idCard; const serialNumber = judgeUI.serialNumber; const kssycs = judgeUI.kssycs; const totalScore = judgeUI.totalScore; const judgeConfigObj = judgeUI.judgeConfigObj; const isAllProjectsEnd = judgeUI.isAllProjectsEnd; const passingScore = judgeUI.passingScore; //TODO 断网考试结束补传 // await uploadDisConnectData(); const time = GetCurrentTime(); const photoBase64 = await getPhoto(); const d1 = ksjs.d1; const d2 = ksjs.d2; const d3 = ksjs.d3; const d4 = ksjs.d4; const d5 = ksjs.d5; const drvexam: DrvexamType = { lsh, kchp: encodeURI(plateNo), kskm: examSubject, sfzmhm: idCard, 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 data: RegulatoryInterfaceParams = { xtlb: '17', jkxlh: serialNumber, jkid: '17C56', drvexam } let backTimeOut = setTimeout(() => { router.back() }, 90 * 1000) const temp = await this.sendWriteObjectOut(data, filePath); promptWxCode('17C56', temp.code) if (temp.code != 1) { avPlayer.playAudio(['voice/监管失败.mp3']) this.judgeUI.errorMsg = decodeURIComponent(temp.message) if (temp.code == 2300028 || temp.code == 2300007) { this.judgeUI.errorMsg = '当前的考试过程信息监管审核未通过,程序将退出!' } this.isUdpEnd = true; closeAllFiles() this.judgeUI.loadingPopupVisible = false; return } console.info(judgeTag, '考试结束 end') const param302: string = Reflect.get(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'); USER[0].kssycs = currentKssycs await SqlInsertTable('USER', USER) console.info(judgeTag, `考试成绩:${totalScore}`) if (!singlePlay) { // await uploadProgressData(); } clearTimeout(backTimeOut) //语音播放扣分项 let score = 0; //结束考试时候是否播报一遍所有扣分 const param634: string = Reflect.get(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: GetDqxmStr = (xmdm) => { const project: ProjectInfo = Reflect.get(this.judgeUI.projectsObj, xmdm) return project?.abbreviation || '通用评判' } // 扣分项目转换 getKfStr: GetKfStr = (code) => { const markRuleListObj = this.judgeUI.markRuleListObj; const thisMark: MarkRule = Reflect.get(markRuleListObj, code) return { desc: thisMark.markshow, score: thisMark.markreal, markcatalog: thisMark.markcatalog, markserial: thisMark.markserial, kfxh: thisMark.kfxh } } // 消息心跳发送 // getMessageHeartbeat = async (isEnd?: Boolean) => { // const carInfo = AppStorage.get('carInfo'); // const { examSubject, plateNo, ksyh } = carInfo; // const { // judgeUI, // isExam, // serialIndex, // tempData, // xmmcCode, // xmxh, // xmmcSingleCode, // xmdm, // performInfo, // kfArr, // getTranslateProject, // getSbxh, // fileLog, // } = this; // const singlePlay = AppStorage.get('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 = StringToASCII( // fillZero((singlePlay ? (examSubject == 2 ? '0000000000000' : '1111111111111') : lsh) || 0, 13) // ); // //13不足要补0 // const ascksyhArr = StringToASCII(fillZero(ksyh || 0, 13)) // const ascsbxhArr = StringToASCII(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]) // ) // const translateJd = convertGpsCoord2(wd).toFixed(gpsDigit) * Math.pow(10, gpsDigit); // const translateWd = convertGpsCoord2(jd).toFixed(gpsDigit) * Math.pow(10, gpsDigit) // const translateProjects = translateProject.map(numStr => string2Bytes(parseInt(numStr, 2), 8)[0]) // // 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}${AppStorage.get('startHourTime') || startHourTime}`, 4 * 8), // // TODO 消息序号从1开始,0结束 // string2Bytes(isEnd ? 0 : serialIndex, 2 * 8), // /*左向灯 右向灯 双跳灯 远光灯 近光灯 视宽灯 点火1 点火2 离合器 脚刹 手刹 副刹 喇叭 门开关 安全带 档位 车辆状态 雨刮器 雾灯 0*/ // translateSignals, // //速度 发动机转速 GPS纬度 GPS经度 主天线位置 // 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}${AppStorage.get('startHourTime') || startHourTime},`); // fileLog.setFourAndOneLogDataBytes(tempArr.toString()); // return Array2Byte(tempArr) // } //获取场地序号 getSbxh: GetgSbbm = (ksxm, xmxh) => { const judgeUI = this.judgeUI; const projectsObj = judgeUI.projectsObj; const cdsbInfoObj = judgeUI.cdsbInfoObj; const project: ProjectInfo = Reflect.get(projectsObj, ksxm); if (judgeUI.examSubject == '3') { return '0000000000' } if (project === undefined) { return '0000000000' } const projectKey = `${ksxm}_${xmxh}`; const currentCdsb: CDSBInfo = Reflect.get(cdsbInfoObj, projectKey) || {} const sbxh: string = currentCdsb.sbbh || '0000000000' return sbxh } getSbbm: GetgSbbm = (ksxm, xmxh) => { const judgeUI = this.judgeUI; const cdsbInfoObj = judgeUI.cdsbInfoObj; const projectsObj = judgeUI.projectsObj; const project: ProjectInfo = Reflect.get(projectsObj, ksxm); //科目三不需要 if (judgeUI.examSubject == '3') { return undefined } if (project === undefined) { return '00000000' } const projectKey = `${ksxm}_${xmxh}`; const currentCdsb: CDSBInfo = Reflect.get(cdsbInfoObj, projectKey) || {} const sbxh: string = currentCdsb.sbbm || '00000000' return sbxh } // 中心所有项目转换 getTranslateProject = () => { const examSubject = this.judgeUI.examSubject; const tempItems: TKmItem[] = (examSubject == '2' ? testKm2Items : testKm3Items).map(item => { const kmItem: KmItem = Reflect.get(this.kmItems, item.code) const status = getCenterProjectStatus(kmItem.status) const temp: TKmItem = { code: item.code, status } return temp }) const arr: string[] = []; 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: number) => { const project: ProjectInfo = Reflect.get(this.judgeUI.projectsObj, projectCode) return project } // 获取模型数据 getModelData = (modelName: string) => { const modelData = this.fileModel.getModelContent(this.modelPath, modelName); return modelData } // 统计必考项目、所有项目、已考数量 setCountItems = async () => { const projectsObj = this.judgeUI.projectsObj; //必考项目数量 必考项目已考数量 let projectNum = 0, endProjectsNum = 0; // 所有考试项目数量 项目已考项目数量 let allProjectNum = 0, allEndProjectsNum = 0; Reflect.ownKeys(projectsObj).forEach(projectKey => { const projectObj: ProjectInfo = Reflect.get(projectsObj, projectKey) const type = projectObj.type const isRequired = projectObj.isRequired 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) } // 检测差分状态 checkDwzt = async (type: number) => { const avPlayer = this.avPlayer; 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) } //开始评判 private async judging(callBack: Function) { const judgeUI = this.judgeUI; const name = judgeUI.name const lsh = judgeUI.lsh const idCard = judgeUI.idCard const kssycs = judgeUI.kssycs const manualMarkRules = judgeUI.manualMarkRules const fileLog = new FileLog(judgeUI.context); const filePath = await fileLog.initFileLogo({ name, lsh, idCard }); this.fileLog = fileLog; this.filePath = filePath; const getJudgeBeginData = this.getJudgeBeginData; const handleUdp = this.handleUdp; const handDistance = this.getJudgeBeginData; const handleTrajectoryUdp = this.handleTrajectoryUdp; const isTrajectoryOpen = this.isTrajectoryOpen; const trajectoryPath = this.trajectoryPath; const avPlayer = this.avPlayer; const isJudgeInitBool = AppStorage.get('isJudgeInitBool'); let strArr: string[] = []; if (isTrajectoryOpen) { const folderPath = await this.fileUtil.initFolder(trajectoryPath); const str: string = await this.fileUtil.readFile(folderPath) strArr = str.split('\n') } //日志回调 console.info(judgeTag, '1.进入评判入口') await examJudgeSetLogCallback(3, async (level: number, info: string, len: number) => { console.log('评判日志:' + info) await fileLog.setExamJudgeLogData(info); }) console.info(judgeTag, '2.注册日志回调完成') let initInfo: JudgeInitObj = isTrajectoryOpen ? JSON.parse(strArr[0]) : await this.getJudgeInitData(); await fileLog.setExamJudgeData(JSON.stringify(initInfo)) //相关评判初始化只做一次 if (!isJudgeInitBool) { const tempJudge = await examJudgeInit(initInfo); AppStorage.setOrCreate('isJudgeInitBool', true) console.info(judgeTag, '4.评判初始化完成') } AppStorage.setOrCreate('isJudge', true) // 2.评判过程回调 await examJudgeSetRealExamCallback(async (strData: string, len: number) => { await fileLog.setExamJudgeCallbackData(strData) console.info('评判回调数据', strData) this.handleRealExam(strData, callBack) }) await examJudgeSetPerformCallback(async (info: string) => { console.info('评判实时数据', info) const performInfo: JudgePerformInfo = JSON.parse(info) this.performInfo = performInfo const jl = Math.floor((performInfo.qjjl + performInfo.dcjl) / 100); if (jl > Number(this.judgeUI.examMileage)) { this.checkExamIsEnd() } this.judgeUI.jl = jl //TODO 待优化 跨组件传值不生效 // globalThis.laneData = performInfo.lane; }) let beginExamInfo: JudgeBeginObj = undefined // 3.开始考试 if (isTrajectoryOpen) { beginExamInfo = JSON.parse(strArr[1]) beginExamInfo.replay = 1 } else { beginExamInfo = await getJudgeBeginData() } await fileLog.setExamJudgeData(JSON.stringify(beginExamInfo)) await examJudgeBeginExam(beginExamInfo); console.info(judgeTag, '6.开始考试注册完成') avPlayer.playAudio([judgeUI.singlePlay ? 'voice/ksks.wav' : 'voice/监管成功.mp3']) if (!judgeUI.singlePlay) { this.videoData = await saveStartRecordVideo(`${name}_${kssycs}`, this.context) } // 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(); //TODO UDP修改 // 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() //TODO 监听远程结束考试 // globalThis.udpEvent.onEndExam(async () => { // this.checkExamIsEnd(true); // }) console.info(judgeTag, JSON.stringify(manualMarkRules)) //TODO 监听远程扣分 // globalThis.udpEvent.onKfExam(async (content:JudgeUdpKf) => { // console.info('评判收到远程扣分项目内容' + JSON.stringify(content)) // const kfxh = content.data.kfxh; // const directives = content.data.directives; // console.info(judgeTag, '评判收到远程扣分项目内容,扣分序号:' + `kfxh=>${kfxh}; directives=>${directives}`) // //根据扣分序号找扣分代码 // const currentKf:MarkRule = manualMarkRules.filter(mark => mark.kfxh == kfxh)[0]; // console.info(judgeTag, '扣分项目:' + JSON.stringify(currentKf)) // this.setJudgeMark(String(currentKf.itemno), currentKf.markserial, 2); // //TODO // //globalThis.judgeUdp.confirmKf(directives, 1) // }) this.checkExamIsEnd(); } }