map_watch.dart 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import 'package:common_pub/logger.dart';
  2. import 'package:common_pub/service/controller.dart';
  3. import 'package:common_pub/ui/map_view/map_view.dart';
  4. import 'package:common_pub/ui/map_view/view_map_trace.dart';
  5. import 'package:track_common/model.dart';
  6. class Flag {
  7. Flag(this.value);
  8. int value;
  9. Color get color => Color(value);
  10. @override
  11. bool operator ==(Object other) {
  12. if (other is Flag) {
  13. return value == other.value;
  14. }
  15. return false;
  16. }
  17. @override
  18. int get hashCode => value.hashCode;
  19. static final red = Flag(0xffff0000);
  20. static final yellow = Flag(0xffffcb00);
  21. static final blue = Flag(0xff00a0ff);
  22. static List<Flag> get values => [red, yellow, blue];
  23. }
  24. class PlayerInfo extends AppGameState {
  25. var id = 0;
  26. int heartRatePercent = 0;
  27. }
  28. class PlayerInfoExt {
  29. var name = '';
  30. var routeName = '';
  31. var cpListWant = <ControlPoint>[];
  32. }
  33. class EventInfo {
  34. var id = 0;
  35. var players = <PlayerInfo>[];
  36. }
  37. class EventInfoExt {
  38. var name = '';
  39. var cpAllCount = 0;
  40. }
  41. class PlayerOnMap {
  42. var info = PlayerInfo();
  43. var _ext = PlayerInfoExt();
  44. set ext(PlayerInfoExt v) {
  45. _ext = v;
  46. info.cpListWant = v.cpListWant;
  47. }
  48. int get id => info.id;
  49. String get name => _ext.name;
  50. List<ControlPoint> get cpList => info.cpListWant;
  51. final isHide = false.obs;
  52. var trace = <TracePoint>[].obs;
  53. var flag = Flag.red.obs;
  54. String get routeName => _ext.routeName;
  55. Distance get distance => info.distance;
  56. List<HeartRate> get hrInfo => info.hrHistory;
  57. List<Position> get positionList => info.positionHistory;
  58. DateTime watchAt = DateTime.now();
  59. int get heartRatePercent => info.heartRatePercent;
  60. Pace get pace => info.pace;
  61. Duration get duration => info.duration;
  62. ControlPoint? get cpNextWant => info.cpNextWant;
  63. Distance get nextDistance {
  64. final one = info.cpNextWant;
  65. if (one != null) {
  66. final p1 = one.position;
  67. final p22 = positionList.lastOrNull;
  68. if (p22 != null) {
  69. return p1.distance(p22);
  70. }
  71. }
  72. return const Distance(m: 1000);
  73. }
  74. String get nextCPSN {
  75. return info.cpNextWant?.snString ?? '';
  76. }
  77. }
  78. class EventOnMap {
  79. var info = EventInfo();
  80. var ext = EventInfoExt();
  81. var userList = <PlayerOnMap>[];
  82. int get id => info.id;
  83. String get name => ext.name;
  84. int get cpAllCount => ext.cpAllCount;
  85. final isHide = false.obs;
  86. PlayerOnMap? getUserById(int id) {
  87. for (final one in userList) {
  88. if (one.id == id) {
  89. return one;
  90. }
  91. }
  92. return null;
  93. }
  94. }
  95. abstract class MapWatchService extends GetxService {
  96. final Rx<MapWatch?> _instance = Rx(null);
  97. MapWatch? get instance => _instance.value;
  98. @protected
  99. Future<MapWatch> newInstanceByMap(MapInfo info);
  100. Future<void> setMap(MapInfo? mapInfo) async {
  101. _instance.value?.close();
  102. if (mapInfo != null) {
  103. final thisInstance = await newInstanceByMap(mapInfo);
  104. thisInstance.addPlugs([thisInstance.plugMap]);
  105. _instance.value = thisInstance;
  106. thisInstance.init();
  107. thisInstance.workFlushData();
  108. } else {
  109. _instance.value = null;
  110. }
  111. }
  112. }
  113. abstract class MapWatch extends PlugController {
  114. Future<void> workFlushData() async {
  115. while (isActive) {
  116. try {
  117. await flushData();
  118. } catch (e) {
  119. error(e);
  120. }
  121. await 1.seconds.delay();
  122. }
  123. }
  124. EventOnMap? getEventById(int id) {
  125. for (final one in eventList) {
  126. if (one.id == id) {
  127. return one;
  128. }
  129. }
  130. return null;
  131. }
  132. MapWatch({required this.id});
  133. final int id;
  134. String name = '';
  135. final plugMap = PlugMap();
  136. final eventList = <EventOnMap>[].obs;
  137. Future<void> flushData() async {
  138. final list = await getEventList(id);
  139. final newList = <EventOnMap>[];
  140. for (final one in list) {
  141. late EventOnMap event;
  142. final old = getEventById(one.id);
  143. if (old != null) {
  144. event = old;
  145. await updateEvent(event, one);
  146. } else {
  147. event = await initEvent(one);
  148. }
  149. newList.add(event);
  150. }
  151. eventList.value = newList;
  152. }
  153. Future<EventOnMap> initEvent(EventInfo info) async {
  154. final ext = await getEventInfoExt(info.id);
  155. final one = EventOnMap()
  156. ..info = info
  157. ..ext = ext;
  158. for (var p in info.players) {
  159. one.userList.add(await initPlayer(info, p));
  160. }
  161. return one;
  162. }
  163. Future<PlayerOnMap> initPlayer(EventInfo event, PlayerInfo playerInfo) async {
  164. final userId = playerInfo.id;
  165. final ext = await getPlayerInfoExt(event.id, userId);
  166. final player = PlayerOnMap()..info = playerInfo;
  167. player.ext = ext;
  168. return player;
  169. }
  170. Future<void> updateEvent(EventOnMap old, EventInfo newOne) async {
  171. final newUserList = <PlayerOnMap>[];
  172. for (final nUser in newOne.players) {
  173. late PlayerOnMap user;
  174. final oUser = old.getUserById(nUser.id);
  175. if (oUser != null) {
  176. user = await updatePlayer(oUser, nUser);
  177. } else {
  178. user = await initPlayer(old.info, nUser);
  179. }
  180. await playerUpdateMap(user);
  181. newUserList.add(user);
  182. }
  183. old.userList = newUserList;
  184. }
  185. Future<void> playerUpdateMap(PlayerOnMap info) async {
  186. for (var one in info.cpList) {
  187. one.onMap = await plugMap.gameMap.worldToPixel(one.position);
  188. }
  189. }
  190. Future<PlayerOnMap> updatePlayer(PlayerOnMap old, PlayerInfo newUser) async {
  191. final indexMap = <int, TracePoint>{};
  192. old.info = newUser;
  193. old.ext = old._ext;
  194. for (final one in old.trace) {
  195. indexMap[one.ts.inMilliseconds] = one;
  196. }
  197. for (final one in newUser.positionHistory) {
  198. final t = one.timestamp;
  199. final startAt = old.watchAt;
  200. final ts = t.difference(startAt);
  201. if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) {
  202. final pos = one;
  203. final oneTrace = TracePoint()
  204. ..ts = ts
  205. ..position = pos;
  206. if (plugMap.isInitFinish) {
  207. oneTrace.onMap =
  208. await plugMap.gameMap.worldToPixel(oneTrace.position);
  209. }
  210. old.trace.add(oneTrace);
  211. } else if (old.trace.isEmpty) {
  212. final oneTrace = TracePoint()
  213. ..ts = Duration.zero
  214. ..position = one;
  215. if (plugMap.isInitFinish) {
  216. oneTrace.onMap =
  217. await plugMap.gameMap.worldToPixel(oneTrace.position);
  218. old.trace.add(oneTrace);
  219. }
  220. }
  221. }
  222. return old;
  223. }
  224. @protected
  225. Future<List<EventInfo>> getEventList(int mapId);
  226. @protected
  227. Future<EventInfoExt> getEventInfoExt(int id);
  228. @protected
  229. Future<PlayerInfoExt> getPlayerInfoExt(int eventId, int userId);
  230. }