周睿 2 anni fa
parent
commit
925830aa10

+ 101 - 95
lib/service/map_watch.dart

@@ -1,3 +1,4 @@
+import 'package:common_pub/model/control_point.dart';
 import 'package:common_pub/model/distance.dart';
 import 'package:common_pub/model/pace.dart';
 import 'package:common_pub/model/position.dart';
@@ -8,17 +9,16 @@ import '../logger.dart';
 import '../service/api.dart' as pb;
 import 'package:fixnum/fixnum.dart';
 
-
 typedef MapId = Int64;
 
-class Flag{
+class Flag {
   Flag(this.value);
   int value;
-  Color get color=>Color(value);
+  Color get color => Color(value);
 
   @override
   bool operator ==(Object other) {
-    if(other is Flag){
+    if (other is Flag) {
       return value == other.value;
     }
     return false;
@@ -30,20 +30,19 @@ class Flag{
   static final red = Flag(0xffff0000);
   static final yellow = Flag(0xffffcb00);
   static final blue = Flag(0xff00a0ff);
-  static List<Flag> get values =>[red, yellow, blue];
+  static List<Flag> get values => [red, yellow, blue];
 }
 
-class ActiveInfo{
+class ActiveInfo {
   var id = 0;
   var name = '';
   var cpAllCount = 0;
   var userList = <UserInfo>[];
   final isHide = false.obs;
 
-
-  UserInfo? getUserById(int id){
-    for (final one in userList){
-      if(one.gameInfo.userId==id){
+  UserInfo? getUserById(int id) {
+    for (final one in userList) {
+      if (one.gameInfo.userId == id) {
         return one;
       }
     }
@@ -51,18 +50,18 @@ class ActiveInfo{
     return null;
   }
 
-  Future<UserInfo> newUserInfo(pb.ToOrienteerInGameInfo info)async{
-    final r =await pb.ApiService.to.stub.toUserInActionBasicQuery(pb.ToUserInActionBasicQueryRequest(
-      actId: id,
-      userId: info.userId
-    ));
+  Future<UserInfo> newUserInfo(pb.ToOrienteerInGameInfo info) async {
+    final r = await pb.ApiService.to.stub.toUserInActionBasicQuery(
+        pb.ToUserInActionBasicQueryRequest(actId: id, userId: info.userId));
 
-    return UserInfo()
+    final user = UserInfo()
       ..routeInfo = r.courseBaseInfo
-      ..userInfo = r.baseInfo
-      ..gameInfo = info
-    ;
+      ..userInfo = r.baseInfo;
+    await user.setGameInfo(info);
+
+    return user;
   }
+
   Future<void> update(pb.ToActionInfo info) async {
     final newUserList = <UserInfo>[];
 
@@ -72,8 +71,7 @@ class ActiveInfo{
       if (oUser != null) {
         user = oUser;
         await user.update(nUser);
-
-      }else{
+      } else {
         user = await newUserInfo(nUser);
       }
 
@@ -81,20 +79,19 @@ class ActiveInfo{
     }
     userList = newUserList;
   }
-
 }
-extension ActiveInfoExt on pb.ToActionInfo{
+
+extension ActiveInfoExt on pb.ToActionInfo {
   Future<ActiveInfo> into() async {
-    final info = await pb.ApiService.to.stub.toActionBasicQuery(
-        pb.IdRequest(id: Int64(actId)));
+    final info = await pb.ApiService.to.stub
+        .toActionBasicQuery(pb.IdRequest(id: Int64(actId)));
 
     final out = ActiveInfo()
       ..id = actId
       ..name = info.actName
       ..cpAllCount = info.totalControlNum;
 
-
-    for(final one in userList){
+    for (final one in userList) {
       out.userList.add(await out.newUserInfo(one));
     }
 
@@ -102,27 +99,31 @@ extension ActiveInfoExt on pb.ToActionInfo{
   }
 }
 
-
-class UserInfo{
+class UserInfo {
   final isHide = false.obs;
   String get name => userInfo.name;
   String get routeName => routeInfo.courseName;
-  Pace get pace => Pace.perKm( gameInfo.gpsInfo.pace.seconds);
-  Duration get duration => DateTime.now().difference(gameInfo.gameSaveInfo.startAt.toModel());
+  Pace get pace => Pace.perKm(gameInfo.gpsInfo.pace.seconds);
+  Duration get duration =>
+      DateTime.now().difference(gameInfo.gameSaveInfo.startAt.toModel());
   Distance get distance => Distance(m: gameInfo.gpsInfo.distance.toDouble());
   var gameInfo = pb.ToOrienteerInGameInfo();
   var routeInfo = pb.CourseBaseInfo();
   var userInfo = pb.OrienteerBaseInfo();
   var trace = <TracePoint>[].obs;
   var flag = Flag.red.obs;
-  DateTime? get startAt => gameInfo.gameSaveInfo.hasStartAt()?gameInfo.gameSaveInfo.startAt.toModel(): null;
+  DateTime? get startAt => gameInfo.gameSaveInfo.hasStartAt()
+      ? gameInfo.gameSaveInfo.startAt.toModel()
+      : null;
+  var cpList = <ControlPoint>[];
+  ControlPoint? nextWant;
 
   Distance get nextDistance {
     final one = nextWant;
-    if(one!= null){
-      final p1 = Position(longitude: one.ciPosition.longitude, latitude: one.ciPosition.latitude);
+    if (one != null) {
+      final p1 = one.position;
       final p22 = gameInfo.gpsInfo.gameGpsInfos.lastOrNull;
-      if(p22 != null){
+      if (p22 != null) {
         final p2 = Position(longitude: p22.longitude, latitude: p22.latitude);
         return p1.distance(p2);
       }
@@ -130,78 +131,84 @@ class UserInfo{
     return const Distance(m: 1000);
   }
 
-  pb.ToControlPoint? get nextWant{
-    final no = gameInfo.gameSaveInfo.nextControlPoint.orderNo;
-    if(no < routeInfo.controlPointSortedList.length){
-      final out = routeInfo.controlPointSortedList[no];
-      out.orderNo=no;
-      return out;
-    }
-
-    return null;
-  }
-  String get nextCPSN{
-    var str = '开始';
-    final next = nextWant;
-    final wantList = routeInfo.controlPointSortedList;
-    if(next != null){
-      if(next.orderNo == wantList.length-1){
-        str = '结束';
-      }else if(next.orderNo > 0){
-        str = '${next.orderNo}号';
-      }
-    }
-    return str;
+  String get nextCPSN {
+    return nextWant?.snString ?? '';
   }
 
-
-  Future<void> update(pb.ToOrienteerInGameInfo info)async{
+  Future<void> update(pb.ToOrienteerInGameInfo info) async {
     final map = MapWatchService.instance;
 
-
-    gameInfo = info;
+    await setGameInfo(info);
     final indexMap = <int, TracePoint>{};
 
-    for (final one in trace){
-      indexMap[one.ts.inMilliseconds]=one;
+    for (final one in trace) {
+      indexMap[one.ts.inMilliseconds] = one;
     }
 
-    for(final one in info.gpsInfo.gameGpsInfos){
+    for (final one in info.gpsInfo.gameGpsInfos) {
       final t = one.gpsTime.toModel();
       final startAt = gameInfo.gameSaveInfo.startAt.toModel();
       final ts = t.difference(startAt);
-      if(ts.inMilliseconds>0 && !indexMap.containsKey(ts.inMilliseconds)){
+      if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) {
         final pos = one.toModel();
         trace.add(TracePoint()
-            ..ts = ts
-            ..position=pos
-        );
+          ..ts = ts
+          ..position = pos);
       }
     }
 
-    if(map!.plugMap.isInitFinish){
-      for (final one in trace){
-        if(one.onMap==Offset.zero){
+    if (map!.plugMap.isInitFinish) {
+      for (final one in trace) {
+        if (one.onMap == Offset.zero) {
           one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
         }
       }
     }
   }
-}
 
+  Future<void> setGameInfo(pb.ToOrienteerInGameInfo info) async {
+    final map = MapWatchService.instance;
+    gameInfo = info;
+    cpList.clear();
+    final cpMap = <int, ControlPoint>{};
+    for (var (i, src) in routeInfo.controlPointSortedList.indexed) {
+      final one = src.toModel()..sn = i.toString();
+      if (map != null) {
+        one.onMap = await map.plugMap.gameMap.worldToPixel(one.position);
+      }
+
+      cpList.add(one);
+      cpMap[one.intId.toInt()] = one;
+    }
+    if (cpList.isNotEmpty) {
+      cpList.first.isStart = true;
+      cpList.last.isFinish = true;
+    }
+    for (var cp in gameInfo.gameSaveInfo.checkedSortedList) {
+      cpMap[cp.controlPointId]!.isSuccess = cp.isCheckSuccess;
+    }
+
+    for (var cp in cpList) {
+      if (!cp.isSuccess) {
+        cp.isNext = true;
+        nextWant = cp;
+        break;
+      }
+    }
+  }
+}
 
-class MapWatchService extends PlugController{
+class MapWatchService extends PlugController {
   static final Rx<MapWatchService?> _instance = Rx(null);
   static MapWatchService? get instance => _instance.value;
 
-  static Future<void> setMapById(MapId id)async{
-    final info = await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()
-      ..id = id);
+  static Future<void> setMapById(MapId id) async {
+    final info =
+        await pb.ApiService.to.stub.toMapDetailV2(pb.IdRequest()..id = id);
 
-    final thisInstance = MapWatchService(
-        id: id)
+    final thisInstance = MapWatchService(id: id)
       ..name = info.mapName
-      ..plugMap.gameMap = info.zipImage.toGameMap() ;
+      ..plugMap.gameMap = info.zipImage.toGameMap();
 
     thisInstance.addPlugs([thisInstance.plugMap]);
 
@@ -210,39 +217,39 @@ class MapWatchService extends PlugController{
     thisInstance.workFlushData();
   }
 
-  Future<void> workFlushData()async{
-    while(isActive){
-      try{
+  Future<void> workFlushData() async {
+    while (isActive) {
+      try {
         await flushData();
-      }catch(e){
+      } catch (e) {
         error(e);
       }
       await 1.seconds.delay();
     }
   }
 
-  ActiveInfo? getActiveById(int id){
-    for (final one in activeList){
-      if(one.id==id){
+  ActiveInfo? getActiveById(int id) {
+    for (final one in activeList) {
+      if (one.id == id) {
         return one;
       }
     }
     return null;
   }
 
-  Future<void> flushData()async{
-    final r = await pb.ApiService.to.stub.toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(
-        mapId: id.toInt()));
+  Future<void> flushData() async {
+    final r = await pb.ApiService.to.stub
+        .toUserDetailQueryV2(pb.ToUserDetailQueryRequestV2(mapId: id.toInt()));
 
     final newList = <ActiveInfo>[];
 
-    for(final one in r.list){
+    for (final one in r.list) {
       late ActiveInfo info;
       final old = getActiveById(one.actId);
-      if(old != null){
+      if (old != null) {
         info = old;
         await info.update(one);
-      }else{
+      } else {
         info = await one.into();
       }
       newList.add(info);
@@ -251,10 +258,9 @@ class MapWatchService extends PlugController{
     activeList.value = newList;
   }
 
-
   MapWatchService({required this.id});
   final MapId id;
-  String name= '';
+  String name = '';
   final plugMap = PlugMap();
   final activeList = <ActiveInfo>[].obs;
-}
+}

+ 45 - 13
lib/view/home/field_control/field_control.dart

@@ -1,6 +1,7 @@
 import 'package:application/service/api.dart' as pb;
 import 'package:application/widget.dart';
 import 'package:common_pub/ui/map_view/map_view.dart';
+import 'package:common_pub/ui/map_view/view_map_cp.dart';
 import 'package:common_pub/ui/map_view/view_map_image.dart';
 import 'package:common_pub/ui/map_view/view_map_trace_tail.dart';
 import 'package:common_pub/ui/map_view/view_map_touch.dart';
@@ -47,18 +48,32 @@ class FieldControlPage extends StatelessWidget {
 
   Widget content(
       BuildContext context, MapWatchService map, FieldControlController c) {
+    final children = <Widget>[
+      ViewPlugLoading(map.plugMap),
+      ViewMapImage(map.plugMap),
+    ];
+
+    final focusUser = c.focusUser.value;
+    if (focusUser != null) {
+      children.add(ViewMapCP(
+        map.plugMap,
+        cpWantAndHistoryList: focusUser.cpList,
+        isHideRouteBeforeStart: false,
+      ));
+    }
+
+    children.addAll([
+      _ViewTrace(map: map, traceDuration: 30.seconds),
+      ViewMapTouch(map.plugMap)
+    ]);
+
     return Row(
       children: [
         Expanded(
             child: Column(
           children: [
             Expanded(
-                child: ViewMapStack(plug: map.plugMap, children: [
-              ViewPlugLoading(map.plugMap),
-              ViewMapImage(map.plugMap),
-              _ViewTrace(map: map, traceDuration:30.seconds),
-              ViewMapTouch(map.plugMap)
-            ])),
+                child: ViewMapStack(plug: map.plugMap, children: children)),
             _MsgView(),
           ],
         )),
@@ -74,13 +89,11 @@ class _ViewTrace extends GetView<FieldControlController> {
   final MapWatchService map;
   final Duration traceDuration;
 
-
   @override
   Widget build(BuildContext context) {
     return Obx(() {
       final children = <Widget>[];
 
-
       for (final act in map.activeList) {
         for (final user in act.userList) {
           if (user.isHide.value) {
@@ -89,14 +102,18 @@ class _ViewTrace extends GetView<FieldControlController> {
           final trace = user.trace.lastOrNull;
           final traceTailOnMap = <Offset>[];
           final st = user.gameInfo.gameSaveInfo.startAt.toModel();
-          for(final one in user.trace){
-            if(DateTime.now().difference(st.add(one.ts)) < traceDuration ){
+          for (final one in user.trace) {
+            if (DateTime.now().difference(st.add(one.ts)) < traceDuration) {
               traceTailOnMap.add(one.onMap);
             }
           }
 
           if (trace != null) {
-            children.add(ViewMapTraceTail(plug: map.plugMap, onMapTrace: traceTailOnMap, color: user.flag.value.color,));
+            children.add(ViewMapTraceTail(
+              plug: map.plugMap,
+              onMapTrace: traceTailOnMap,
+              color: user.flag.value.color,
+            ));
             children.add(ViewMapUserPoint(map.plugMap, trace,
                 info: user.name, color: user.flag.value.color));
           }
@@ -216,7 +233,9 @@ class _UserInfoView extends GetView<FieldControlController> {
                         color: Colors.white,
                       ),
                       ' ${hr == 0 ? '--' : hr}',
-                      (data.gameInfo.otherInfo.hasHeartRatePercent()?data.gameInfo.otherInfo.heartRatePercent: 0)
+                      (data.gameInfo.otherInfo.hasHeartRatePercent()
+                              ? data.gameInfo.otherInfo.heartRatePercent
+                              : 0)
                           .toHRPColor()),
                   container(null, paceInfo, data.pace.color)
                 ],
@@ -232,6 +251,19 @@ class _UserInfoView extends GetView<FieldControlController> {
               )
             ],
           )),
+          GestureDetector(
+            onTap: () {
+              controller.focusUser.value = data;
+            },
+            child: Obx(() => Icon(
+                  Icons.route,
+                  color: data.gameInfo.userId !=
+                          controller.focusUser.value?.gameInfo.userId
+                      ? Colors.grey
+                      : const Color(0xffffbb77),
+                )),
+          ),
+          const SizedBox(width: 8),
           GestureDetector(
             onTap: () {
               data.isHide.value = !data.isHide.value;
@@ -253,7 +285,7 @@ class _UserInfoView extends GetView<FieldControlController> {
 
   String get cpInfo {
     final next = data.nextWant;
-    return next!=null?'${data.nextCPSN}点(${next.sn})': '--';
+    return next != null ? '${data.nextCPSN}点(${next.areaId})' : '--';
   }
 
   String get paceInfo {

+ 5 - 7
lib/view/home/field_control/field_control_controller.dart

@@ -1,23 +1,21 @@
-import 'package:application/service/api.dart';
 import 'package:application/service/map_watch.dart';
-import 'package:application/logger.dart';
 import 'package:get/get.dart';
 import '../home_controller.dart';
 export 'package:application/service/map_watch.dart';
 
-
-class FieldControlController extends GetxController{
+class FieldControlController extends GetxController {
   @override
   void onInit() {
     super.onInit();
     final map = MapWatchService.instance;
-    if(map != null){
+    if (map != null) {
       activeList.bindStream(map.activeList.stream);
     }
   }
 
-
   HomeController get _home => Get.find();
   MapWatchService? get mapWatch => MapWatchService.instance;
   final activeList = <ActiveInfo>[].obs;
-}
+  final Rx<UserInfo?> focusUser = Rx(null);
+  
+}

+ 1 - 0
lib/view/home/map/map_page.dart

@@ -44,6 +44,7 @@ class MapPageController extends GetxController {
   final isMapGetMoreLoading = false.obs;
   final mapListScrollController = ScrollController();
   final Rx<m.Position?> position = Rx(null);
+  
 }
 
 class MapPage extends StatelessWidget {

+ 1 - 1
third_party/common_pub

@@ -1 +1 @@
-Subproject commit 6ab2a84e79c8b12c85a5dcb15dfef8af08931be4
+Subproject commit 9e788bdf27aad8acf7a7fe2d5a310005a8e686a2