map_watch.dart 6.6 KB

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