2024-09-19 18:46:35 +08:00

1676 lines
54 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import systemTime from '@ohos.systemDateTime';
import router from '@ohos.router';
import util from '@ohos.util';
import buffer from '@ohos.buffer';
import { testKm2Items,testKm3Items, testMarkRules } from './dataTest/index';
import { EXAMDATA, SOUND, KSJS } from './api/judgeSDK';
import VoiceAnnounce from './utils/voiceAnnouncements';
import FileModel from './utils/fileModel';
import FilePhoto from './utils/filePhoto';
import FileUtil from '../../common/utils/File';
import FileLog from './utils/fileLog';
import JudgeTask from './utils/judgeTask';
import { judgeConfig } from './utils/judgeConfig';
import { uploadExamProgressData, writeObjectOut } from '../../api/judge';
import UsbService from '../../common/service/usbService';
import { LANE,KF } from '../judgeSDK/api/judgeSDK.d';
import {saveStartRecordVideo,endRecordVideo} from '../../common/service/videoService'
import {
Array2Byte,
convertGpsCoord2,
deepClone,
fillZero,
getCurrentTime,
string2Bytes,
stringToASC
} from '../../common/utils/tools';
import {
getCarStatus,
getCarStatusType,
getDwStatusType,
getCenterProjectStatus,
getKmProjectVoice,
getTranslateSignals,
plcStrToJson,
plcStrToWXJson,
promptWxCode,
senorToWXDataStr,
getKmProjectCancelVoice
} from './utils/judgeCommon';
import {
examJudgeArtificialItem,
examJudgeArtificialMark,
examJudgeBeginExam,
examJudgeEndExam,
examJudgeInit,
examJudgeSoundEnd,
examJudgeRealExam,
examJudgeSetLogCallback,
examJudgeSetPerformCallback,
examJudgeSetRealExamCallback,
examCalcGpsDistance,
examJudgeVersion
} from './api/index';
const judgeTag = 'SURENJUN_JUDGE'
import { getSyncData, upDateTableByArray } from '../../common/service/initable';
export default class Judge {
constructor(judgeUI) {
this.serialIndex = 1;
this.judgeUI = judgeUI
//语音播放工具
this.avPlayer = new VoiceAnnounce();
//模型工具
this.fileModel = new FileModel(judgeUI.context);
//文件工具
this.fileUtil = new FileUtil(judgeUI.context)
this.judgeTask = new JudgeTask()
this.usbService = new UsbService();
this.filePhoto = new FilePhoto(judgeUI.context);
this.kfArr = judgeUI.kfArr
this.xmmcStr = '';
this.xmmcCode = '';
this.carztStr = '';
this.testKmItems = {};
// 考试回放配置
const {isTrajectoryOpen,modelPath,trajectoryPath} = judgeConfig
this.isTrajectoryOpen = isTrajectoryOpen;
this.modelPath = modelPath;
this.trajectoryPath = trajectoryPath;
this.isExam = !this.judgeUI.singlePlay;
const {projectsCenterObj,examSubject} = judgeUI;
(examSubject ==2 ? testKm2Items : testKm3Items ).forEach(item => {
const projectCenterObj = projectsCenterObj[item.code]
this.testKmItems[item.code] = item;
//考试项目存在
this.testKmItems[item.code] = {
code: item.code,
status: projectCenterObj === undefined
? 0
: ( projectCenterObj.isEnd ? 3 : 1 )
}
})
console.info(judgeTag+'testKmItems',JSON.stringify(this.testKmItems))
this.isExamEnd = false;
}
public async onJudgeFn(fn: Function) {
await this.judging(fn)
}
//开始评判
private async judging(callBack: Function) {
const {judgeUI} = this;
const { name, lsh, idCard,kssycs} = judgeUI;
const fileLog = new FileLog(judgeUI.context);
const filePath = await fileLog.initFileLogo({
name, lsh, idCard
});
this.fileLog = fileLog;
this.filePath = filePath;
const {getJudgeBeginData,handleUdp,handDistance,fileUtil,handleTrajectoryUdp,isTrajectoryOpen,trajectoryPath,avPlayer} = this;
const isJudgeInitBool = globalThis.isJudgeInitBool;
let strArr = [];
if (isTrajectoryOpen) {
const folderPath = await this.fileUtil.initFolder(trajectoryPath);
const str = await fileUtil.readFile(folderPath)
strArr = str.split('\n')
}
//日志回调
console.info(judgeTag, '1.进入评判入口')
await examJudgeSetLogCallback(3, async (level, info, len) => {
console.log('评判日志:' + info)
await fileLog.setExamJudgeLogData(info);
})
console.info(judgeTag, '2.注册日志回调完成')
let initInfo = isTrajectoryOpen ? JSON.parse(strArr[0]) : await this.getJudgeInitData();
await fileLog.setExamJudgeData(initInfo)
//相关评判初始化只做一次
if (!isJudgeInitBool) {
const tempJudge = await examJudgeInit(initInfo);
globalThis.isJudgeInitBool = true
console.info(judgeTag, '4.评判初始化完成')
}
globalThis.isJudge = true
// 2.评判过程回调
await examJudgeSetRealExamCallback(async (strData, len) => {
await fileLog.setExamJudgeCallbackData(strData)
console.info('评判回调数据', strData)
this.handleRealExam(strData, callBack)
})
await examJudgeSetPerformCallback(async (info) => {
console.info('评判实时数据', info)
const performInfo = JSON.parse(info)
this.performInfo = performInfo
this.judgeUI.jl = Math.floor((performInfo.qjjl + performInfo.dcjl) / 100)
//TODO 待优化 跨组件传值不生效
globalThis.laneData = performInfo.lane;
})
// 3.开始考试
let beginExamInfo = isTrajectoryOpen ? {
...JSON.parse(strArr[1]),
replay: 1,
} : await getJudgeBeginData()
await fileLog.setExamJudgeData(beginExamInfo)
await examJudgeBeginExam(beginExamInfo);
console.info(judgeTag, '6.开始考试注册完成')
avPlayer.playAudio([globalThis.singlePlay ? 'voice/ksks.WAV' : 'voice/监管成功.mp3'])
if(!globalThis.singlePlay){
this.videoData = await saveStartRecordVideo(`${name}_${kssycs}`)
}
const {examSubject,projectsObj} = this.judgeUI
if(examSubject == 3){
//不做模拟灯光,需要做上车准备 =>(请上车准备)
if(projectsObj[41]?.type == 3 && projectsObj[1]?.type != 3){
avPlayer.playAudio(['voice/上车准备.mp3'])
}
//不做模拟灯光,不做上车准备 =>(请起步,完成考试)
if(projectsObj[41]?.type == 3 && projectsObj[1]?.type == 3){
avPlayer.playAudio(['voice/402001.mp3'])
}
}
this.judgeUI.draw = true
// 处理轨迹plc信息
if (isTrajectoryOpen) {
handleTrajectoryUdp(strArr);
return
}
// 处理实时udp里的plc信号
// globalThis.udpClient.closeMessage_1();
globalThis.udpClient.onMessage_1(async (msg) => {
console.info('socketTag[PLC.UdpClient]', '收到udp回调数据')
handleUdp(msg)
const udpIndex = globalThis.udpIndex;
if (udpIndex % 5 === 0) {
handDistance();
}
})
globalThis.udpEvent.onBeginExam(async ()=>{
this.checkExamIsEnd(true);
})
//TODO 监听远程扣分
}
//实时计算gps经纬度距离
handDistance= async ()=>{
const {jd,wd,hxj,dwzt,jdzt} = this.tempData.gps;
const tJD = convertGpsCoord2(jd)
const tWD = convertGpsCoord2(wd)
const {prevJd,prevWd} = this
if(prevJd && dwzt == 4 && jdzt == 3){
const distance = await examCalcGpsDistance({
jd1:prevJd,
wd1:prevWd,
jd2:tJD,
wd2:tWD,
h:hxj || 1,
})
//@ts-ignore
globalThis.distanceClass?.setTimeData(((distance / 100).toFixed(2)) * 1)
}
this.prevJd = tJD;
this.prevWd = tWD;
}
// 获取评判初始化数据
getJudgeInitData = async () => {
const {getModelData,getKm3JudgeInitConfig} = this
const carInfo = globalThis.carInfo;
const { examSubject,plateNo,carId } = carInfo;
const judgeUI = this.judgeUI
const {projectsObj,itemInfoObj,markRuleListObj,carType,carName,systemparmArr} = judgeUI
const examType = examSubject == 2 ? 'km2' : 'km3'
let allitems = [];
if (examSubject == 2) {
allitems = Reflect.ownKeys(itemInfoObj).map(cdsbKey => {
const cdsb = itemInfoObj[cdsbKey];
const {xmdm,xmxh,modelKey} = cdsb
return {
xmdm, xmxh, model: getModelData(`${examType}/${modelKey}.txt`)
}
})
}
//获取版本号
const sdkver = await examJudgeVersion();
const initInfo = {
sdkver,
appver:globalThis.version,
kskm: examSubject * 1,
kchp: plateNo,
kchm: carId * 1,
kscx: carType,
cxcode: '1',
name: carName,
carmodel: getModelData(`${examType}/${carType}.txt`),
allitems,
iteminfo: [],
systemparm: systemparmArr,
mark: Reflect.ownKeys(markRuleListObj).map(ruleKey => (markRuleListObj[ruleKey])) || testMarkRules,
sysset: judgeUI.judgeConfig,
itemInfoObj,
carlist:judgeUI.carlist
};
let km3Config = {}
if (examSubject == 3) {
km3Config = await getKm3JudgeInitConfig();
}
// 获取科目三的评判配置
console.info(judgeTag, '3.获取评判初始化数据完成')
return {
...initInfo,
...km3Config,
}
}
// 获取开始考试数据
getJudgeBeginData = async () => {
const {code,name:examinerName} = globalThis.examinerInfo;
let currentParams: any = router.getParams();
const {sczb,kfdm} = currentParams;
const {isExam} = this;
const judgeUI = this.judgeUI
const {projects,carType,isDdxk,ddxkTime,projectsCenterObj,ddxkKsxmArr,ddxkKfArr,passingScore} = judgeUI;
const beginInfo = {
kgid: '012',
kgxm: decodeURI(examinerName || ''),
exam: isExam ? 1 : 0,
//是否回放
replay: 0,
//生成的轨迹文件
track: '',
xm: judgeUI.name,
sex: 0,
kslsh: judgeUI.lsh,
sfzmhm: judgeUI.idCard,
ksyy: '',
kscx: carType,
kkcs: 1,
sfyk: 0,
ykkkcs: 1,
wayno: judgeUI.wayno * 1,
czlx: 0,
kskssj: await systemTime.getCurrentTime(),
passing:passingScore * 1,
ksxm: projects.map(project => {
return {
xmdm: project.projectCode * 1,
xmxh: '',
}
}),
//断点续考
ddxk: isDdxk ? 1 : 0,
ddkssj: ddxkTime || 0,
ykxm: (ddxkKsxmArr?.map(projectCenterCode => (projectsCenterObj[projectCenterCode]?.projectCode) * 1)) || [],
kfxm: isDdxk ? (ddxkKfArr?.map(kf => {
const [xmdm, kfdm] = kf.split(',')
return {xmdm: xmdm * 1,kfdm}
})) : [],
//TODO 已考里程待修改
yklc: 0,
special: [],
//TODO 科目三参数临时写死
sczb: (sczb === undefined || sczb == 0) ? 0 : 1,
sczbkf: kfdm,
dmndg: false,
mfxx: false,
mfxxn: false
}
console.info(judgeTag, '5.获取开始考试数据完成')
return beginInfo
}
//处理评判过程回调
handleRealExam = async (strData, callBack) => {
let examData: EXAMDATA = JSON.parse(strData);
const {getDqxmStr,getKfStr,goJudgeVoice,setMndg,avPlayer,fileLog,judgeUI} = this;
const {carzt,xmks,kf,event,xmjs,xmqx,ksjs,sound,mndg,lane,precast} = examData
const param512 = (judgeUI.judgeConfigObj['512'] || '').split(',');
//获取项目结束、项目开始代码
const xmdm = event == 2 ? xmjs.xmdm : xmks.xmdm
const xmxh = event == 2 ? xmjs.xmxh : xmks.xmxh;
const isManualProjectIn = this.artSubject3ProjectsCodesArr.includes(xmdm);
const {examSubject,projects,judgeConfigObj} = this.judgeUI;
const param611 = judgeConfigObj['611'] || '';
switch (event) {
//项目开始
case 1:
judgeUI.projectsObj[xmdm].type = '2';
if (isManualProjectIn) {
//手动项目是否在进行中
this.judgeUI.isManualProjectIn = true
}
if (xmdm == 41 && examSubject == 3) {
this.rmndg = 1
}
this.judgeUI.currentXmdm = xmdm;
const xmmcStr = judgeUI.projectsObj[xmdm].name;
const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter;
const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode;
this.testKmItems[xmmcCode].status = 2;
this.xmmcStr = xmmcStr;
this.xmmcCode = xmmcCode;
this.xmmcSingleCode = xmmcSingleCode
this.xmdm = xmdm;
this.xmxh = xmxh;
this.judgeUI.isProjectIn = true
if(param512[7] != 0){
this.judgeUI.isDeductedPopShow = true
}
break;
//项目结束
case 2: {
const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter;
judgeUI.projectsObj[xmdm].type = (xmjs.xmhg === 0 ? '4' : '3');
//计算项目是否全部结束
this.judgeUI.isProjectIn = (Reflect.ownKeys(judgeUI.projectsObj).filter(
projectKey => judgeUI.projectsObj[projectKey].type == '2').length
) > 0;
if (isManualProjectIn) {
this.judgeUI.isManualProjectIn = false
}
this.testKmItems[xmmcCode].status = 3;
//统计必考项目数量
this.xmmcStr = '无';
this.xmmcCode = '';
this.xmdm = '';
this.judgeUI.isDeductedPopShow = false
this.judgeUI.currentXmdm = undefined;
break;
}
//扣分
case 3:
const thisKf = getKfStr(`${kf.xmdm}_${kf.kfdm}`)
//扣分信息
this.kfArr.push({
//扣分项目名称
xmmcStr: getDqxmStr(kf.xmdm),
xmdm: kf.xmdm,
//扣分描述
desc: thisKf.desc,
//扣分分数
score: thisKf.score,
// 扣分无锡所代码
markcatalog: thisKf.markcatalog,
markserial: thisKf.markserial,
kfxh: thisKf.kfxh,
//扣分类型
type: kf.type
})
this.judgeUI.totalScore += thisKf.score * 1;
break;
//考车状态
case 4:
this.carztStr = getCarStatus(carzt);
break;
//考试结束
case 5:
this.ksjs = ksjs;
await fileLog.setExamJudgeData({
method: 'examJudgeEndExam',
})
break;
//项目取消
case 6:{
console.info(judgeTag,'项目取消');
const {examSubject} = this.judgeUI
const xmdm = xmqx.xmdm;
const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter;
const voiceCode = getKmProjectCancelVoice(examSubject,xmmcCode);
avPlayer.playAudio([`voice/${voiceCode}.mp3`],true)
this.judgeUI.projectsObj[xmdm].type = '1';
this.testKmItems[xmmcCode].status = '1';
break;
}
//语音播放和提示
case 7:
goJudgeVoice(sound)
break;
//模拟灯光事件
case 8:
setMndg(mndg)
break;
//车道和路段变化
case 9:
this.judgeUI.lane = lane
this.lane = lane;
break;
//预进项目事件
case 10:{
const param611 = judgeConfigObj['611'] || '';
const [f,s] = param611.split('/')
const {xmdm} = precast;
const xmmcCode = judgeUI.projectsObj[xmdm].projectCodeCenter;
const xmmcSingleCode = judgeUI.projectsObj[xmdm].projectCode;
if(examSubject == 2 && ((xmdm == 0 && f == 1) || (xmdm == 1 && s == 1) || xmdm == 3)){
//倒车入库/桩考/侧方停车
avPlayer.playAudio([`voice/${xmmcCode}.mp3`],false)
}
this.testKmItems[xmmcCode].status = 2;
this.xmmcStr = xmmcStr;
this.xmmcCode = xmmcCode;
this.xmmcSingleCode = xmmcSingleCode;
judgeUI.projectsObj[xmdm].type = '2';
}
break;
default:
break;
}
const {xmmcStr,carztStr,kfArr} = this;
await callBack({
//项目名称 考车状态 扣分arr
xmmcStr, carztStr, kfArr
});
//语音播报
this.goVoiceAnnounce(event, xmdm, this.kfArr, xmjs, ksjs,xmxh)
//更新UI
if (event == 1 || event == 2 || event == 3 || event == 6) {
const copyProjectsObj = this.judgeUI.projectsObj;
judgeUI.projectsObj = deepClone(copyProjectsObj);
}
}
// 更改考试状态
goVoiceAnnounce = async (event, xmdm, kf, xmjs, ksjs,xmxh) => {
const {
beginProject,
pointsDedute,
endProject,
avPlayer,
uploadProgressPhoto,
judgeTask,
handEndExam,
judgeUI,
checkExamIsEnd,
checkProjectIsStart,
lane
} = this;
const {projectsObj,judgeConfigObj,examSubject,examMileage,jl,isAllProjectsEnd} = judgeUI;
const kfLen = kf.length;
//不报语音的项目列表
const ignoreVoiceCodeArr = (judgeConfigObj['312'] || '').split(',')
const param611 = judgeConfigObj['611'] || '';
const [f,s] = param611.split('/')
switch (event) {
// 项目开始
case 1:
const code = projectsObj[xmdm].projectCodeCenter;
const isEnd = projectsObj[xmdm].isEnd;
const kmCode = getKmProjectVoice(code, 1, judgeConfigObj, lane,xmxh)
if (!ignoreVoiceCodeArr.includes(code)) {
if(examSubject == 2 && ((xmdm == 0 && f == 2) || (xmdm == 1 && s == 2) || xmdm == 3)){
//倒出入库、桩考\进项目语音控制
}else{
kmCode && avPlayer.playAudio([`voice/${kmCode}.mp3`],true)
}
}
//项目已考不上传监管信息
if (!isEnd) {
judgeTask.addTask(async () => {
console.info(judgeTag, `项目开始-${xmdm}-${projectsObj[xmdm].name}`)
await beginProject(xmdm)
},{isDelay: true})
judgeTask.addTask(async () => {
console.info(judgeTag, `项目-${xmdm}-上传照片 start`)
await uploadProgressPhoto(xmdm)
},{isDelay: true})
this.judgeUI.projectsObj[xmdm].isUpload = true;
}
break;
// 项目结束
case 2:{
const endCode = projectsObj[xmdm].projectCodeCenter;
const projectIsEnd = projectsObj[xmdm].isEnd;
const endKmCode = getKmProjectVoice(endCode, 2, judgeConfigObj, lane,xmxh)
if (!ignoreVoiceCodeArr.includes(endCode) && examSubject == 3) {
endKmCode && avPlayer.playAudio([`voice/${endKmCode}.mp3`])
}
const isStart = await checkProjectIsStart(xmdm,1);
if(isStart){
//项目结束了就不再生成数据
console.info(judgeTag + ' projectIsEnd =>',projectIsEnd)
if (!projectIsEnd) {
judgeTask.addTask(async () => {
console.info(judgeTag, `项目结束-${xmdm}-${projectsObj[xmdm].name}`)
await endProject(xmdm);
this.xmmcSingleCode = 0;
}, {isDelay: true})
}
}
judgeUI.projectsObj[xmdm].isEnd = true;
break;
}
// 扣分
case 3:
//扣分时实时播报语音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, '考试结束')
judgeTask.addTask(async () => {
console.info(judgeTag, '考试结束 start')
globalThis.isJudge = false;
await handEndExam(ksjs)
})
clearInterval(globalThis.judgeTimer)
break
default:
break
}
if (event == 2 || event == 3) {
setTimeout(() => {
this.judgeUI.kfArrScroller.scrollTo({
yOffset: 999999, xOffset: 0
})
},500)
//统计必考项目完成数量
await this.setCountItems();
await checkExamIsEnd()
}
}
// 检测扣分、结束项目时该项目是否开始
checkProjectIsStart = async(xmdm,currentType:1|2,kf?:KF) => {
if(xmdm == 20){
return true
}
const {judgeTask,beginProject,pointsDedute,uploadProgressPhoto,endProject,checkExamIsEnd,totalScore} = this;
const {projectsObj,passingScore:passingGrade} = this.judgeUI
const {isUpload} = projectsObj[xmdm];
//如果项目没有开始
console.info('surenjun isUpload=>',isUpload)
if(!isUpload){
console.info(judgeTag,'项目补传开始')
//项目开始补传
judgeTask.addTask(async ()=>{await beginProject(xmdm)},{isDelay:true})
judgeTask.addTask(async ()=>{await uploadProgressPhoto(xmdm)},{isDelay:true})
this.judgeUI.projectsObj[xmdm].isUpload = true;
//扣分补传
if(currentType == 2){
judgeTask.addTask(async ()=>{await pointsDedute(xmdm,kf)},{isDelay:true})
}
//扣分补传判断是否合格 不合格补传项目结束
if(currentType == 1 || (currentType == 2 && totalScore < passingGrade)){
judgeTask.addTask(async ()=>{await endProject(xmdm)},{isDelay:true})
this.judgeUI.projectsObj[xmdm].isEnd = true;
}
judgeTask.addTask(async ()=>{
checkExamIsEnd()
})
return false;
}else{
return true
}
}
// 项目开始接口同步
beginProject = async (ksxm) => {
const carInfo = globalThis.carInfo;
const { examSubject,plateNo } = carInfo;
const {judgeUI,fileLog,getSbbm,xmxh,filePath} = this;
const {lsh,idCard,serialNumber,projectsObj,ksdd,kslx,xldm} = judgeUI
const time = await getCurrentTime();
const project = projectsObj[ksxm]
const sbxh = getSbbm(ksxm, xmxh)
const data = {
//系统类别 接口序列号 接口标识
xtlb: '17', jkxlh: serialNumber, jkid: '17C52',
drvexam: {
// 考试科目 身份证号码
lsh,
kskm: examSubject,
sfzmhm: idCard,
ksxm: project.projectCodeCenter,
sbxh,
ksxl:xldm,
kchp: encodeURI(plateNo),
// 开始时间
ksdd: encodeURI(ksdd),
kslx: encodeURI(kslx) || '',
kssj: time
}
}
const {code} = await writeObjectOut(data,filePath)
console.info(judgeTag, '项目开始 end')
if (code === 2300007) {
this.isJudgeDisConnect = true;
}
promptWxCode('17C52', code)
}
// 项目结束接口同步
endProject = async (ksxm) => {
const carInfo = globalThis.carInfo;
const deviceNo = globalThis.deviceNo;
const { examSubject,plateNo,carNo } = carInfo;
const {judgeUI,fileLog,getSbxh,xmxh,getSbbm,filePath} = this;
const {lsh,idCard,serialNumber,projectsObj,cdsbInfoObj,ksdd,kslx,xldm,} = judgeUI
const time = await getCurrentTime();
const project = projectsObj[ksxm]
const sbxh = examSubject == 3 ? undefined : getSbbm(ksxm, xmxh)
const data = {
xtlb: '17', jkxlh: serialNumber, jkid: '17C55',
drvexam: {
lsh,
kskm: examSubject,
sfzmhm: idCard,
ksxm: project.projectCodeCenter,
sbxh,
//TODO 操作类型 1:正常 0:撤销该考试记录
czlx: '1',
ksxl:xldm,
kchp: encodeURI(plateNo),
ksdd: encodeURI(ksdd),
kslx: encodeURI(kslx) || '',
jssj: time
}
}
const {code} = await writeObjectOut(data,filePath)
if (code === 2300007) {
this.isJudgeDisConnect = true;
}
console.info(judgeTag, '项目结束 end')
promptWxCode('17C55', code)
}
// 考试扣分
pointsDedute = async (ksxm, kf) => {
const carInfo = globalThis.carInfo;
const deviceNo = globalThis.deviceNo;
const { examSubject,plateNo,carNo } = carInfo;
const {judgeUI,getProjectInfo,fileLog,xmmcSingleCode,filePath} = this;
const {lsh,idCard,serialNumber,ksdd,projectsObj} = judgeUI
const time = await getCurrentTime();
const project = getProjectInfo(ksxm);
//科目三夜间行驶.模拟灯光、上车准备出现通用评判ksxm为当前进行的项目
const checkProjects = ['17', '41', '1'];
//获取正在进行的项目
const inProjects = Reflect.ownKeys(projectsObj).filter(projectKey => projectsObj[projectKey].type == 2);
let commonKsxm = '';
checkProjects.forEach(projectCode=>{
if(inProjects.includes(projectCode)){
commonKsxm = projectCode
}
})
const data = {
xtlb: '17', jkxlh: serialNumber, jkid: '17C53',
drvexam: {
lsh,
kskm: examSubject,
ksxm: project == undefined
? (commonKsxm
? (projectsObj[commonKsxm].projectCodeCenter)
: (examSubject == 3 ? 30000 : 10000))
: project.projectCodeCenter ,
kfxm: kf.markcatalog,
kfxmmx: `${ksxm},${kf.markserial}`,
sfzmhm: idCard,
kchp: encodeURI(carInfo.plateNo),
//扣分方式
kffs: kf.type == 0 ? 1 : 2,
ksdd: encodeURI(ksdd),
kfsj: time
}
}
console.info(judgeTag + 'ksxm=>',data.drvexam.ksxm)
const {code} = await writeObjectOut(data,filePath);
if (code === 2300007) {
this.isJudgeDisConnect = true
}
console.info(judgeTag, '项目扣分 end')
promptWxCode('17C53', code)
}
// 考试过程照片
uploadProgressPhoto = async (ksxm) => {
const time = await getCurrentTime();
const {judgeUI,plcData,getPhoto,fileLog,filePath} = this;
const photoBase64 = await getPhoto();
const carInfo = globalThis.carInfo;
const { examSubject,plateNo,carNo } = carInfo;
const {lsh,idCard,serialNumber,projectsObj,ksdd,judgeConfigObj} = judgeUI;
const {sensor,gps} = plcData
const project = projectsObj[ksxm]
const data = {
xtlb: '17', jkxlh: serialNumber, jkid: '17C54',
drvexam: {
lsh,
kskm: examSubject,
ksxm: project.projectCodeCenter,
sfzmhm: idCard,
kchp: encodeURI(plateNo),
zpsj: time,
//@ts-ignore
zp: photoBase64,
cs: Math.floor((judgeConfigObj['350'] == 0?gps.sd:sensor.cs) * 1.852),
ksdd: encodeURI(ksdd)
}
};
const {code} = await writeObjectOut(data,filePath);
if (code === 2300007) {
this.isJudgeDisConnect = true
}
promptWxCode('17C54', code)
console.info(judgeTag, '上传照片 end')
}
// 评判语音提示
goJudgeVoice = async (sound: SOUND) => {
const {avPlayer,fileLog} = this;
const {xmdm,code,type} = sound;
//判断是不是模拟灯光语音
if (type == 1) {
avPlayer.playAudio([`voice/${code}.mp3`], false, () => {
examJudgeSoundEnd({
itemno: xmdm, code, type
})
fileLog.setExamJudgeData({
method: 'examJudgeSoundEnd',
itemno: xmdm,
code,
type,
})
})
}else{
avPlayer.playAudio([`voice/${code}.mp3`])
}
}
// 校验考试是否结束
checkExamIsEnd =
async (isManual?: boolean) => {
const {judgeUI,avPlayer,isExamEnd,isEndTip} = this;
const {isAllProjectsEnd,examSubject,singlePlay,totalScore,judgeConfigObj,passingScore} = judgeUI;
if (isExamEnd) {
return
}
//及格分
let passingGrade = passingScore
if (isManual) {
// 考试不合格
await examJudgeEndExam()
this.isExamEnd = true
this.isManual = true
} else {
const param302 = judgeConfigObj['302'];
const param342 = judgeConfigObj['342'];
const param512 = (judgeConfigObj['512'] || '').split(',');
//单机模式
if (singlePlay) {
console.info(judgeTag + ' isAllProjectsEnd => ',isAllProjectsEnd)
if (isAllProjectsEnd) {
//成绩合格
if(totalScore >= passingGrade && !isEndTip) {
if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) {
if(param512[7] != 0){
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){
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 && param302 == 4){
await examJudgeEndExam()
this.isExamEnd = true
return
}
if (examSubject == 3 && (param342 == 0 || param342 == 2) && (param302 != 6 || param302 != 7 || param302 != 8)) {
if(param512[7] != 0){
avPlayer.playAudio(['voice/综合评判.mp3'])
this.judgeUI.isDeductedPopShow = true
this.judgeUI.defaultTabIndex = 1
this.isEndTip = true
}
} else {
await examJudgeEndExam()
this.isExamEnd = true
}
}
}
}
}
// 处理考试结束
public handEndExam = async (ksjs: KSJS) => {
this.judgeUI.loadingPopupVisible = true;
this.judgeUI.endPopupVisible = false;
this.judgeUI.isDeductedPopShow = false;
const {qjjl,dcjl} = ksjs
const {judgeUI,endExam,handleSEP,kfArr,avPlayer,judgeTask,isManual} = this;
const {judgeConfigObj,examSubject,isAllProjectsEnd,totalScore,passingScore} = judgeUI;
//计算考试分数
// this.judgeUI.totalScore = isAllProjectsEnd ? totalScore : 0;
const singlePlay = globalThis.singlePlay
const param302 = judgeConfigObj['302'];
// globalThis.windowClass.setWindowSystemBarEnable(['navigation'])
//自动退出待验证并且不合格
if (!isManual && examSubject == 3 && (param302 == 1 || (singlePlay && param302 == 2)) && totalScore < passingScore) {
avPlayer.playAudio([`voice/考试结束.mp3`])
}
//联网模式下手动结束的直接退出
if (!singlePlay && isManual && !isAllProjectsEnd) {
avPlayer.playAudio(['voice/empty.mp3'], true, () => {
router.back();
})
return
}
if (examSubject == 3) {
const param302 = judgeConfigObj['302'];
if (totalScore < passingScore) {
//考试不合格;考试模式,自动退出;
if (param302 == 4 || param302 == 5 || param302 == 7 || param302 == 8) {
}
} else {
//考试合格
}
}
await handleSEP(306);
avPlayer.playAudio(['voice/exam_waiting.mp3'], globalThis.singlePlay, async () => {
try {
if (!singlePlay) {
const bytes = await this.getMessageHeartbeat(true);
globalThis.judgeUdp.send(bytes)
}
await endExam()
} catch (e) {
console.info(judgeTag,JSON.stringify(e))
// setTimeout(() => {
// // avPlayer.avPlayerStop();
// router.back();
// }, 3000)
}
});
}
// 考试结束
public endExam = async (isManual?: Boolean) => {
const carInfo = globalThis.carInfo;
const singlePlay = globalThis.singlePlay
const { examSubject ,plateNo} = carInfo;
const {judgeUI,ksjs,getPhoto,uploadProgressData,uploadDisConnectData,avPlayer,kfArr,judgeTask,filePath} = this;
const {lsh,idCard,serialNumber,kssycs,totalScore,judgeConfigObj,isAllProjectsEnd,passingScore} = judgeUI
await uploadDisConnectData();
const time = await getCurrentTime();
const photoBase64 = await getPhoto();
const {d1,d2,d3,d4,d5} = ksjs
const data = {
xtlb: '17', jkxlh: serialNumber, jkid: '17C56',
drvexam: {
lsh,
kchp: encodeURI(plateNo),
kskm: examSubject,
sfzmhm: idCard,
//@ts-ignore
zp: photoBase64,
jssj: time,
kscj: (totalScore * 1) > 0 ? totalScore : 0,
kslc: Math.ceil(((ksjs?.qjjl + ksjs?.dcjl) || 0) / 100),
// 1,22;2,560;3,128;4,0;5,0;
dwlc: [d1,d2,d3,d4,d5].map((d,index) => `${index+1},${Math.floor(d /100)}`).join(';'),
}
}
const {code,keystr,message} = await writeObjectOut(data,filePath);
promptWxCode('17C56', code)
if(code != 1){
avPlayer.playAudio(['voice/监管失败.mp3'])
this.isUdpEnd = true
router.back();
return
}
console.info(judgeTag, '考试结束 end')
const param302 = judgeConfigObj['302'];
judgeUI.loadingPopupVisible = true;
let currentKssycs =0;
let voiceURL = ''
if (examSubject == 2) {
if (isAllProjectsEnd) {
voiceURL = (totalScore < passingScore ? `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav` : 'voice/qualified.mp3')
}else{
voiceURL = `voice/unqualified_${kssycs == 1 ? 'one' : 'two'}.wav`
currentKssycs = kssycs == 1 ? 0 : 1
}
switch (voiceURL){
case 'voice/unqualified_one.wav':
currentKssycs = 0;
break;
case 'voice/unqualified_two.wav':
currentKssycs = 1;
break;
case 'voice/qualified.mp3':
currentKssycs = 0;
break;
}
}
if (examSubject == 3) {
if (isAllProjectsEnd) {
if (totalScore < passingScore) {
voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3`
currentKssycs = kssycs == 1 ? 0 : 1
} else {
voiceURL = 'voice/exam_pass.mp3'
currentKssycs = 0
}
} else {
voiceURL = `voice/${kssycs == 1 ? 'exam_no_pass_finish' : 'exam_no_pass'}.mp3`
currentKssycs = kssycs == 1 ? 0 : 1
}
switch (voiceURL){
case 'voice/exam_no_pass_finish.mp3':
currentKssycs = 0;
break;
case 'voice/exam_no_pass.mp3':
currentKssycs = 1;
break;
case 'voice/exam_pass.mp3':
currentKssycs = 0;
break;
}
}
const USER = await getSyncData('USER');
await upDateTableByArray('USER', [{
...USER[0],
kssycs:currentKssycs
}])
console.info(judgeTag, `考试成绩:${totalScore}`)
if(!singlePlay){
await endRecordVideo(this.videoData)
await uploadProgressData();
}
//语音播放扣分项
let score = 0;
//结束考试时候是否播报一遍所有扣分
const param634 = judgeConfigObj['634'];
if (kfArr.length && param634 == 1) {
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
router.back();
})
throw new Error('End Loop')
}
avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`])
} else {
avPlayer.playAudio([`voice/${kf.markcatalog}.mp3`, voiceURL], false, () => {
router.back();
})
throw new Error('End Loop')
}
})
} catch (e) {
console.info(judgeTag,JSON.stringify(e))
}
})
} else {
avPlayer.playAudio([voiceURL], true, () => {
setTimeout(() => {
this.isUdpEnd = true
router.back();
}, param302 == 8 ? 3000 : 0)
})
}
}
// 当前项目转换
getDqxmStr = (type) => {
const projectsObj = this.judgeUI.projectsObj
return projectsObj[type]?.abbreviation || '通用评判'
}
// 扣分项目转换
getKfStr = (code) => {
const markRuleListObj = this.judgeUI.markRuleListObj;
const thisMark = markRuleListObj[code]
return {
desc: thisMark.markshow,
score: thisMark.markreal,
markcatalog: thisMark.markcatalog,
markserial: thisMark.markserial,
kfxh: thisMark.kfxh
}
}
// 消息心跳发送
getMessageHeartbeat = async (isEnd?: Boolean) => {
const carInfo = globalThis.carInfo;
const { examSubject,plateNo,ksyh } = carInfo;
const {
judgeUI,
isExam,
serialIndex,
tempData,
xmmcCode,
xmxh,
xmmcSingleCode,
xmdm,
performInfo,
kfArr,
getTranslateProject,
getSbxh
} = this;
const singlePlay = globalThis.singlePlay
const {lsh,startHourTime,totalScore,examTime,judgeConfigObj} = judgeUI;
const {fourInOneScreen:{gpsDigit}} = judgeConfig
const examType = examSubject == 2?2:3
const {sensor,gps} = tempData;
if(tempData.sensor === undefined){
return
}
const {zfxd,yfxd,shtd,ygd,jgd,skd,dh1,dh2,lhq,jsc,ssc,fsc,lb,mkg,aqd,ygq,cs,fdjzs,dw} = sensor
const {jd,wd, hxj, fyj, hbg,sd} = gps
const translateProject = getTranslateProject();
const sbxh = getSbxh(xmdm, xmxh)
const {carzt,dcjl,qjjl,dxjl,bxjl} = performInfo || {};
const asclshArr = stringToASC(
fillZero((singlePlay ? (examSubject == 2 ? '0000000000000':'1111111111111') : lsh) || 0, 13)
);
//13不足要补0
const ascksyhArr = stringToASC(fillZero(ksyh || 0, 13))
const ascsbxhArr = stringToASC(sbxh)
const translateSignals = getTranslateSignals(
[zfxd, yfxd, shtd, ygd, jgd, skd, dh1, dh2, lhq, jsc, ssc, fsc, lb, mkg, aqd].concat(getDwStatusType(dw)).concat(getCarStatusType(carzt)).concat([ygq, sensor.wd, 0])
)
//@ts-ignore
const translateJd = convertGpsCoord2(wd).toFixed(gpsDigit) * Math.pow(10, gpsDigit);
//@ts-ignore
const translateWd = convertGpsCoord2(jd).toFixed(gpsDigit) * Math.pow(10, gpsDigit)
//@ts-ignore
const translateProjects = translateProject.map(numStr => string2Bytes(parseInt(numStr, 2), 8)[0])
//@ts-ignore
let tempSd = ((judgeConfigObj['350'] ==0 ? sd : cs) * 1.852).toFixed(0) * 1
if(tempSd < 1){
tempSd = 0
}
const arr = [
//考生号
asclshArr.map(lsh => string2Bytes(lsh, 8)[0]),
//考试员号
ascksyhArr.map(ksyh => string2Bytes(ksyh, 8)[0]),
//科目类型(0:未考试 1:科目二 2:科目三) + 考试开始时间
string2Bytes(`${examType}${startHourTime}`, 4 * 8),
// TODO 消息序号从1开始0结束
string2Bytes(isEnd ? 0 : serialIndex, 2 * 8),
/*左向灯 右向灯 双跳灯 远光灯 近光灯 视宽灯 点火1 点火2 离合器 脚刹 手刹 副刹 喇叭 门开关 安全带 档位 车辆状态 雨刮器 雾灯 0*/
translateSignals,
//速度 发动机转速 GPS纬度 GPS经度 主天线位置
//@ts-ignore
string2Bytes(tempSd * 100, 2 * 8), string2Bytes(fdjzs / 100, 8), string2Bytes(translateJd, 4 * 8), string2Bytes(translateWd, 4 * 8), string2Bytes(1, 8),
//GPS东向距离
string2Bytes(dxjl < 0 ? (dxjl + 4294967296) : dxjl, 4 * 8),
//GPS北向距离
string2Bytes(bxjl < 0 ? (bxjl + 4294967296) : bxjl, 4 * 8),
//航向角 俯仰角 高程(海拔)
string2Bytes((hxj) * 100, 2 * 8), string2Bytes(fyj * 100, 2 * 8), string2Bytes(hbg * 100, 4 * 8),
//项目状态 parseInt('01010010',2) 二进制转成10进制
translateProjects,
//当前项目编号
string2Bytes(xmmcSingleCode ? (xmmcSingleCode * 1 + 1) : 0, 8),
//场地设备编号
ascsbxhArr.map(sbxh => string2Bytes(sbxh, 8)[0]),
//本次考试行驶距离
string2Bytes(Math.floor((dcjl + qjjl) / 100), 2 * 8),
//扣分
string2Bytes(100 - Math.abs(totalScore), 2 * 8),
//扣分项数量
string2Bytes(kfArr.length, 8),
//n个扣分序号
kfArr.map(kf => string2Bytes(kf.kfxh, 8)[0]),
//TODO 牵引车第二gps精度、纬度
string2Bytes(0, 4 * 8), string2Bytes(0, 4 * 8),
//TODO 牵引车第二航向角
string2Bytes(0, 2 * 8),
//TODO 摩托压线 Byte[20],
string2Bytes(0, 20 * 8),
//考试用时
string2Bytes(examTime, 4 * 8),
//TODO 项目用时
string2Bytes(fillZero(0,2), 2 * 8),
//TODO 设备信号状态
string2Bytes(0, 4 * 8),
]
let tempArr = [];
arr.forEach(itemArr => {
tempArr = tempArr.concat(itemArr)
})
this.serialIndex += 1;
return Array2Byte(tempArr)
}
//获取场地序号
getSbxh = (ksxm, xmxh) => {
const {judgeUI} = this;
const {cdsbInfoObj,projectsObj} = judgeUI;
const project = projectsObj[ksxm]
if(project == 3){
return '0000000000'
}
if (project === undefined) {
return '0000000000'
}
const projectType = project.sbxh;
const projectKey = `${ksxm}_${xmxh}`;
const currentCdsb = cdsbInfoObj[projectKey] || {};
const sbxh = currentCdsb.sbbh || '0000000000'
return sbxh
}
getSbbm = (ksxm, xmxh) => {
const {judgeUI} = this;
const {cdsbInfoObj,projectsObj,examSubject} = judgeUI;
const project = projectsObj[ksxm]
//科目三不需要
if(examSubject == 3){
return undefined
}
if (project === undefined) {
return '00000000'
}
const projectKey = `${ksxm}_${xmxh}`;
const currentCdsb = cdsbInfoObj[projectKey] || {};
const sbxh = currentCdsb.sbbm || '00000000'
return sbxh
}
// 中心所有项目转换
getTranslateProject = () => {
const {examSubject} = this.judgeUI;
const tempItems = (examSubject == 2 ? testKm2Items:testKm3Items).map(item => {
const current = this.testKmItems[item.code];
return {
code: item.code,
status: getCenterProjectStatus(current.status)
}
})
const arr = [];
for (let i = 0; i <= 4; i++) {
const temp = tempItems.slice(i * 4, (i + 1) * 4);
let tempArr = temp.map(item => item.status)
if (i === 4) {
tempArr = examSubject == 2
//bit36-bit39保留
? tempArr.concat(['00', '00'])
//bit30-bit39保留
: tempArr.concat(['00', '00','00'])
}
// if (i === 3 && examSubject == 3) {
// tempArr = tempArr.concat(['00'])
// }
arr.push(tempArr.join(''));
}
return arr
}
// 获取考试项目详情
getProjectInfo = (projectCode) => {
const judgeUI = this.judgeUI;
return judgeUI.projectsObj[projectCode]
}
// 获取模型数据
getModelData = (modelName) => {
const modelPath = this.modelPath
const fileModel = this.fileModel;
const modelData = fileModel.getModelContent(modelPath, modelName);
return modelData
}
// 过程照片拍照
getPhoto = async (empty?: boolean) => {
const singlePlay = globalThis.singlePlay
//单机模式返回空照片
if (singlePlay) {
return ''
} else {
const {filePhoto} = this;
const photoBase64 = await filePhoto.getPhoto();
console.info(judgeTag, '拍照完成')
return photoBase64
}
}
//人工操作项目
public setJudgeItem = async (itemno, type: 1 | 2) => {
console.info('surenjun','2')
const {fileLog} = this;
await examJudgeArtificialItem(itemno * 1, type);
await fileLog.setExamJudgeData({
method: 'examJudgeArtificialItem',
itemno: itemno * 1,
type
})
console.info(judgeTag, `人工评判${type == 1 ? '进入' : '取消'}项目-${itemno}`)
}
//人工扣分
public setJudgeMark = async (itemno, serial, type = 1) => {
const {fileLog} = this
await examJudgeArtificialMark(itemno * 1, serial, type);
console.info(judgeTag, `进入人工扣分-${itemno}-${serial}`)
await fileLog.setExamJudgeData({
method: 'examJudgeArtificialMark',
itemno: itemno * 1,
serial,
type
})
console.info(judgeTag, `人工扣分-${itemno}-${serial}`)
}
// 断网数据补传
uploadDisConnectData = async () => {
const {isJudgeDisConnect,fileLog,fileUtil} = this;
if (!isJudgeDisConnect) {
return
}
const folderPath = fileLog.folderPath
const examDataStr = await fileUtil.readFile(`${folderPath}/wuxi_dis_progress_data.txt`);
const examDataArr = examDataStr.split('\n');
for (let examDataStr of examDataArr) {
const examData = JSON.parse(examDataStr)
const code = await writeObjectOut(examData);
}
}
//上传无锡所过程数据
uploadProgressData = async () => {
const {judgeUI,fileUtil,fileLog} = this;
const {idCard,startFullTime} = judgeUI
const carInfo = globalThis.carInfo;
const {carId,examinationRoomId} = carInfo
const folderPath = fileLog.folderPath
const base64 = new util.Base64();
const time = await getCurrentTime();
const endTime = await getCurrentTime(1)
let examDataBase64
//@ts-ignore
//TODO try catch报错待优化
const examDataStr: string = await fileUtil.readFile(`${folderPath}/wuxi_progress_data.txt`);
try {
let tempBuff = buffer.alloc(examDataStr.length, examDataStr)
let examData: Uint8Array = new Uint8Array(tempBuff.buffer)
examDataBase64 = base64.encodeToStringSync(examData)
} catch (e) {
console.info(judgeTag, JSON.stringify(e))
}
console.info(judgeTag, '过程数据文件上传 start')
await uploadExamProgressData({
time,
carId,
examinationRoomId,
examData: examDataBase64,
type: 1,
cardNo: idCard,
examStartTime: startFullTime,
examEndTime: endTime,
})
console.info(judgeTag, '过程数据文件上传 end')
}
//获取科目三的评判初始化配置
getKm3JudgeInitConfig = async () => {
const {judgeUI,getModelData} = this;
const {carinfoArrr,mapPointArr,mapPointItemArr} = judgeUI;
return {
carinfo: carinfoArrr,
map_point: mapPointArr,
map_point_item: mapPointItemArr,
//科目三暂时为空
iteminfo: [],
roads: getModelData('km3/Roads.txt'),
sharps: getModelData('km3/Sharps.txt')
}
}
// 处理udp plc信号
handleUdp = async (msg) => {
console.info('plc信号', msg)
const {fileLog,getPlcData,usbService,isUdpEnd,isExamEnd,judgeUI} = this
const stachArr = msg.split(',')
if (stachArr[0] != '#DN_GD' || isUdpEnd) {
return
}
const plcData = await getPlcData(msg);
// 4.过程数据
await fileLog.setExamJudgeData(plcData)
//检测到有无锡所设备接入,需要发送特定的数据,供检测
if (usbService.isWXUSBDevice) {
const str = await senorToWXDataStr(msg);
usbService.sendUSB(str)
}
this.judgeUI.isDwztRight = (plcData.gps.dwzt == 4 && plcData.gps.jdzt == 3);
const param350 = judgeUI.judgeConfigObj['350']
//@ts-ignore
this.judgeUI.sd = ((param350 == 0? plcData.gps.sd :plcData.sensor.cs) as number * 1.852).toFixed(0) + ''
this.judgeUI.dw = (Math.floor(plcData.sensor.dw as number) || 0) + ''
//TODO 暂时关闭差分检测异常
await this.checkDwzt(plcData.gps.dwzt,plcData.gps.jdzt);
if(!isExamEnd){
await examJudgeRealExam(plcData)
}
const udpIndex = globalThis.udpIndex;
let [prevJd,preWd] = [0,0]
if (udpIndex % 5 === 0 && !isUdpEnd) {
const judgeUdp = globalThis.judgeUdp
const bytes = await this.getMessageHeartbeat(isExamEnd);
console.info(judgeTag,JSON.stringify(bytes))
console.info(judgeTag,'udp-prev-send')
judgeUdp.send(bytes)
console.info(judgeTag,'udp-prev-end')
}
globalThis.udpIndex += 1
}
// 处理特殊参数配置
handleSEP = async (code: number) => {
const {judgeUI:{
judgeConfigObj
},avPlayer} = this;
const {examSubject} = globalThis.carInfo;
switch (code) {
//结束考试方式
case 306:
if (judgeConfigObj[code] == 5) {
//靠边停车
avPlayer.playAudio(['voice/406001.mp3'])
}
break;
}
}
// 获取plc数据
getPlcData = async (plc: string) => {
const {fileLog,mndgStr,rmndg} = this;
await fileLog.setPlcProgressData(plc)
//plc字符串转化成评判初始化数据
const tempData = await plcStrToJson(plc);
//模拟灯光回放时刻
tempData.sensor.rmndg = rmndg;
//模拟灯灯光灯光项目
tempData.sensor.mndg = mndgStr;
//plc字符串转化成无锡所过程数据
const wuXiDataStr = await plcStrToWXJson(plc)
this.plcData = tempData
await fileLog.setExamJudgeWuxiProgressData(wuXiDataStr)
this.tempData = tempData
this.plcStr = plc;
this.mndgStr = '';
this.rmndg = 0;
globalThis.msgStr = plc
return tempData
}
// 处理轨迹plc信号
handleTrajectoryUdp = async (strArr) => {
const {fileLog,setJudgeItem,setJudgeMark,endExam} = this;
let num = 2;
const judgeTimer = setInterval(async () => {
const msgStr = strArr[num];
if(msgStr == ''){
console.info(judgeTag, '模拟数据考试结束')
globalThis.windowClass.setWindowSystemBarEnable(['navigation'])
clearInterval(judgeTimer)
this.checkExamIsEnd(true)
return
}
const msg = JSON.parse(strArr[num]);
num++
// 4.过程数据
this.tempData = msg
this.judgeUI.isDwztRight = (msg?.gps?.dwzt == 4 && msg?.gps?.jdzt == 3);
this.judgeUI.sd = Math.floor(msg?.gps?.sd * 1.852) + '';
this.judgeUI.dw = Math.floor(msg?.sensor?.dw) + ''
this.plcData = msg
// this.judgeUI.isDwztRight = msg.gps.dwzt == 4;
globalThis.msgStr = ''
if (msg.method === 'examJudgeArtificialItem') {
setJudgeItem(msg.itemno, msg.type)
}
if (msg.method === 'examJudgeArtificialMark') {
setJudgeItem(msg.itemno, msg.serial)
}
await examJudgeRealExam(msg)
const bytes = await this.getMessageHeartbeat();
bytes && globalThis.judgeUdp.send(bytes)
}, 50)
globalThis.judgeTimer = judgeTimer;
}
// 统计必考项目、所有项目、已考数量
setCountItems = async () => {
const carInfo = globalThis.carInfo;
const { examSubject} = carInfo;
const {projectsObj} = this.judgeUI;
//必考项目数量 必考项目已考数量
let projectNum = 0, endProjectsNum = 0;
// 所有考试项目数量 项目已考项目数量
let allProjectNum = 0, allEndProjectsNum = 0;
Reflect.ownKeys(projectsObj).forEach(projectKey => {
const {type,isRequired} = projectsObj[projectKey];
allProjectNum += 1;
if (type == 3 || type == 4) {
allEndProjectsNum += 1;
}
if (isRequired) {
projectNum += 1;
if (type == 3 || type == 4) {
endProjectsNum += 1;
}
}
})
console.info(judgeTag,'必考项目数量:' + projectNum)
console.info(judgeTag,'必考项目已考数量:' + endProjectsNum)
//必考项目除靠边停车是否全部完成
this.judgeUI.isRequiredProjectsEnd = (projectNum - endProjectsNum === 0)
this.judgeUI.isAllProjectsEnd = (allProjectNum - allEndProjectsNum === 0)
}
// 模拟灯光
setMndg = async (mndgStr: string) => {
this.mndgStr = mndgStr
}
// 检测差分状态
checkDwzt = async (dwzt,jdzt) => {
const {avPlayer} = this;
const judgeConfig = this.judgeUI.judgeConfig;
// const param499 = judgeConfig['499']
//10秒内dwzt不为4
const dwztNum = this.dwztNum
if(dwztNum != 0 && (dwztNum % (5 * 10) == 0)){
this.judgeUI.dwztErrorVisible = true;
avPlayer.playAudio([`voice/差分状态异常.mp3`],true)
}
if(dwzt != 4 || jdzt != 3){
this.dwztNum += 1
}else{
this.dwztNum = 0;
this.judgeUI.dwztErrorVisible = false;
}
}
public plcStr: string
private judgeUI
private fileLog
private filePath
private totalScore: number
private prevJd: number = 0
private prevWd: number = 0
private dwztNum:number = 0
private folderPath: string
private modelPath: string
private avPlayer
private carztStr: string
private rmndg: 0 | 1
private mndgStr: string | undefined
private xmmcStr: string
private xmmcCode: string
private xmmcSingleCode: number
private xmdm: string | number
private xmxh: string
private fileModel: FileModel
private filePhoto: FilePhoto
private usbService: UsbService
//是否是考试模式
private isExam: boolean
//考试是否结束了
private isExamEnd: boolean
// 是否发送udp
private isUdpEnd: boolean = false
//是否手动结束考试
private isManual: boolean
//UDP服务序列号
private serialIndex: number
private fileUtil: FileUtil
private judgeTask: JudgeTask
private tempData: any
private performInfo: any
private isEndTip:boolean = false;
private ksjs: {
// 累计前进距离
qjjl: number,
// 累计倒车距离
dcjl: number
d1: number
d2: number
d3: number
d4: number
d5: number
d6: number
}
private kfArr: {
//项目名称
xmmcStr: string,
xmdm: string | number,
//扣分描述
desc: string,
//扣分
score: string
//无锡所扣分代码
markcatalog: string
markserial: string
kfxh: string
type: 0| 1 | 2
}[]
private km2ItemsStatus: any[]
//所有的科目考试项目(大车&小车)
private testKmItems: any
private plcData: any
//当前科目二的考试项目
private currentKm2ItemsObj: any
//本地轨迹回放地址
private trajectoryPath: string
private isTrajectoryOpen: boolean;
// 调代理接口是否断网了
private isJudgeDisConnect: boolean;
private artSubject3ProjectsCodesArr: number[] = [3, 9, 4, 10, 12, 11]
private lane: LANE = {
road: '', num: 0, count: 0
}
private videoData:any
}