From c88e3fd60a81c483f266b89bbe689fe384c7d747 Mon Sep 17 00:00:00 2001 From: Calcitem Date: Sun, 16 May 2021 21:06:04 +0800 Subject: [PATCH] flutter: Support standard notation --- src/ui/flutter_app/lib/common/config.dart | 4 ++ src/ui/flutter_app/lib/l10n/intl_en.arb | 4 ++ src/ui/flutter_app/lib/l10n/intl_zh.arb | 1 + src/ui/flutter_app/lib/mill/recorder.dart | 34 ++++++++++-- src/ui/flutter_app/lib/mill/types.dart | 52 ++++++++++++++++++- .../lib/widgets/game_settings_page.dart | 10 ++++ .../personalization_settings_page.dart | 17 ++++++ 7 files changed, 118 insertions(+), 4 deletions(-) diff --git a/src/ui/flutter_app/lib/common/config.dart b/src/ui/flutter_app/lib/common/config.dart index ae515c33..0be0b964 100644 --- a/src/ui/flutter_app/lib/common/config.dart +++ b/src/ui/flutter_app/lib/common/config.dart @@ -40,6 +40,7 @@ class Config { static bool developerMode = false; // Display + static bool standardNotationEnabled = true; static bool isPieceCountInHandShown = false; static double boardBorderLineWidth = 2.0; static double boardInnerLineWidth = 2.0; @@ -86,6 +87,8 @@ class Config { Config.developerMode = settings['DeveloperMode'] ?? false; // Display + Config.standardNotationEnabled = + settings['StandardNotationEnabled'] ?? true; Config.isPieceCountInHandShown = settings['IsPieceCountInHandShown'] ?? false; Config.boardBorderLineWidth = settings['BoardBorderLineWidth'] ?? 2; @@ -151,6 +154,7 @@ class Config { settings['DeveloperMode'] = Config.developerMode; // Display + settings['StandardNotationEnabled'] = Config.standardNotationEnabled; settings['IsPieceCountInHandShown'] = Config.isPieceCountInHandShown; settings['BoardBorderLineWidth'] = Config.boardBorderLineWidth; settings['BoardInnerLineWidth'] = Config.boardInnerLineWidth; diff --git a/src/ui/flutter_app/lib/l10n/intl_en.arb b/src/ui/flutter_app/lib/l10n/intl_en.arb index ad17b484..33f3789b 100644 --- a/src/ui/flutter_app/lib/l10n/intl_en.arb +++ b/src/ui/flutter_app/lib/l10n/intl_en.arb @@ -596,6 +596,10 @@ "@boardInnerLineWidth": { "description": "Board inner line width" }, + "standardNotation": "Standard notation", + "@standardNotation": { + "description": "Standard notation" + }, "restore": "Restore", "@restore": { "description": "Restore" diff --git a/src/ui/flutter_app/lib/l10n/intl_zh.arb b/src/ui/flutter_app/lib/l10n/intl_zh.arb index b999b472..38884cf2 100644 --- a/src/ui/flutter_app/lib/l10n/intl_zh.arb +++ b/src/ui/flutter_app/lib/l10n/intl_zh.arb @@ -149,6 +149,7 @@ "display": "显示", "boardBorderLineWidth": "棋盘外框线宽", "boardInnerLineWidth": "棋盘内部线宽", + "standardNotation": "标准棋谱格式", "restore": "重置", "restoreDefaultSettings": "恢复默认设置", "exitApp": "App 将退出。", diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index ee1416c1..d75866b4 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -16,6 +16,8 @@ along with this program. If not, see . */ +import 'package:sanmill/common/config.dart'; + import 'position.dart'; import 'types.dart'; @@ -91,12 +93,38 @@ class GameRecorder { } String buildMoveHistoryText({cols = 2}) { - // var moveHistoryText = ''; + int k = 1; + String num = ""; for (var i = 0; i < _history.length; i++) { - moveHistoryText += '${i < 9 ? ' ' : ''}${i + 1}. ${_history[i].move} '; - if ((i + 1) % cols == 0) moveHistoryText += '\n'; + if (Config.standardNotationEnabled) { + if (k % cols == 1) { + num = "${(k + 1) ~/ 2}. "; + if (k < 9 * cols) { + num = " " + num + " "; + } + } else { + num = ""; + } + if (i + 1 < _history.length && + _history[i + 1].type == MoveType.remove) { + moveHistoryText += + '$num${_history[i].notation}${_history[i + 1].notation} '; + i++; + } else { + moveHistoryText += '$num${_history[i].notation} '; + } + k++; + } else { + moveHistoryText += '${i < 9 ? ' ' : ''}${i + 1}. ${_history[i].move} '; + } + + if (Config.standardNotationEnabled) { + if ((k + 1) % cols == 0) moveHistoryText += '\n'; + } else { + if ((i + 1) % cols == 0) moveHistoryText += '\n'; + } } if (moveHistoryText.isEmpty) { diff --git a/src/ui/flutter_app/lib/mill/types.dart b/src/ui/flutter_app/lib/mill/types.dart index 83ae8765..703d863f 100644 --- a/src/ui/flutter_app/lib/mill/types.dart +++ b/src/ui/flutter_app/lib/mill/types.dart @@ -40,6 +40,9 @@ class Move { // 'move' is the UCI engine's move-string String? move = ""; + // "notation" is Standard Notation + String? notation = ""; + MoveType type = MoveType.none; // Used to restore fen step counter when undoing move @@ -55,6 +58,8 @@ class Move { from = fromFile = fromRank = fromIndex = invalidMove; toFile = int.parse(move![2]); toRank = int.parse(move![4]); + to = makeSquare(toFile, toRank); + notation = "x${squareToNotation[to]}"; //captured = Piece.noPiece; } else if (move!.length == "(1,2)->(3,4)".length) { type = MoveType.move; @@ -64,12 +69,16 @@ class Move { fromIndex = squareToIndex[from] ?? invalidMove; toFile = int.parse(move![8]); toRank = int.parse(move![10]); + to = makeSquare(toFile, toRank); + notation = "${squareToNotation[from]}-${squareToNotation[to]}"; removed = Piece.noPiece; } else if (move!.length == "(1,2)".length) { type = MoveType.place; from = fromFile = fromRank = fromIndex = invalidMove; toFile = int.parse(move![1]); toRank = int.parse(move![3]); + to = makeSquare(toFile, toRank); + notation = "${squareToNotation[to]}"; removed = Piece.noPiece; } else if (move == "draw") { // TODO @@ -78,7 +87,6 @@ class Move { assert(false); } - to = makeSquare(toFile, toRank); toIndex = squareToIndex[to] ?? invalidMove; } @@ -315,6 +323,48 @@ Map squareToIndex = { 31: 0 }; +/* + a b c d e f g + 7 X --- X --- X 7 + |\ | /| + 6 | X - X - X | 6 + | |\ | /| | + 5 | | X-X-X | | 5 + 4 X-X-X X-X-X 4 + 3 | | X-X-X | | 3 + | |/ | \| | + 2 | X - X - X | 2 + |/ | \| + 1 X --- X --- X 1 + a b c d e f g + */ +Map squareToNotation = { + 8: "d5", + 9: "e5", + 10: "e4", + 11: "e3", + 12: "d3", + 13: "c3", + 14: "c4", + 15: "c5", + 16: "d6", + 17: "f6", + 18: "f4", + 19: "f2", + 20: "d2", + 21: "b2", + 22: "b4", + 23: "b6", + 24: "d7", + 25: "g7", + 26: "g4", + 27: "g1", + 28: "d1", + 29: "a1", + 30: "a4", + 31: "a7" +}; + Map indexToSquare = squareToIndex.map((k, v) => MapEntry(v, k)); enum GameResult { pending, win, lose, draw, none } diff --git a/src/ui/flutter_app/lib/widgets/game_settings_page.dart b/src/ui/flutter_app/lib/widgets/game_settings_page.dart index ab05587a..a5bf1b7f 100644 --- a/src/ui/flutter_app/lib/widgets/game_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_settings_page.dart @@ -498,4 +498,14 @@ class _GameSettingsPageState extends State { Config.save(); } + + setStandardNotationEnabled(bool value) async { + setState(() { + Config.standardNotationEnabled = value; + }); + + print("[config] standardNotationEnabled: $value"); + + Config.save(); + } } diff --git a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart index 968021df..15e989e8 100644 --- a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart @@ -249,6 +249,13 @@ class _PersonalizationSettingsPageState titleString: S.of(context).boardTop, onTap: setBoardTop, ), + ListItemDivider(), + SettingsSwitchListTile( + context: context, + value: Config.standardNotationEnabled, + onChanged: setStandardNotationEnabled, + titleString: S.of(context).standardNotation, + ), ], ), SizedBox(height: AppTheme.sizedBoxHeight), @@ -304,4 +311,14 @@ class _PersonalizationSettingsPageState Config.save(); } + + setStandardNotationEnabled(bool value) async { + setState(() { + Config.standardNotationEnabled = value; + }); + + print("[config] standardNotationEnabled: $value"); + + Config.save(); + } }