| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import 'dart:async';
- import 'package:grpc/grpc.dart';
- import 'package:trackoffical_app/exception/exception.dart';
- import 'package:trackoffical_app/logger.dart';
- import 'package:trackoffical_app/model.dart';
- import 'package:trackoffical_app/service/api.dart';
- import 'package:trackoffical_app/service/app.dart';
- import 'package:trackoffical_app/service/app_map.dart';
- import 'package:trackoffical_app/service/game/game_instance.dart';
- import 'package:trackoffical_app/service/image.dart';
- import 'package:trackoffical_app/utils.dart';
- import 'package:protobuf/protobuf.dart';
- import '../../model/game_map.dart';
- import '../../model/game_person_data.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:trackoffical_app/pb.dart' as pb;
- class GameInstanceGuardian extends GameInstance {
- GameInstanceGuardian({required this.underGuardianId});
- @override
- Future<void> onInit() async {
- if (underGuardianId >= 0) {
- _workWatch();
- } else {
- // 测试
- _gameMapInitState = 'ok';
- }
- await _waitGameMapOk();
- if (!isActive) {
- throw FutureCancel();
- }
- await gameMapData.loadMemory(onReceiveProgress: (int count, int total) {});
- if (!isActive) {
- throw FutureCancel();
- }
- for(var p in gamePersonData){
- await p.initControlPointWantSequence(gameMapData);
- }
- addTimer(100.milliseconds, () {
- for (var one in gamePersonData) {
- final startAt = one.startAt;
- final endAt = one.endAt ?? App.to.now;
- var duration = startAt != null ? endAt.difference(startAt) : 0.seconds;
- one.duration.value = duration;
- }
- });
- }
- void _workWatch() async {
- debug('watch: 开始');
- while (isActive) {
- try {
- _watchStream = ApiService.to.guardianWatch(underGuardianId);
- await for (var msg in _watchStream!.stream) {
- debug('rcv: ${msg.meta.typeUrl}');
- msg.handleType(pb.GetInGameDataReply(), (userId, data) {
- onPersonInit(userId, data);
- onMapInit(data.data);
- });
- msg.handleType(pb.GameGpsUploadRequest(), onGameGpsUploadRequest);
- msg.handleType(pb.GameFinishRequest(), onGameFinish);
- msg.handleType(pb.GameSaveUploadRequest(), onGameSaveUploadRequest);
- msg.handleType(pb.GameHrUploadRequest(), onGameHrUploadRequest);
- msg.handleType(pb.GameCleUploadRequest(), onGameCleUploadRequest);
- msg.handleType(pb.PupilInGameInfoOther(), onPupilInGameInfoOther);
- }
- } on GrpcError catch (e) {
- if (e.code == StatusCode.unavailable) {
- warn('watch: 断线:$e');
- await 3.seconds.delay();
- }else if (e.code == StatusCode.cancelled) {
- break;
- } else {
- warn('watch: GrpcError:$e');
- _gameMapInitState = e;
- break;
- }
- } catch (e) {
- debug('watch: err:$e');
- _gameMapInitState = e;
- break;
- }
- }
- if (Get.currentRoute == '/GuardianWatchGameView') {
- Get.back();
- }
- debug('watch: 结束');
- }
- void onGameSaveUploadRequest(int userId, pb.GameSaveUploadRequest data) {
- final old = _gamePersonDataGetByUserId(userId);
- if (old != null) {
- old.gameSrcState.update((val) {
- val?.pbGameSave = data.gameSave;
- });
- old.cpWantSequenceRefresh(gameMapData);
- }
- }
- void onPersonInit(int userId, pb.GetInGameDataReply data) {
- final old = _gamePersonDataGetByUserId(userId);
- if (old == null) {
- final headImage = data.data.image.toModel();
- final state = data.data.toGameState();
- state.pbGameSave = data.save;
- final person = GamePersonData()
- ..userId = userId
- ..userHead.value = headImage
- ..userName = data.data.name
- ..gameSrcState.value = state;
- headImage.loadMemory().then((value) => person.userHead.update((val) {}));
- gamePersonData.add(person);
- person.initControlPointWantSequence(gameMapData);
- }
- }
- Future<void> onMapInit(pb.GameData data) async {
- if (_gameMapInitState == 'ok') {
- return;
- }
- gameMapData = data.mapZip.toGameMap();
- _gameMapInitState = 'ok';
- }
- void onGameGpsUploadRequest(int userId, pb.GameGpsUploadRequest data) async {
- final p = _gamePersonDataGetByUserId(userId);
- if (p != null) {
- final gpsList = data.gameGpsInfos.map((e) => e.toModel()).toList();
- p.myPositionHistory.addAll(gpsList);
- final onMapList = <Offset>[];
- for (var one in gpsList) {
- onMapList.add(await gameMapData.worldToPixel(one));
- }
- p.myPositionOnMapHistory.addAll(onMapList);
- p.pacePerKm.value = data.pace.seconds;
- p.myPositionHistoryLen.value = data.distance.meter;
- }
- }
- void onGameHrUploadRequest(int userId, pb.GameHrUploadRequest data)async {
- final p = _gamePersonDataGetByUserId(userId);
- if (p != null) {
- if(data.gameHrInfos.isNotEmpty){
- final hr = data.gameHrInfos.last;
- p.heartRate.value = hr.hr;
- }
- }
- }
- void onGameCleUploadRequest(int userId, pb.GameCleUploadRequest data)async {
- final p = _gamePersonDataGetByUserId(userId);
- if (p != null) {
- p.ck.value = data.ck.toDouble();
- p.kCal.value = data.cle.toDouble()/1000;
- p.hrMean.value = data.avgHr;
- p.hrMax.value = data.maxHr;
- p.stepCount.value = data.stepNum;
- p.heartRatePercent.value = data.heartRatePercent.toDouble();
- }
- }
- void onPupilInGameInfoOther(int userId, pb.PupilInGameInfoOther data)async {
- final p = _gamePersonDataGetByUserId(userId);
- if (p != null) {
- p.beanCount.value = data.sysPoint;
- }
- }
- void onGameFinish(int userId, pb.GameFinishRequest data) async {
- _gamePersonDataRemoveByUserId(userId);
- }
- GamePersonData? _gamePersonDataGetByUserId(int userId) {
- for (var one in gamePersonData) {
- if (one.userId == userId) {
- return one;
- }
- }
- return null;
- }
- void _gamePersonDataRemoveByUserId(int userId) {
- var index = -1;
- for (var i = 0; i < gamePersonData.length; i++) {
- if (gamePersonData[i].userId == userId) {
- index = i;
- break;
- }
- }
- if (index >= 0) {
- gamePersonData.removeAt(index);
- }
- }
- Future<void> _waitGameMapOk() async {
- while (isActive && _gameMapInitState == null) {
- await 10.milliseconds.delay();
- }
- if (_gameMapInitState == 'ok') {
- return;
- }
- throw _gameMapInitState;
- }
- @override
- Future<void> onClose() async {
- _watchStream?.stream.cancel();
- _watchStream?.channel.terminate();
- }
- final gamePersonData = <GamePersonData>[].obs;
- var gameMapData = GameMap();
- final int underGuardianId;
- StreamGuardianWatch? _watchStream;
- dynamic _gameMapInitState;
- }
- extension MsgHandle on pb.PupilInGameWatchReply {
- void handleType<T extends GeneratedMessage>(
- T instance, void Function(int userId, T data) handler) {
- if (meta.canUnpackInto(instance)) {
- final data = meta.unpackInto(instance);
- handler(oId, data);
- }
- }
- }
|