1963 lines
66 KiB
Plaintext
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 } 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<Km3JudgeInitConfig>
type GetgSbbm = (ksxm: number, xmxh: string) => string
type SendWriteObjectOut = (data: RegulatoryInterfaceParams, filePath: string) => Promise<WR>
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<boolean>('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<CarInfoType>('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')
// 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<number>('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<CarInfoType>('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<CarInfoType>('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<CarInfoType>('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<CarInfoType>('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<BaseInfoType>('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<ExaminerInfoType>('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<boolean>('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<CarInfoType>('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<boolean>('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<CarInfoType>('carInfo');
const singlePlay = AppStorage.get<boolean>('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');
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<CarInfoType>('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<boolean>('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<boolean>('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();
}
}