utils.dart 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:trackoffical_app/model/m_control_point.dart';
  4. import 'package:trackoffical_app/service/game/game_model.dart';
  5. import 'package:trackoffical_app/utils.dart';
  6. import 'package:trackoffical_app/view/ingame/in_game_controller.dart';
  7. import 'package:screen_brightness/screen_brightness.dart';
  8. import '../../service/game/game.dart';
  9. import '../../widget/app_dialog.dart';
  10. import 'checked_cp_record.dart';
  11. extension MCPExt on MControlPoint{
  12. Widget display({TextStyle? textStyle, double? height}){
  13. final next = this;
  14. if (next.sn == MControlPoint.snStart || next.sn == MControlPoint.snFinish) {
  15. var src = 'ic_bottom_bar_next_start.png';
  16. if (next.sn == MControlPoint.snFinish) {
  17. src = 'ic_bottom_bar_next_finish.png';
  18. }
  19. return Image.asset(
  20. 'assets/images/$src',
  21. height: height??22,
  22. fit: BoxFit.fitHeight,
  23. color: Colors.white,
  24. );
  25. }
  26. return Text(next.sn, style: textStyle);
  27. }
  28. Widget icon({double? height}){
  29. final next = this;
  30. var src = 'ic_cp.png';
  31. if(next.isStart){
  32. src = 'ic_cp_start.png';
  33. }
  34. if(next.isFinish){
  35. src = 'ic_cp_finish.png';
  36. }
  37. return Image.asset(
  38. 'assets/images/$src',
  39. height: height??22,
  40. fit: BoxFit.fitHeight,
  41. );
  42. }
  43. }
  44. extension MCPNullableExt on MControlPoint?{
  45. Widget display({TextStyle? textStyle, double? height}){
  46. Widget text;
  47. final nextCp = this;
  48. if (nextCp != null) {
  49. text = nextCp.display(textStyle: textStyle);
  50. if (nextCp.areaId.isNotEmpty && nextCp.type == MControlPointType.nfc) {
  51. text = Row(
  52. mainAxisSize: MainAxisSize.min,
  53. children: [
  54. text,
  55. Text(
  56. ' (${nextCp.areaId})',
  57. style: textStyle,
  58. )
  59. ],
  60. );
  61. }
  62. } else {
  63. text = Text('--', style: textStyle, maxLines: 1);
  64. }
  65. return text;
  66. }
  67. }
  68. class _TwoValueElem extends StatelessWidget{
  69. const _TwoValueElem({
  70. required this.value1,
  71. required this.value2,
  72. required this.unit,
  73. required this.fontSize
  74. });
  75. final String value1;
  76. final String value2;
  77. final String unit;
  78. final double fontSize;
  79. @override
  80. Widget build(BuildContext context) {
  81. final small = fontSize * 0.875;
  82. final unitSize = small -2;
  83. return Row(
  84. children: [
  85. Expanded(child: Column(
  86. mainAxisSize: MainAxisSize.min,
  87. children: [
  88. SizedBox(
  89. width: context.width,
  90. child: Text(value1,
  91. maxLines: 1,
  92. style: TextStyle(fontSize: small))),
  93. Container(height: 1, width: context.width, color: Colors.white,),
  94. SizedBox(
  95. width: context.width,
  96. child: Text(value2,
  97. maxLines: 1,
  98. textAlign: TextAlign.end,
  99. style: TextStyle(fontSize: fontSize))),
  100. ],
  101. )),
  102. const SizedBox(width: 5),
  103. Text(unit, style: TextStyle(fontSize: unitSize))
  104. ],
  105. );
  106. }
  107. }
  108. extension GameModelExt on GameModel{
  109. Widget widgetDistance({double fontSize = 17.4, bool withTrip = true}) {
  110. final small = fontSize * 0.875;
  111. final unitSize = small -2;
  112. if (withTrip){
  113. return _TwoValueElem(
  114. value1: (myPositionHistoryLenFromLastCP.m).round().toString(),
  115. value2: (myPositionHistoryLen.value.m).round().toString(),
  116. unit: 'm',
  117. fontSize: fontSize);
  118. }else{
  119. var (value, unit) = myPositionHistoryLen.value.toStringValueAndUnit();
  120. return RichText(text: TextSpan(
  121. text: value,
  122. style: TextStyle(fontSize: fontSize),
  123. children: [
  124. TextSpan(text: unit, style: TextStyle(fontSize: unitSize))
  125. ]
  126. ));
  127. }
  128. }
  129. String paceString(Duration pace){
  130. if(pace.inMinutes> 99){
  131. return '99+\'';
  132. }
  133. return pace.toMinSecondString();
  134. }
  135. Widget widgetPace({double fontSize = 17.4, bool withTrip = true}) {
  136. final small = fontSize * 0.875;
  137. final unitSize = small -2;
  138. if (withTrip){
  139. return _TwoValueElem(
  140. value1: paceString(paceSecondKmFromLastCP.value),
  141. value2: paceString(paceSecondKm.value),
  142. unit: '/km',
  143. fontSize: fontSize);
  144. }else{
  145. return RichText(text: TextSpan(
  146. text: paceString(paceSecondKm.value),
  147. style: TextStyle(fontSize: fontSize),
  148. children: [
  149. TextSpan(text: '/km', style: TextStyle(fontSize: unitSize))
  150. ]
  151. ));
  152. }
  153. }
  154. }
  155. Widget wSport(String value, String iconSrc, {TextStyle? textStyle}) {
  156. return Column(
  157. mainAxisSize: MainAxisSize.min,
  158. crossAxisAlignment: CrossAxisAlignment.center,
  159. children: [
  160. Text(value, maxLines: 1, overflow: TextOverflow.clip, style: textStyle),
  161. Image.asset(iconSrc, height: 14.16)],
  162. );
  163. }
  164. void showCheckedPoints(List<MControlPoint> data) {
  165. final textStyle = Get.theme.textTheme.titleLarge;
  166. Get.dialog(
  167. Card(
  168. color: Colors.white,
  169. surfaceTintColor: Colors.white,
  170. margin: const EdgeInsets.fromLTRB(40, 50, 40, 100),
  171. child: Padding(
  172. padding: const EdgeInsets.all(20),
  173. child: Column(
  174. children: [
  175. Text('打点记录', style: textStyle),
  176. const SizedBox(height: 12),
  177. Expanded(
  178. child: CheckedCPRecord(
  179. data: data,
  180. ),
  181. ),
  182. // SizedBox(
  183. // child: CheckPointRecord(data: controller.checkedPointHistory),
  184. // ),
  185. FilledButton(
  186. onPressed: () => Get.back(), child: const Text('确定'))
  187. ],
  188. ),
  189. )),
  190. );
  191. }
  192. Widget getSmallTitle(String title){
  193. return Container(
  194. alignment: Alignment.center,
  195. padding: const EdgeInsets.only(left: 3, right: 3),
  196. decoration: const BoxDecoration(color: Colors.black),
  197. child: Text(title,
  198. style: const TextStyle(
  199. fontSize:11,
  200. color: Colors.white,
  201. fontWeight: FontWeight.w700))
  202. );
  203. }
  204. Future<bool> get isBrightnessMax async{
  205. final b = await ScreenBrightness().current;
  206. return b>=1;
  207. }
  208. void onButtonExit(InGameController controller) {
  209. Get.dialog(AppDialog(
  210. title: const Text('退出比赛'),
  211. content: const Text('是否强制结束?'),
  212. onConfirm: () async {
  213. controller.forceExit();
  214. },
  215. onCancel: () => Get.back(),
  216. onConfirmText: '是',
  217. onCancelText: '否',
  218. ));
  219. }