1043 add castling method option v2#1347
Conversation
|
Just for my understanding, why the v1 was closed? thanks :) |
|
Sure, I had attempted an implementation that modified dartchess and chessground which maybe was not the correct approach. I didn't have a great deal of time to look at it at that point so I just closed the PRs for hygeine. See here for reference lichess-org/dartchess#44 This change is limited to only the mobile app with no changes elsewhere. Not sure if this is the right approach still, happy to be told if you think there is an alternative way to come at it |
c97a375 to
b2a2c28
Compare
b2a2c28 to
c8348c0
Compare
|
I think this is ready to be looked at @veloce. Not sure what's going on with the tests but maybe an issue unrelated to this PR? |
|
A fix was pushed on the main branch. The tests need to be rerun manually. |
|
@Jimima can you rebase your branch on top of main so the tests pass? thank. |
|
@veloce done! |
veloce
left a comment
There was a problem hiding this comment.
Thanks for this. This is looking good but there are a couple of issues to address on top of the comments I've made:
- for now this settings applies only to online games, but it should also apply to puzzles, analysis, study, etc.
- the logic you added to game_controller.dart must be refactored so it can work everywhere.
- this is the time for a refactoring: we need a global
boardwrapper so we can apply settings to the whole app - a good starting point for this refactoring imo, is the private _BoardWidget which should be extracted to a public widget in another file. It should be modified to take only
BoardPrefsandBoardSettingsOverride(and not directly theChessboardSettingsfrom chessground which should be constructed inside the widget from the prefs and the optional override). - the new castling logic should be tested
|
|
||
| // TODO: l10n | ||
| String get label => switch (this) { | ||
| CastlingMethod.kingOverRook => 'Move king over rook', |
There was a problem hiding this comment.
translation keys already exist: look at app_en.arb: preferencesCastleByMovingOntoTheRook.
| PieceShiftMethod.tapTwoSquares => 'Tap two squares', | ||
| }; | ||
|
|
||
| String castlingMethodl10n(BuildContext context, CastlingMethod castlingMethod) => |
There was a problem hiding this comment.
Duplicated l10n logic; must be defined directly in the enum to be consistent with rest of code.
|
Thanks for the feedback, that all makes sense. I also wonder if we are worried about premoves respecting the preference as right now they do not. I think the main site does not either but I would need to check this. |
|
@veloce I would appreciate another review if possible, I have made a few changes: Created a new BoardWidget component and use this in place of Chessboard where possible Some questions: I wonder if we can support either castling method in the app as it seems like an improvement over the web site. I have left it in for now but can easily remove it if you prefer. Right now I kept the refactoring light and boardPrefs is passed in as a parameter. Should the board widget be fetching the boardPrefs directly from the shared state rather than taking it as a parameter? Is there further refactoring to be done? You mentioned taking only BoardPrefs and BoardSettingsOverride but I was a bit unsure about how to make this work. Any further guidance would be gratefully received 🙂 |
|
Oh yes, also I will add some tests in the meantime |
…ethod-option-v2' into 1043-add-castling-method-option-v2
|
@veloce I had a go at the tests. I can check that clicking on the king highlights the relevant squares as valid moves. I wanted to also test that you could/could not perform a castling move in line with the selected preference. I tried (for way too long) to find a way to make this work but couldn't really figure it out. I think I need to learn a bit more about how everything fits together regarding riverpod, testing, mocking, overrides etc. If you have any guidance here I would appreciate it. In the process I wondered it in any case the widget should be using the shared state directly rather than being passed in. I think this would simplify mocking the state in the tests but I'm not really sure. Would really appreciate any guidance you can give me on how to progress this. I also appreciate you are likely very busy so don't feel you need to prioritise responding to me! |
|
Will look at it asap @Jimima |
| required ClockPosition clockPosition, | ||
| @JsonKey(defaultValue: PieceShiftMethod.either, unknownEnumValue: PieceShiftMethod.either) | ||
| required PieceShiftMethod pieceShiftMethod, | ||
| required CastlingMethod castlingMethod, |
There was a problem hiding this comment.
It is required to add a
@JsonKey(defaultValue: CastlingMethod.either, unknownEnumValue: CastlingMethod.either)otherwise json parsing will fail for people who already save settings.
| kingTwoSquares, | ||
| either; | ||
|
|
||
| String castlingMethodl10n(BuildContext context, CastlingMethod castlingMethod) => |
There was a problem hiding this comment.
The preferred way is:
String l10n(AppLocalizations l10n) => switch (this) {
CastlingMethod.kingOverRook => l10n.preferencesCastleByMovingOntoTheRook,
CastlingMethod.kingTwoSquares => l10n.preferencesCastleByMovingTwoSquares,
CastlingMethod.either => 'Either', //TODO l10n string
}We don't want to pass BuildContext and other enums in the app have the same method named l10n
| settingsLabel: Text( | ||
| context.l10n.preferencesCastleByMovingTheKingTwoSquaresOrOntoTheRook, | ||
| ), | ||
| settingsValue: boardPrefs.castlingMethod.name, |
There was a problem hiding this comment.
You should use the l10n method of the CastlingMethod enum instead.
| return buildScreenRoute( | ||
| context, | ||
| screen: const CastlingMethodSettingsScreen(), | ||
| title: 'Castling method', |
There was a problem hiding this comment.
Use the translated string: preferencesCastleByMovingTheKingTwoSquaresOrOntoTheRook
| validMoves: makeLegalMoves(pos), | ||
| promotionMove: null, | ||
| onMove: (NormalMove move, {bool? isDrop}) { | ||
| //This doesn't work because the position is not updated in the UI |
There was a problem hiding this comment.
For this to work it would need to be part of a StatefulWidget and be called inside setState.
Ideally we'd want to have an higher level test on a whole screen, and that would solve this. This is preferable because if we refactor and remove the InteractiveBoardWidget, the tests for the whole screen will still work and be relevant.
You could for instance test this on the AnalysisScreen, because it is easy to build a test screen with a PGN that gives you a position ready to castle.
You could add a
group('respect castling preferences', () {
// add your tests here
});I can take care of the GameScreen tests if you want, since it's a little bit harder to setup (need to mock websocket response). There are already some examples on how to do this though.
|
Thanks for the review, really helpful comments. I will take a look 👍🏻 |
9c3ed18 to
a87e7a0
Compare
|
@veloce I made the requested changes and started to implement the tests on the Analysis screen. I couldn't figure out how to override the preferences, however. I am really not very familiar with this side of things (testing/provider/mocks etc.) so if you can point me in the right direction I would appreciate it. I was trying various things and not really getting very far so thought I would ask to save my sanity, hope you don't mind! |
|
Oh and I don't really know why the checks are failing either 👎🏻 |
|
@Jimima to override the preferences you have the defaultPreferences parameter of the helper function Here is an example of its usage for the engine test: |
|
@veloce added tests on the Analysis screen, please feel free to review when able. |
|
|
||
| group('Respect castling preference', () { | ||
| testWidgets('Castle kingside - king over rook', (tester) async { | ||
| final castlingMethodVariantUnderTest = castlingMethodVariant.currentValue!; |
There was a problem hiding this comment.
Test variants are already used to test the different platforms (android, iOS). So here I'd rather use a for loop:
for (final variant in CastlingMethod.values) {
testWidgets('Castle kingside - king over rook with pref: $variant', (tester) async {
...
}
}|
Sorry @Jimima I had to refactor, as I didn't want to parse the fen a second time for nothing in I realise this PR was much harder to do than it was supposed to, because the castling option was not planned from the beginning. |
|
That's cool, I was struggling to find the time to work on it in any case! I'll review what you did just for my learning, thanks |
Adds an option to change castling method. Still needs some work to tidy up but the approach is implemented. Note that it only really works for Standard variants as chess960 always uses king over rook. I think this is okay but maybe the UI could make this clearer.