import 'package:common_pub/logger.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 'package:track_common/model.dart'; 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 PlayerInfo { var id = 0; var name = ''; var routeName = ''; var cpWantList = []; } class PlayerOnMap extends AppGameState { var info = PlayerInfo(); int get id => info.id; String get name => info.name; List get cpList => cpListChecked; final isHide = false.obs; var trace = [].obs; var flag = Flag.red.obs; String get routeName => info.routeName; int heartRatePercent = 0; Pace pace = Pace.perKm(99.hours); var distance = 0.km; List get hrInfo => hrHistory; List get positionList => positionHistory; @override Duration get duration => DateTime.now().difference(startAt); Distance get nextDistance { final one = cpNextWant; if (one != null) { final p1 = one.position; final p22 = positionList.lastOrNull; if (p22 != null) { return p1.distance(p22); } } return const Distance(m: 1000); } String get nextCPSN { return cpNextWant?.snString ?? ''; } } class EventOnMap { var info = EventInfo(); var userList = []; int get id => info.id; String get name => info.name; int get cpAllCount => info.cpAllCount; final isHide = false.obs; PlayerOnMap? getUserById(int id) { for (final one in userList) { if (one.id == id) { return one; } } return null; } } abstract class MapWatchService extends GetxService { final Rx _instance = Rx(null); MapWatch? get instance => _instance.value; @protected Future newInstanceByMap(MapInfo info); Future setMap(MapInfo mapInfo) async { final thisInstance = await newInstanceByMap(mapInfo); thisInstance.addPlugs([thisInstance.plugMap]); _instance.value = thisInstance; thisInstance.init(); thisInstance.workFlushData(); } } abstract class MapWatch extends PlugController { Future workFlushData() async { while (isActive) { try { await flushData(); } catch (e) { error(e); } await 1.seconds.delay(); } } EventOnMap? getEventById(int id) { for (final one in eventList) { if (one.id == id) { return one; } } return null; } MapWatch({required this.id}); final int id; String name = ''; final plugMap = PlugMap(); final eventList = [].obs; Future flushData() async { final list = await getEventList(id); final newList = []; for (final one in list) { late EventOnMap event; final old = getEventById(one.id); if (old != null) { event = old; await updateEvent(event, one); } else { event = await initEvent(one); } newList.add(event); } eventList.value = newList; } Future initEvent(EventOnMap event) async { final id = event.id; final info = await getEventInfo(id); event.info = info; event.info.id = id; for (var p in event.userList) { await initPlayer(event, p); } return event; } Future initPlayer(EventOnMap event, PlayerOnMap player) async { final userId = player.id; final info = await getPlayerInfo(event.id, userId); player.info = info; player.info.id = userId; player.cpListWant = info.cpWantList; return player; } Future updateEvent(EventOnMap old, EventOnMap newOne) async { final newUserList = []; for (final nUser in newOne.userList) { late PlayerOnMap user; final oUser = old.getUserById(nUser.id); if (oUser != null) { user = oUser; await updatePlayer(user, nUser); } else { user = await initPlayer(old, nUser); } user.updateState(); await playerUpdateMap(user); newUserList.add(user); } old.userList = newUserList; } Future playerUpdateMap(PlayerOnMap info) async { for (var one in info.cpList) { one.onMap = await plugMap.gameMap.worldToPixel(one.position); } } Future updatePlayer(PlayerOnMap old, PlayerOnMap newUser) async { final indexMap = {}; for (final one in old.trace) { indexMap[one.ts.inMilliseconds] = one; } for (final one in newUser.positionList) { final t = one.timestamp; final startAt = old.startAt; final ts = t.difference(startAt); if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) { final pos = one; final oneTrace = TracePoint() ..ts = ts ..position = pos; if (plugMap.isInitFinish) { oneTrace.onMap = await plugMap.gameMap.worldToPixel(oneTrace.position); } old.trace.add(oneTrace); } } } @protected Future> getEventList(int mapId); @protected Future getEventInfo(int id); @protected Future getPlayerInfo(int eventId, int userId); }