map_watch.dart 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 id = gameInfo.gameSaveInfo.nextControlPoint.id;
  111. for (final one in routeInfo.controlPointSortedList){
  112. if(one.id==id){
  113. return one;
  114. }
  115. }
  116. return null;
  117. }
  118. Future<void> update(pb.ToOrienteerInGameInfo info)async{
  119. final map = MapWatchService.instance;
  120. gameInfo = info;
  121. final indexMap = <int, TracePoint>{};
  122. for (final one in trace){
  123. indexMap[one.ts.inMilliseconds]=one;
  124. }
  125. for(final one in info.gpsInfo.gameGpsInfos){
  126. final t = one.gpsTime.toModel();
  127. final startAt = gameInfo.gameSaveInfo.startAt.toModel();
  128. final ts = t.difference(startAt);
  129. if(ts.inMilliseconds>0 && !indexMap.containsKey(ts.inMilliseconds)){
  130. final pos = one.toModel();
  131. trace.add(TracePoint()
  132. ..ts = ts
  133. ..position=pos
  134. );
  135. }
  136. }
  137. if(map!.plugMap.isInitFinish){
  138. for (final one in trace){
  139. if(one.onMap==Offset.zero){
  140. one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
  141. }
  142. }
  143. }
  144. }
  145. }
  146. class MapWatchService extends PlugController{
  147. static final Rx<MapWatchService?> _instance = Rx(null);
  148. static MapWatchService? get instance => _instance.value;
  149. static Future<void> setMapById(MapId id)async{
  150. final info = await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()
  151. ..id = id);
  152. final thisInstance = MapWatchService(
  153. id: id)
  154. ..name = info.mapName
  155. ..plugMap.gameMap = info.zipImage.toGameMap() ;
  156. thisInstance.addPlugs([thisInstance.plugMap]);
  157. _instance.value = thisInstance;
  158. thisInstance.init();
  159. thisInstance.workFlushData();
  160. }
  161. Future<void> workFlushData()async{
  162. while(isActive){
  163. try{
  164. await flushData();
  165. }catch(e){
  166. error(e);
  167. }
  168. await 1.seconds.delay();
  169. }
  170. }
  171. ActiveInfo? getActiveById(int id){
  172. for (final one in activeList){
  173. if(one.id==id){
  174. return one;
  175. }
  176. }
  177. return null;
  178. }
  179. Future<void> flushData()async{
  180. final r = await pb.ApiService.to.stub.toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(
  181. mapId: id.toInt()));
  182. final newList = <ActiveInfo>[];
  183. for(final one in r.list){
  184. late ActiveInfo info;
  185. final old = getActiveById(one.actId);
  186. if(old != null){
  187. info = old;
  188. await info.update(one);
  189. }else{
  190. info = await one.into();
  191. }
  192. newList.add(info);
  193. }
  194. activeList.value = newList;
  195. }
  196. MapWatchService({required this.id});
  197. final MapId id;
  198. String name= '';
  199. final plugMap = PlugMap();
  200. final activeList = <ActiveInfo>[].obs;
  201. }