import 'package:common_pub/model/control_point.dart'; import 'package:common_pub/model/distance.dart'; import 'package:common_pub/model/pace.dart'; import 'package:common_pub/model/position.dart'; import 'package:common_pub/service/controller.dart'; import 'package:common_pub/ui/map_view/map_view.dart'; import 'package:common_pub/ui/map_view/view_map_trace.dart'; import '../logger.dart'; import '../service/api.dart' as pb; import 'package:fixnum/fixnum.dart'; typedef MapId = Int64; class Flag { Flag(this.value); int value; Color get color => Color(value); @override bool operator ==(Object other) { if (other is Flag) { return value == other.value; } return false; } @override int get hashCode => value.hashCode; static final red = Flag(0xffff0000); static final yellow = Flag(0xffffcb00); static final blue = Flag(0xff00a0ff); static List get values => [red, yellow, blue]; } class ActiveInfo { var id = 0; var name = ''; var cpAllCount = 0; var userList = []; final isHide = false.obs; UserInfo? getUserById(int id) { for (final one in userList) { if (one.gameInfo.userId == id) { return one; } } return null; } Future newUserInfo(pb.ToOrienteerInGameInfo info) async { final r = await pb.ApiService.to.stub.toUserInActionBasicQuery( pb.ToUserInActionBasicQueryRequest(actId: id, userId: info.userId)); final user = UserInfo() ..routeInfo = r.courseBaseInfo ..userInfo = r.baseInfo; await user.setGameInfo(info); return user; } Future update(pb.ToActionInfo info) async { final newUserList = []; for (final nUser in info.userList) { late UserInfo user; final oUser = getUserById(nUser.userId); if (oUser != null) { user = oUser; await user.update(nUser); } else { user = await newUserInfo(nUser); } newUserList.add(user); } userList = newUserList; } } extension ActiveInfoExt on pb.ToActionInfo { Future into() async { final info = await pb.ApiService.to.stub .toActionBasicQuery(pb.IdRequest(id: Int64(actId))); final out = ActiveInfo() ..id = actId ..name = info.actName ..cpAllCount = info.totalControlNum; for (final one in userList) { out.userList.add(await out.newUserInfo(one)); } return out; } } class UserInfo { final isHide = false.obs; String get name => userInfo.name; String get routeName => routeInfo.courseName; Pace get pace => Pace.perKm(gameInfo.gpsInfo.pace.seconds); Duration get duration => DateTime.now().difference(gameInfo.gameSaveInfo.startAt.toModel()); Distance get distance => Distance(m: gameInfo.gpsInfo.distance.toDouble()); int get id => gameInfo.userId; var gameInfo = pb.ToOrienteerInGameInfo(); var routeInfo = pb.CourseBaseInfo(); var userInfo = pb.OrienteerBaseInfo(); var trace = [].obs; var flag = Flag.red.obs; DateTime? get startAt => gameInfo.gameSaveInfo.hasStartAt() ? gameInfo.gameSaveInfo.startAt.toModel() : null; var cpList = []; ControlPoint? nextWant; Distance get nextDistance { final one = nextWant; if (one != null) { final p1 = one.position; final p22 = gameInfo.gpsInfo.gameGpsInfos.lastOrNull; if (p22 != null) { final p2 = Position(longitude: p22.longitude, latitude: p22.latitude); return p1.distance(p2); } } return const Distance(m: 1000); } String get nextCPSN { return nextWant?.snString ?? ''; } Future update(pb.ToOrienteerInGameInfo info) async { final map = MapWatchService.instance; await setGameInfo(info); final indexMap = {}; for (final one in trace) { indexMap[one.ts.inMilliseconds] = one; } for (final one in info.gpsInfo.gameGpsInfos) { final t = one.gpsTime.toModel(); final startAt = gameInfo.gameSaveInfo.startAt.toModel(); final ts = t.difference(startAt); if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) { final pos = one.toModel(); final oneTrace = TracePoint() ..ts = ts ..position = pos; if (map!.plugMap.isInitFinish){ oneTrace.onMap = await map.plugMap.gameMap.worldToPixel(oneTrace.position); } trace.add(oneTrace); } } // if (map!.plugMap.isInitFinish) { // for (final one in trace) { // if (one.onMap == Offset.zero) { // one.onMap = await map.plugMap.gameMap.worldToPixel(one.position); // } // } // } } Future setGameInfo(pb.ToOrienteerInGameInfo info) async { final map = MapWatchService.instance; gameInfo = info; cpList.clear(); final cpMap = {}; for (var (i, src) in routeInfo.controlPointSortedList.indexed) { final one = src.toModel()..sn = i.toString(); if (map != null) { one.onMap = await map.plugMap.gameMap.worldToPixel(one.position); } cpList.add(one); cpMap[one.intId.toInt()] = one; } if (cpList.isNotEmpty) { cpList.first.isStart = true; cpList.last.isFinish = true; } var index = 0; for (var cp in gameInfo.gameSaveInfo.checkedSortedList) { if(cp.isCheckSuccess){ for(var i = index; i < cpList.length; i++){ final want = cpList[i]; if(want.intId == cp.controlPointId){ want.isSuccess=true; index++; break; } } } // cpMap[cp.controlPointId.toInt()]!.isSuccess = cp.isCheckSuccess; } for (var cp in cpList) { if (!cp.isSuccess) { cp.isNext = true; nextWant = cp; break; } } } } class MapWatchService extends PlugController { static final Rx _instance = Rx(null); static MapWatchService? get instance => _instance.value; static Future setMapById(MapId id) async { final info = await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()..id = id); final thisInstance = MapWatchService(id: id) ..name = info.mapName ..plugMap.gameMap = info.zipImage.toGameMap(); thisInstance.addPlugs([thisInstance.plugMap]); _instance.value = thisInstance; thisInstance.init(); thisInstance.workFlushData(); } Future workFlushData() async { while (isActive) { try { await flushData(); } catch (e) { error(e); } await 1.seconds.delay(); } } ActiveInfo? getActiveById(int id) { for (final one in activeList) { if (one.id == id) { return one; } } return null; } Future flushData() async { final r = await pb.ApiService.to.stub .toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(mapId: id.toInt())); final newList = []; for (final one in r.list) { late ActiveInfo info; final old = getActiveById(one.actId); if (old != null) { info = old; await info.update(one); } else { info = await one.into(); } newList.add(info); } activeList.value = newList; } MapWatchService({required this.id}); final MapId id; String name = ''; final plugMap = PlugMap(); final activeList = [].obs; }