import 'package:fixnum/fixnum.dart'; import 'package:get/get.dart'; import 'package:trackoffical_app/model.dart'; import 'package:trackoffical_app/pb.dart' as pb; import 'package:flutter/material.dart'; import 'package:trackoffical_app/utils.dart'; enum MControlPointType { nfc, gps } class MControlPoint { MControlPoint( {this.sn = '', this.areaId = '', this.intId = Int64.ZERO, this.isSuccess = false}); /// 点位顺序号 String sn = ''; /// 点位场地编号,如:A51 String areaId = ''; /// 点位ID Int64 intId = Int64.ZERO; bool isSuccess; /// 作为规划点打点成功 bool isPlan=false; bool isNext = false; var type = MControlPointType.nfc; bool isUnchecked = true; Duration checkAfterStart = 0.seconds; Duration checkAfterPrev = 0.seconds; Distance checkDistanceAfterStart = 0.meter; Distance checkDistanceAfterPrev = 0.meter; Distance distanceStraightToPrev = 0.meter; Offset onMap = Offset.zero; MPosition position = MPosition(); /// 答题ID int? qbId; bool isAnswerCorrect = false; // 答题是否正确 int? userAnswerIndex; //用户答案序号 Duration paceAfterPrev = Duration.zero; Duration paceAfterStart = Duration.zero; CPExtraInfo? extraInfo; bool get isStart => sn == snStart; bool get isFinish => sn == snFinish; String get snString { if (sn.isEmpty) { return ''; } if (isStart) { return "开始"; } if (isFinish) { return "结束"; } return "$sn号"; } set isStart(bool v) { if (v) { sn = snStart; } } set isFinish(bool v) { if (v) { sn = snFinish; } } static const snStart = 'start'; static const snFinish = 'finish'; Widget getSnDisplay(double height, {TextStyle? textStyle}) { if (isStart || isFinish) { var src = 'ic_bottom_bar_next_start.png'; if (isFinish) { src = 'ic_bottom_bar_next_finish.png'; } return Image.asset('assets/images/$src', height: height, fit: BoxFit.fitHeight); } return Text(sn, style: textStyle); } pb.GameSaveControlPoint toPbSave() { final out = pb.GameSaveControlPoint() ..controlPointId= intId ..isCheckSuccess= isSuccess ..checkAfterStart= checkAfterStart.toPb() ..distinctAfterStart= checkDistanceAfterStart.m ..answerCorrect= isAnswerCorrect ..isAnswer= userAnswerIndex!= null ; if(userAnswerIndex!= null){ out.userAnswerIndex=userAnswerIndex!; } if(qbId!= null){ out.userAnswerIndex=qbId!; } return out; } void updateBySimple(pb.ControlPointSimple other) { areaId = other.sn; } void updateBy(MControlPoint other) { sn = sn.isEmpty ? other.sn : sn; areaId = areaId.isEmpty ? other.areaId : areaId; extraInfo ??= other.extraInfo; } MControlPoint clone() { return MControlPoint() ..sn = sn ..areaId = '' ..intId = intId ..isSuccess = isSuccess ..isNext = isNext ..type = type ..isUnchecked = isUnchecked ..checkAfterStart = checkAfterStart ..checkAfterPrev = checkAfterPrev ..checkDistanceAfterStart = checkDistanceAfterStart ..checkDistanceAfterPrev = checkDistanceAfterPrev ..distanceStraightToPrev = distanceStraightToPrev ..onMap = onMap ..position = position ..qbId = qbId ..isAnswerCorrect = isAnswerCorrect ..userAnswerIndex = userAnswerIndex ..paceAfterPrev = paceAfterPrev ..paceAfterStart = paceAfterStart ..extraInfo = extraInfo; } } extension PbGameSaveControlPointExt on pb.GameSaveControlPoint { MControlPoint toModel() { final one = MControlPoint(); one.intId = controlPointId; one.isSuccess = isCheckSuccess; one.checkAfterStart = checkAfterStart.toDuration(); one.checkDistanceAfterStart = distinctAfterStart.meter; one.isAnswerCorrect = answerCorrect; if (hasUserAnswerIndex()) { one.userAnswerIndex = userAnswerIndex; } if (hasQbId()) { one.qbId = qbId; } return one; } } extension PbControlPointExt on pb.ControlPoint { MControlPoint toModel() { final one = MControlPoint(); one.areaId = sn; one.intId = id; one.position = ciPosition.toModel(); if (category == 1) { one.type = MControlPointType.nfc; } if (category == 2) { one.type = MControlPointType.gps; } if (hasInfo()) { if (info.hasDisplayInfo()) { final extraInfo = info.toModel(); one.extraInfo = extraInfo; if(extraInfo is CPExtraInfoChoiceQuestion){ one.qbId = extraInfo.qid; } } } return one; } } extension PbControlPointSimpleExt on pb.ControlPointSimple { MControlPoint toModel() { final one = MControlPoint(); one.areaId = sn; one.intId = id; return one; } } /// 完赛后检查点 extension PbGameControlPointExt on pb.GameControlPoint { MControlPoint toModel() { final one = MControlPoint(); one.areaId = sn; one.intId = id; if (cType == pb.CType.BeginType) { one.isStart = true; } if (cType == pb.CType.MiddleType) { if (orderNo != 0) { one.sn = orderNo.toString(); } } if (cType == pb.CType.EndType) { one.isFinish = true; } one.isSuccess = isCheckSuccess; one.checkAfterPrev = checkAfterLast.toDuration(); one.checkAfterStart = checkAfterStart.toDuration(); one.checkDistanceAfterPrev = disAfterLast.meter; one.distanceStraightToPrev = disStraightAfterLast.meter; one.paceAfterPrev = paceAfterLast.seconds; one.paceAfterStart = paceAfterStart.seconds; return one; } } extension ControlPointInfoExt on pb.ControlPointInfo { CPExtraInfo toModel() { if (displayInfo.canUnpackInto(pb.ControlPointDisplayInfoSingleChoice())) { final data = displayInfo.unpackInto(pb.ControlPointDisplayInfoSingleChoice()); return data.toModel(); } throw UnimplementedError('${displayInfo.typeUrl}未实现'); } }