map_watch.dart 6.3 KB

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