| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- import 'dart:collection';
- import 'package:common_pub/logger.dart';
- import 'package:common_pub/service/controller.dart';
- import 'package:common_pub/ui/map_view/map_view.dart';
- import 'package:common_pub/ui/map_view/view_map_trace.dart';
- import 'package:track_common/model.dart';
- import 'package:track_common/model/event_state.dart';
- class Flag {
- Flag(this.value);
- int value;
- Color get color => Color(value);
- @override
- bool operator ==(Object other) {
- if (other is Flag) {
- return value == other.value;
- }
- return false;
- }
- @override
- int get hashCode => value.hashCode;
- static final red = Flag(0xffff0000);
- static final yellow = Flag(0xffffcb00);
- static final blue = Flag(0xff00a0ff);
- static List<Flag> get values => [red, yellow, blue];
- }
- class PlayerInfo extends AppGameState {
- var id = 0;
- int heartRatePercent = 0;
- }
- class PlayerInfoExt {
- int id = 0;
- var name = '';
- var routeName = '';
- var cpListWant = <ControlPoint>[];
- }
- class EventInfo {
- var id = 0;
- var players = <PlayerInfo>[];
- }
- class EventInfoExt {
- var name = '';
- var cpAllCount = 0;
- String startAt = '';
- String endAt = '';
- EventState state = EventState.idle;
- }
- class PlayerOnMap {
- var info = PlayerInfo();
- var _ext = PlayerInfoExt();
- set ext(PlayerInfoExt v) {
- _ext = v;
- info.cpListWant = v.cpListWant;
- }
- int get id => info.id;
- String get name => _ext.name;
- List<ControlPoint> get cpList => info.cpListWant;
- final isHide = false.obs;
- var trace = <TracePoint>[].obs;
- var flag = Flag.red.obs;
- String get routeName => _ext.routeName;
- Distance get distance => info.distance;
- List<HeartRate> get hrInfo => info.hrHistory;
- List<Position> get positionList => info.positionHistory;
- DateTime watchAt = DateTime.now();
- int get heartRatePercent => info.heartRatePercent;
- Pace get pace => info.pace;
- Duration get duration => info.duration;
- ControlPoint? get cpNextWant => info.cpNextWant;
- Distance get nextDistance {
- final one = info.cpNextWant;
- if (one != null) {
- final p1 = one.position;
- final p22 = positionList.lastOrNull;
- if (p22 != null) {
- return p1.distance(p22);
- }
- }
- return const Distance(m: 1000);
- }
- String get nextCPSN {
- return info.cpNextWant?.snString ?? '';
- }
- }
- class EventOnMap {
- var info = EventInfo();
- var ext = EventInfoExt();
- var userList = <PlayerOnMap>[];
- int get id => info.id;
- String get name => ext.name;
- int get cpAllCount => ext.cpAllCount;
- final isHide = false.obs;
- PlayerOnMap? getUserById(int id) {
- for (final one in userList) {
- if (one.id == id) {
- return one;
- }
- }
- return null;
- }
- }
- abstract class MapWatchService extends GetxService {
- final Rx<MapWatch?> _instance = Rx(null);
- MapWatch? get instance => _instance.value;
- @protected
- Future<MapWatch> newInstanceByMap(MapInfo info);
- Future<void> setMap(MapInfo? mapInfo) async {
- _instance.value?.close();
- if (mapInfo != null) {
- final thisInstance = await newInstanceByMap(mapInfo);
- thisInstance.addPlugs([thisInstance.plugMap]);
- _instance.value = thisInstance;
- thisInstance.init();
- thisInstance.workFlushData();
- } else {
- _instance.value = null;
- }
- }
- }
- abstract class MapWatch extends PlugController {
- Future<void> workFlushData() async {
- while (isActive) {
- try {
- await flushData();
- } catch (e) {
- error("${e.toString()}", e);
- }
- await 1.seconds.delay();
- }
- }
- EventOnMap? getEventById(int id) {
- for (final one in eventList) {
- if (one.id == id) {
- return one;
- }
- }
- return null;
- }
- MapWatch({required this.id});
- final int id;
- String name = '';
- final plugMap = PlugMap();
- final eventList = <EventOnMap>[].obs;
- Future<void> flushData() async {
- final list = await getEventList(id);
- final newList = <EventOnMap>[];
- for (final one in list) {
- late EventOnMap event;
- final old = getEventById(one.id);
- if (old != null) {
- event = old;
- await updateEvent(event, one);
- } else {
- event = await initEvent(one);
- }
- newList.add(event);
- }
- eventList.value = newList;
- }
- Future<HashMap<int, PlayerInfoExt>> getPlayerInfoExtMap(
- int eventId, Iterable<int> userIdList) async {
- final playerExtList = await getPlayerInfoExt(eventId, userIdList);
- final playerExtMap = HashMap<int, PlayerInfoExt>();
- for (final one in playerExtList) {
- playerExtMap[one.id] = one;
- }
- return playerExtMap;
- }
- Future<EventOnMap> initEvent(EventInfo info) async {
- final ext = await getEventInfoExt(info.id);
- final one = EventOnMap()
- ..info = info
- ..ext = ext;
- final playerIdList = info.players.map((e) => e.id);
- final playerExtMap = await getPlayerInfoExtMap(info.id, playerIdList);
- for (var p in info.players) {
- one.userList.add(await initPlayer(info, p, playerExtMap));
- }
- return one;
- }
- Future<PlayerOnMap> initPlayer(EventInfo event, PlayerInfo playerInfo,
- HashMap<int, PlayerInfoExt> playerExtMap) async {
- final userId = playerInfo.id;
- final player = PlayerOnMap()..info = playerInfo;
- if (playerExtMap != null) {
- player.ext = playerExtMap[userId]!;
- } else {
- player.ext = (await getPlayerInfoExt(event.id, [userId])).first;
- }
- return player;
- }
- Future<void> updateEvent(EventOnMap old, EventInfo newOne) async {
- final newUserList = <PlayerOnMap>[];
- final ext = await getEventInfoExt(old.id);
- final needUserIdList = <int>[];
- for (final nUser in newOne.players) {
- final oUser = old.getUserById(nUser.id);
- if (oUser == null) {
- needUserIdList.add(nUser.id);
- }
- }
- final playerExtMap = await getPlayerInfoExtMap(old.id, needUserIdList);
- for (final nUser in newOne.players) {
- late PlayerOnMap user;
- final oUser = old.getUserById(nUser.id);
- if (oUser != null) {
- user = await updatePlayer(oUser, nUser);
- } else {
- user = await initPlayer(old.info, nUser, playerExtMap);
- }
- await playerUpdateMap(user);
- newUserList.add(user);
- }
- old.userList = newUserList;
- old.ext = ext;
- }
- Future<void> playerUpdateMap(PlayerOnMap info) async {
- for (var one in info.cpList) {
- one.onMap = await plugMap.gameMap.worldToPixel(one.position);
- }
- }
- Future<PlayerOnMap> updatePlayer(PlayerOnMap old, PlayerInfo newUser) async {
- final indexMap = <int, TracePoint>{};
- old.info = newUser;
- old.ext = old._ext;
- for (final one in old.trace) {
- indexMap[one.ts.inMilliseconds] = one;
- }
- for (final one in newUser.positionHistory) {
- final t = one.timestamp;
- final startAt = old.watchAt;
- final ts = t.difference(startAt);
- if (ts.inMilliseconds > 0 && !indexMap.containsKey(ts.inMilliseconds)) {
- final pos = one;
- final oneTrace = TracePoint()
- ..ts = ts
- ..position = pos;
- if (plugMap.isInitFinish) {
- oneTrace.onMap =
- await plugMap.gameMap.worldToPixel(oneTrace.position);
- }
- old.trace.add(oneTrace);
- } else if (old.trace.isEmpty) {
- final oneTrace = TracePoint()
- ..ts = Duration.zero
- ..position = one;
- if (plugMap.isInitFinish) {
- oneTrace.onMap =
- await plugMap.gameMap.worldToPixel(oneTrace.position);
- old.trace.add(oneTrace);
- }
- }
- }
- return old;
- }
- @protected
- Future<List<EventInfo>> getEventList(int mapId);
- @protected
- Future<EventInfoExt> getEventInfoExt(int id);
- @protected
- Future<Iterable<PlayerInfoExt>> getPlayerInfoExt(
- int eventId, Iterable<int> userIdList);
- }
|