map_watch.dart 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. trace.add(TracePoint()
  131. ..ts = ts
  132. ..position = pos);
  133. }
  134. }
  135. if (map!.plugMap.isInitFinish) {
  136. for (final one in trace) {
  137. if (one.onMap == Offset.zero) {
  138. one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
  139. }
  140. }
  141. }
  142. }
  143. Future<void> setGameInfo(pb.ToOrienteerInGameInfo info) async {
  144. final map = MapWatchService.instance;
  145. gameInfo = info;
  146. cpList.clear();
  147. final cpMap = <int, ControlPoint>{};
  148. for (var (i, src) in routeInfo.controlPointSortedList.indexed) {
  149. final one = src.toModel()..sn = i.toString();
  150. if (map != null) {
  151. one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
  152. }
  153. cpList.add(one);
  154. cpMap[one.intId.toInt()] = one;
  155. }
  156. if (cpList.isNotEmpty) {
  157. cpList.first.isStart = true;
  158. cpList.last.isFinish = true;
  159. }
  160. var index = 0;
  161. for (var cp in gameInfo.gameSaveInfo.checkedSortedList) {
  162. if(cp.isCheckSuccess){
  163. for(var i = index; i < cpList.length; i++){
  164. final want = cpList[i];
  165. if(want.intId == cp.controlPointId){
  166. want.isSuccess=true;
  167. index++;
  168. break;
  169. }
  170. }
  171. }
  172. // cpMap[cp.controlPointId.toInt()]!.isSuccess = cp.isCheckSuccess;
  173. }
  174. for (var cp in cpList) {
  175. if (!cp.isSuccess) {
  176. cp.isNext = true;
  177. nextWant = cp;
  178. break;
  179. }
  180. }
  181. }
  182. }
  183. class MapWatchService extends PlugController {
  184. static final Rx<MapWatchService?> _instance = Rx(null);
  185. static MapWatchService? get instance => _instance.value;
  186. static Future<void> setMapById(MapId id) async {
  187. final info =
  188. await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()..id = id);
  189. final thisInstance = MapWatchService(id: id)
  190. ..name = info.mapName
  191. ..plugMap.gameMap = info.zipImage.toGameMap();
  192. thisInstance.addPlugs([thisInstance.plugMap]);
  193. _instance.value = thisInstance;
  194. thisInstance.init();
  195. thisInstance.workFlushData();
  196. }
  197. Future<void> workFlushData() async {
  198. while (isActive) {
  199. try {
  200. await flushData();
  201. } catch (e) {
  202. error(e);
  203. }
  204. await 1.seconds.delay();
  205. }
  206. }
  207. ActiveInfo? getActiveById(int id) {
  208. for (final one in activeList) {
  209. if (one.id == id) {
  210. return one;
  211. }
  212. }
  213. return null;
  214. }
  215. Future<void> flushData() async {
  216. final r = await pb.ApiService.to.stub
  217. .toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(mapId: id.toInt()));
  218. final newList = <ActiveInfo>[];
  219. for (final one in r.list) {
  220. late ActiveInfo info;
  221. final old = getActiveById(one.actId);
  222. if (old != null) {
  223. info = old;
  224. await info.update(one);
  225. } else {
  226. info = await one.into();
  227. }
  228. newList.add(info);
  229. }
  230. activeList.value = newList;
  231. }
  232. MapWatchService({required this.id});
  233. final MapId id;
  234. String name = '';
  235. final plugMap = PlugMap();
  236. final activeList = <ActiveInfo>[].obs;
  237. }