map_watch.dart 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import 'package:common_pub/model/control_point.dart';
  2. import 'package:common_pub/model/distance.dart';
  3. import 'package:common_pub/model/pace.dart';
  4. import 'package:common_pub/model/position.dart';
  5. import 'package:common_pub/service/controller.dart';
  6. import 'package:common_pub/ui/map_view/map_view.dart';
  7. import 'package:common_pub/ui/map_view/view_map_trace.dart';
  8. import '../logger.dart';
  9. import '../service/api.dart' as pb;
  10. import 'package:fixnum/fixnum.dart';
  11. typedef MapId = Int64;
  12. class Flag {
  13. Flag(this.value);
  14. int value;
  15. Color get color => Color(value);
  16. @override
  17. bool operator ==(Object other) {
  18. if (other is Flag) {
  19. return value == other.value;
  20. }
  21. return false;
  22. }
  23. @override
  24. int get hashCode => value.hashCode;
  25. static final red = Flag(0xffff0000);
  26. static final yellow = Flag(0xffffcb00);
  27. static final blue = Flag(0xff00a0ff);
  28. static List<Flag> get values => [red, yellow, blue];
  29. }
  30. class ActiveInfo {
  31. var id = 0;
  32. var name = '';
  33. var cpAllCount = 0;
  34. var userList = <UserInfo>[];
  35. final isHide = false.obs;
  36. UserInfo? getUserById(int id) {
  37. for (final one in userList) {
  38. if (one.gameInfo.userId == id) {
  39. return one;
  40. }
  41. }
  42. return null;
  43. }
  44. Future<UserInfo> newUserInfo(pb.ToOrienteerInGameInfo info) async {
  45. final r = await pb.ApiService.to.stub.toUserInActionBasicQuery(
  46. pb.ToUserInActionBasicQueryRequest(actId: id, userId: info.userId));
  47. final user = UserInfo()
  48. ..routeInfo = r.courseBaseInfo
  49. ..userInfo = r.baseInfo;
  50. await user.setGameInfo(info);
  51. return user;
  52. }
  53. Future<void> update(pb.ToActionInfo info) async {
  54. final newUserList = <UserInfo>[];
  55. for (final nUser in info.userList) {
  56. late UserInfo user;
  57. final oUser = getUserById(nUser.userId);
  58. if (oUser != null) {
  59. user = oUser;
  60. await user.update(nUser);
  61. } else {
  62. user = await newUserInfo(nUser);
  63. }
  64. newUserList.add(user);
  65. }
  66. userList = newUserList;
  67. }
  68. }
  69. extension ActiveInfoExt on pb.ToActionInfo {
  70. Future<ActiveInfo> into() async {
  71. final info = await pb.ApiService.to.stub
  72. .toActionBasicQuery(pb.IdRequest(id: Int64(actId)));
  73. final out = ActiveInfo()
  74. ..id = actId
  75. ..name = info.actName
  76. ..cpAllCount = info.totalControlNum;
  77. for (final one in userList) {
  78. out.userList.add(await out.newUserInfo(one));
  79. }
  80. return out;
  81. }
  82. }
  83. class UserInfo {
  84. final isHide = false.obs;
  85. String get name => userInfo.name;
  86. String get routeName => routeInfo.courseName;
  87. Pace get pace => Pace.perKm(gameInfo.gpsInfo.pace.seconds);
  88. Duration get duration =>
  89. DateTime.now().difference(gameInfo.gameSaveInfo.startAt.toModel());
  90. Distance get distance => Distance(m: gameInfo.gpsInfo.distance.toDouble());
  91. int get id => gameInfo.userId;
  92. var gameInfo = pb.ToOrienteerInGameInfo();
  93. var routeInfo = pb.CourseBaseInfo();
  94. var userInfo = pb.OrienteerBaseInfo();
  95. var trace = <TracePoint>[].obs;
  96. var flag = Flag.red.obs;
  97. DateTime? get startAt => gameInfo.gameSaveInfo.hasStartAt()
  98. ? gameInfo.gameSaveInfo.startAt.toModel()
  99. : null;
  100. var cpList = <ControlPoint>[];
  101. ControlPoint? nextWant;
  102. Distance get nextDistance {
  103. final one = nextWant;
  104. if (one != null) {
  105. final p1 = one.position;
  106. final p22 = gameInfo.gpsInfo.gameGpsInfos.lastOrNull;
  107. if (p22 != null) {
  108. final p2 = Position(longitude: p22.longitude, latitude: p22.latitude);
  109. return p1.distance(p2);
  110. }
  111. }
  112. return const Distance(m: 1000);
  113. }
  114. String get nextCPSN {
  115. return nextWant?.snString ?? '';
  116. }
  117. Future<void> update(pb.ToOrienteerInGameInfo info) async {
  118. final map = MapWatchService.instance;
  119. await setGameInfo(info);
  120. final indexMap = <int, TracePoint>{};
  121. for (final one in trace) {
  122. indexMap[one.ts.inMilliseconds] = one;
  123. }
  124. for (final one in info.gpsInfo.gameGpsInfos) {
  125. final t = one.gpsTime.toModel();
  126. final startAt = gameInfo.gameSaveInfo.startAt.toModel();
  127. final ts = t.difference(startAt);
  128. if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) {
  129. final pos = one.toModel();
  130. final oneTrace = TracePoint()
  131. ..ts = ts
  132. ..position = pos;
  133. if (map!.plugMap.isInitFinish){
  134. oneTrace.onMap =
  135. await map.plugMap.gameMap.worldToPixel(oneTrace.position);
  136. }
  137. trace.add(oneTrace);
  138. }
  139. }
  140. // if (map!.plugMap.isInitFinish) {
  141. // for (final one in trace) {
  142. // if (one.onMap == Offset.zero) {
  143. // one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
  144. // }
  145. // }
  146. // }
  147. }
  148. Future<void> setGameInfo(pb.ToOrienteerInGameInfo info) async {
  149. final map = MapWatchService.instance;
  150. gameInfo = info;
  151. cpList.clear();
  152. final cpMap = <int, ControlPoint>{};
  153. for (var (i, src) in routeInfo.controlPointSortedList.indexed) {
  154. final one = src.toModel()..sn = i.toString();
  155. if (map != null) {
  156. one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
  157. }
  158. cpList.add(one);
  159. cpMap[one.intId.toInt()] = one;
  160. }
  161. if (cpList.isNotEmpty) {
  162. cpList.first.isStart = true;
  163. cpList.last.isFinish = true;
  164. }
  165. var index = 0;
  166. for (var cp in gameInfo.gameSaveInfo.checkedSortedList) {
  167. if(cp.isCheckSuccess){
  168. for(var i = index; i < cpList.length; i++){
  169. final want = cpList[i];
  170. if(want.intId == cp.controlPointId){
  171. want.isSuccess=true;
  172. index++;
  173. break;
  174. }
  175. }
  176. }
  177. // cpMap[cp.controlPointId.toInt()]!.isSuccess = cp.isCheckSuccess;
  178. }
  179. for (var cp in cpList) {
  180. if (!cp.isSuccess) {
  181. cp.isNext = true;
  182. nextWant = cp;
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. class MapWatchService extends PlugController {
  189. static final Rx<MapWatchService?> _instance = Rx(null);
  190. static MapWatchService? get instance => _instance.value;
  191. static Future<void> setMapById(MapId id) async {
  192. final info =
  193. await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()..id = id);
  194. final thisInstance = MapWatchService(id: id)
  195. ..name = info.mapName
  196. ..plugMap.gameMap = info.zipImage.toGameMap();
  197. thisInstance.addPlugs([thisInstance.plugMap]);
  198. _instance.value = thisInstance;
  199. thisInstance.init();
  200. thisInstance.workFlushData();
  201. }
  202. Future<void> workFlushData() async {
  203. while (isActive) {
  204. try {
  205. await flushData();
  206. } catch (e) {
  207. error(e);
  208. }
  209. await 1.seconds.delay();
  210. }
  211. }
  212. ActiveInfo? getActiveById(int id) {
  213. for (final one in activeList) {
  214. if (one.id == id) {
  215. return one;
  216. }
  217. }
  218. return null;
  219. }
  220. Future<void> flushData() async {
  221. final r = await pb.ApiService.to.stub
  222. .toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(mapId: id.toInt()));
  223. final newList = <ActiveInfo>[];
  224. for (final one in r.list) {
  225. late ActiveInfo info;
  226. final old = getActiveById(one.actId);
  227. if (old != null) {
  228. info = old;
  229. await info.update(one);
  230. } else {
  231. info = await one.into();
  232. }
  233. newList.add(info);
  234. }
  235. activeList.value = newList;
  236. }
  237. MapWatchService({required this.id});
  238. final MapId id;
  239. String name = '';
  240. final plugMap = PlugMap();
  241. final activeList = <ActiveInfo>[].obs;
  242. }