From 061c8b757158fe1d2fdb49a0383f30b4aefa4583 Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Fri, 31 Jan 2025 16:38:25 +0100 Subject: [PATCH 1/9] wip: poc implementation --- assets/endgames.json | 697 ++++++++++++++++++ assets/positions.json | 688 +++++++++++++++++ lib/src/model/board_editor/position.dart | 15 + .../view/board_editor/board_editor_menu.dart | 171 ++++- pubspec.yaml | 2 + 5 files changed, 1572 insertions(+), 1 deletion(-) create mode 100644 assets/endgames.json create mode 100644 assets/positions.json create mode 100644 lib/src/model/board_editor/position.dart diff --git a/assets/endgames.json b/assets/endgames.json new file mode 100644 index 0000000000..05c54e3109 --- /dev/null +++ b/assets/endgames.json @@ -0,0 +1,697 @@ +[{ + "eco": "0", + "fen": "8/8/8/3k4/8/8/8/5RQK w - - 0 1", + "name": "Mate Queen and Rook" +}, { + "eco": "1", + "fen": "8/8/8/8/8/4k3/6R1/6RK w - - 0 1", + "name": "Mate Two Rooks" +}, { + "eco": "2", + "fen": "8/8/5Q2/2k5/4K3/8/8/8 w - - 0 1", + "name": "Mate Queen I" +}, { + "eco": "3", + "fen": "8/8/8/3k4/8/8/8/6QK w - - 0 1", + "name": "Mate Queen II" +}, { + "eco": "4", + "fen": "3k4/R7/8/4K3/8/8/8/8 w - - 0 1", + "name": "Mate Rook I" +}, { + "eco": "5", + "fen": "8/8/8/8/4k3/8/8/6RK w - - 0 1", + "name": "Mate Rook II" +}, { + "eco": "6", + "fen": "8/8/3B4/6K1/8/8/2k5/q7 b - - 0 1", + "name": "Queen vs Bishop" +}, { + "eco": "7", + "fen": "8/8/8/3nk3/8/3Q4/8/7K w - - 0 1", + "name": "Queen vs Knight" +}, { + "eco": "8", + "fen": "8/3k4/3P4/3K4/8/8/8/8 b - - 0 1", + "name": "Pawn Ending I" +}, { + "eco": "9", + "fen": "8/3k4/3P4/3K4/8/8/8/8 w - - 0 1", + "name": "Pawn Ending II" +}, { + "eco": "10", + "fen": "6k1/8/8/8/8/8/P7/7K w - - 0 1", + "name": "Pawn Ending III" +}, { + "eco": "11", + "fen": "8/4k3/2K5/8/8/8/1P6/8 w - - 0 1", + "name": "Pawn Ending IV" +}, { + "eco": "12", + "fen": "5k2/8/4K3/5P2/8/8/8/8 w - - 0 1", + "name": "Pawn Ending V" +}, { + "eco": "13", + "fen": "5k2/8/5K2/5P2/8/8/8/8 w - - 0 1", + "name": "Pawn Ending VI" +}, { + "eco": "14", + "fen": "5k2/8/4K3/5P2/8/8/8/8 b - - 0 1", + "name": "Pawn Ending VII" +}, { + "eco": "15", + "fen": "5k2/8/5K2/5P2/8/8/8/8 b - - 0 1", + "name": "Pawn Ending VIII" +}, { + "eco": "16", + "fen": "7k/5K2/8/6P1/8/8/8/8 w - - 0 1", + "name": "Pawn Ending IX" +}, { + "eco": "17", + "fen": "5k2/8/8/8/3PK3/8/8/8 w - - 0 1", + "name": "Pawn Ending X" +}, { + "eco": "18", + "fen": "5k2/8/8/8/3PK3/8/8/8 b - - 0 1", + "name": "Pawn Ending XI" +}, { + "eco": "19", + "fen": "8/6k1/8/6K1/8/6P1/8/8 w - - 0 1", + "name": "Pawn Ending XII" +}, { + "eco": "20", + "fen": "1k6/8/PK6/8/8/8/8/8 b - - 0 1", + "name": "Pawn Ending XIII" +}, { + "eco": "21", + "fen": "8/4k3/6K1/8/7P/8/8/8 b - - 0 1", + "name": "Pawn Ending XIV" +}, { + "eco": "22", + "fen": "8/K7/8/8/8/1k6/1N1p4/8 w - - 0 1", + "name": "Knight vs Pawn I" +}, { + "eco": "23", + "fen": "8/8/8/8/5N2/8/2p4K/2k5 w - - 0 1", + "name": "Knight vs Pawn II" +}, { + "eco": "24", + "fen": "8/8/8/8/4N3/1p6/7K/1k6 b - - 0 1", + "name": "Knight vs Pawn III" +}, { + "eco": "25", + "fen": "8/8/K7/4N3/8/7p/7k/8 w - - 0 1", + "name": "Knight vs Pawn IV" +}, { + "eco": "26", + "fen": "K7/8/8/5N2/8/3k3p/8/8 w - - 0 1", + "name": "Knight vs Pawn V" +}, { + "eco": "27", + "fen": "8/2K5/8/8/4N3/2k5/7p/8 b - - 0 1", + "name": "Knight vs Pawn VI" +}, { + "eco": "28", + "fen": "8/8/8/8/8/p7/2K1N3/k7 w - - 0 1", + "name": "Knight vs Pawn VII" +}, { + "eco": "29", + "fen": "8/k7/8/8/7p/8/6N1/4K3 b - - 0 1", + "name": "Knight vs Pawn VIII" +}, { + "eco": "30", + "fen": "8/8/8/5PK1/8/k7/8/3r4 b - - 0 1", + "name": "Rook vs Pawn I" +}, { + "eco": "31", + "fen": "8/8/8/5PK1/8/k7/8/3r4 w - - 0 1", + "name": "Rook vs Pawn II" +}, { + "eco": "32", + "fen": "7r/8/8/2KP4/8/8/2k5/8 b - - 0 1", + "name": "Rook vs Pawn III" +}, { + "eco": "33", + "fen": "8/8/8/8/7P/6K1/1r6/k7 b - - 0 1", + "name": "Rook vs Pawn IV" +}, { + "eco": "34", + "fen": "8/8/8/5KP1/8/5k2/8/r7 b - - 0 1", + "name": "Rook vs Pawn IV" +}, { + "eco": "35", + "fen": "8/8/8/8/4KP2/8/r3k3/8 b - - 0 1", + "name": "Rook vs Pawn X" +}, { + "eco": "36", + "fen": "8/8/8/8/4KP2/8/r3k3/8 w - - 0 1", + "name": "Rook vs Pawn XI" +}, { + "eco": "37", + "fen": "4r3/8/8/3KP3/k7/8/8/8 b - - 0 1", + "name": "Rook vs Pawn XII" +}, { + "eco": "38", + "fen": "8/2K5/8/1P3k2/8/8/8/7r b - - 0 1", + "name": "Rook vs Pawn XIII" +}, { + "eco": "39", + "fen": "7r/2K5/k7/3P4/8/8/8/8 b - - 0 1", + "name": "Rook vs Pawn XIV" +}, { + "eco": "40", + "fen": "8/8/8/3r4/2KP4/8/2k5/8 b - - 0 1", + "name": "Rook vs Pawn XV" +}, { + "eco": "41", + "fen": "8/8/5K2/8/6P1/8/3r4/4k3 b - - 0 1", + "name": "Rook vs Pawn XVI" +}, { + "eco": "42", + "fen": "8/8/8/6KP/8/6k1/8/r7 b - - 0 1", + "name": "Rook vs Pawn XVII" +}, { + "eco": "43", + "fen": "8/4k1KP/8/8/8/8/8/r7 b - - 0 1", + "name": "Rook vs Pawn XVIII" +}, { + "eco": "44", + "fen": "8/8/4k1KP/8/8/8/8/r7 w - - 0 1", + "name": "Rook vs Pawn XIX" +}, { + "eco": "45", + "fen": "8/8/4k1KP/8/8/8/8/r7 b - - 0 1", + "name": "Rook vs Pawn XX" +}, { + "eco": "46", + "fen": "8/2P2k2/3K4/5r2/8/8/8/8 b - - 0 1", + "name": "Rook vs Pawn XXI" +}, { + "eco": "47", + "fen": "8/8/3k3p/3P3P/2K5/8/8/8 w - - 0 1", + "name": "Pawns Ending I" +}, { + "eco": "48", + "fen": "8/8/8/1k5p/7P/1PK5/8/8 w - - 0 1", + "name": "Pawns Ending II" +}, { + "eco": "49", + "fen": "8/8/p7/P7/3k4/3P4/3K4/8 w - - 0 1", + "name": "Pawns Ending III" +}, { + "eco": "50", + "fen": "8/8/8/p7/P7/3k4/3P4/3K4 w - - 0 1", + "name": "Pawns Ending IV" +}, { + "eco": "51", + "fen": "k7/8/2P5/K7/8/8/8/8 w - - 0 1", + "name": "Pawn Ending XV" +}, { + "eco": "52", + "fen": "8/6k1/4P3/6K1/8/8/8/8 w - - 0 1", + "name": "Pawn Ending XVI" +}, { + "eco": "53", + "fen": "k7/8/1PK5/8/8/8/8/8 w - - 0 1", + "name": "Pawn Ending XVII" +}, { + "eco": "54", + "fen": "8/1PK5/8/8/8/4q3/8/1k6 b - - 0 1", + "name": "Queen vs Pawn I" +}, { + "eco": "55", + "fen": "8/3PK3/8/8/8/8/4k3/5q2 b - - 0 1", + "name": "Queen vs Pawn II" +}, { + "eco": "56", + "fen": "8/5K1P/8/8/3q4/8/8/2k5 w - - 0 1", + "name": "Queen vs Pawn III" +}, { + "eco": "57", + "fen": "8/6KP/8/4k3/3q4/8/8/8 b - - 0 1", + "name": "Queen vs Pawn IV" +}, { + "eco": "58", + "fen": "8/5P2/3K4/8/8/1k6/8/q7 w - - 0 1", + "name": "Queen vs Pawn V" +}, { + "eco": "59", + "fen": "8/5PK1/8/6k1/8/8/q7/8 b - - 0 1", + "name": "Queen vs Pawn VI" +}, { + "eco": "60", + "fen": "8/4KP2/8/8/6k1/8/q7/8 b - - 0 1", + "name": "Queen vs Pawn VII" +}, { + "eco": "61", + "fen": "8/4KP2/8/1k6/8/8/q7/8 b - - 0 1", + "name": "Queen vs Pawn VIII" +}, { + "eco": "62", + "fen": "8/8/8/8/8/k2K4/2Q5/q7 w - - 0 1", + "name": "Queen vs Pawn IX" +}, { + "eco": "63", + "fen": "8/8/P7/1P5k/8/8/7K/5r2 w - - 0 1", + "name": "Rook vs 2 Pawns I" +}, { + "eco": "64", + "fen": "8/8/P7/1P5k/8/8/7K/6r1 b - - 0 1", + "name": "Rook vs 2 Pawns II" +}, { + "eco": "65", + "fen": "6r1/8/P7/1P5k/8/8/7K/8 w - - 0 1", + "name": "Rook vs 2 Pawns III" +}, { + "eco": "66", + "fen": "6r1/8/P7/1P5k/8/8/7K/8 b - - 0 1", + "name": "Rook vs 2 Pawns IV" +}, { + "eco": "67", + "fen": "r3k3/8/3PP3/3K4/8/8/8/8 w - - 0 1", + "name": "Rook vs 2 Pawns V" +}, { + "eco": "68", + "fen": "r7/2kPK3/4P3/8/8/8/8/8 b - - 0 1", + "name": "Rook vs 2 Pawns VI" +}, { + "eco": "69", + "fen": "r7/3kPK2/5P2/8/8/8/8/8 b - - 0 1", + "name": "Rook vs 2 Pawns VII" +}, { + "eco": "70", + "fen": "r7/4kPK1/6P1/8/8/8/8/8 b - - 0 1", + "name": "Rook vs 2 Pawns VIII" +}, { + "eco": "71", + "fen": "r7/5kPK/7P/8/8/8/8/8 b - - 0 1", + "name": "Rook vs 2 Pawns IX" +}, { + "eco": "72", + "fen": "8/8/5KP1/5P2/8/2k4r/8/8 b - - 0 1", + "name": "Rook vs 2 Pawns X" +}, { + "eco": "73", + "fen": "8/8/8/1P6/PK6/8/r7/2k5 w - - 0 1", + "name": "Rook vs 2 Pawns XI" +}, { + "eco": "74", + "fen": "4k3/R7/8/3KP3/8/6r1/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook I" +}, { + "eco": "75", + "fen": "3K4/3P1k2/8/8/8/8/7r/4R3 b - - 0 1", + "name": "Rook + Pawn vs Rook II - Lucena" +}, { + "eco": "76", + "fen": "4K3/4P1k1/8/8/8/8/r7/5R2 b - - 0 1", + "name": "Rook + Pawn vs Rook III" +}, { + "eco": "77", + "fen": "1k6/7R/8/KP6/8/8/8/2r5 w - - 0 1", + "name": "Rook + Pawn vs Rook IV" +}, { + "eco": "78", + "fen": "4k3/7R/8/3KPr2/8/8/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook V - Philidor" +}, { + "eco": "79", + "fen": "r7/3RK1k1/4P3/8/8/8/8/8 w - - 0 1", + "name": "Rook + Pawn vs Rook VI" +}, { + "eco": "80", + "fen": "1r6/R3K1k1/4P3/8/8/8/8/8 w - - 0 1", + "name": "Rook + Pawn vs Rook VII" +}, { + "eco": "81", + "fen": "7r/8/4k3/8/2P5/2K5/8/3R4 b - - 0 1", + "name": "Rook + Pawn vs Rook VIII" +}, { + "eco": "82", + "fen": "2r5/8/5k2/8/2P5/2K5/8/4R3 w - - 0 1", + "name": "Rook + Pawn vs Rook IX" +}, { + "eco": "83", + "fen": "3r4/8/k7/8/3P4/3K4/8/1R6 w - - 0 1", + "name": "Rook + Pawn vs Rook X" +}, { + "eco": "84", + "fen": "1r6/8/8/2R5/1P1k4/1K6/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook XI" +}, { + "eco": "85", + "fen": "2r5/8/8/3R4/2P1k3/2K5/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook XII" +}, { + "eco": "86", + "fen": "3r4/8/8/8/7R/3P1k2/3K4/8 b - - 0 1", + "name": "Rook + Pawn vs Rook XIII" +}, { + "eco": "87", + "fen": "2r5/8/7R/4k3/2P5/2K5/8/8 w - - 0 1", + "name": "Rook + Pawn vs Rook XIV" +}, { + "eco": "88", + "fen": "2r5/8/7R/4k3/2P5/2K5/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook XV" +}, { + "eco": "89", + "fen": "4r3/8/8/5R2/4P1k1/4K3/8/8 b - - 0 1", + "name": "Rook + Pawn vs Rook XVI" +}, { + "eco": "90", + "fen": "8/1k6/8/1P6/1P6/1K6/8/8 w - - 0 1", + "name": "Pawns Ending I" +}, { + "eco": "91", + "fen": "1k6/8/1P6/1P6/1K6/8/8/8 w - - 0 1", + "name": "Pawns Ending II" +}, { + "eco": "92", + "fen": "7k/R7/7K/8/8/1b6/8/8 w - - 0 1", + "name": "Rook vs Bishop I" +}, { + "eco": "93", + "fen": "6k1/5R2/6K1/8/8/8/8/6b1 w - - 0 1", + "name": "Rook vs Bishop II" +}, { + "eco": "94", + "fen": "8/8/8/8/8/3k4/r7/3NK3 w - - 0 1", + "name": "Rook vs Knight I" +}, { + "eco": "95", + "fen": "8/8/8/8/8/6k1/r7/6NK w - - 0 1", + "name": "Rook vs Knight II" +}, { + "eco": "96", + "fen": "8/8/8/8/8/6k1/r7/6KN b - - 0 1", + "name": "Rook vs Knight III" +}, { + "eco": "97", + "fen": "3k4/1K6/2PbP3/3B4/8/8/8/8 w - - 0 1", + "name": "Opposite Color Bishops I" +}, { + "eco": "98", + "fen": "8/2bB4/2P5/6k1/4K3/5P2/8/8 w - - 0 1", + "name": "Opposite Color Bishops II" +}, { + "eco": "99", + "fen": "8/2kB4/2P5/6b1/4K3/5P2/8/8 w - - 0 1", + "name": "Opposite Color Bishops III" +}, { + "eco": "100", + "fen": "2k5/8/3P1K2/2B3P1/2b5/8/8/8 b - - 0 1", + "name": "Opposite Color Bishops IV" +}, { + "eco": "101", + "fen": "8/3k4/3B1K2/4P3/1Pb5/8/8/8 b - - 0 1", + "name": "Opposite Color Bishops V" +}, { + "eco": "102", + "fen": "8/bB6/P2k4/3P4/4K3/8/8/8 w - - 0 1", + "name": "Opposite Color Bishops VI" +}, { + "eco": "103", + "fen": "1b6/1P6/4Bk2/5P2/4K3/8/8/8 w - - 0 1", + "name": "Opposite Color Bishops VII" +}, { + "eco": "104", + "fen": "2b5/8/1P1B4/8/4kP2/8/5K2/8 b - - 0 1", + "name": "Opposite Color Bishops VIII" +}, { + "eco": "105", + "fen": "8/8/8/2Bk4/1P3Pb1/4K3/8/8 w - - 0 1", + "name": "Opposite Color Bishops IX" +}, { + "eco": "106", + "fen": "8/b7/P7/3Bk3/2K1P3/8/8/8 w - - 0 1", + "name": "Opposite Color Bishops X" +}, { + "eco": "107", + "fen": "8/8/8/5k2/5P1P/8/8/K7 w - - 0 1", + "name": "Pawns Ending III" +}, { + "eco": "108", + "fen": "8/8/2k5/8/P2P4/8/8/7K b - - 0 1", + "name": "Pawns Ending IV" +}, { + "eco": "109", + "fen": "8/8/8/8/4k3/8/6K1/6BN w - - 0 1", + "name": "Mate Bishop + Knight" +}, { + "eco": "110", + "fen": "K7/5B2/7B/8/4k3/8/8/8 w - - 0 1", + "name": "Mate Two Bishops" +}, { + "eco": "111", + "fen": "R7/P4k2/8/8/8/8/6K1/r7 b - - 0 1", + "name": "Rook + Pawn vs Rook XVII" +}, { + "eco": "112", + "fen": "R7/5k2/P7/8/8/8/6K1/r7 b - - 0 1", + "name": "Rook + Pawn vs Rook XVIII" +}, { + "eco": "113", + "fen": "4k3/8/4PP2/4K3/1b6/3B4/8/8 w - - 0 1", + "name": "Opposite Color Bishops XI" +}, { + "eco": "114", + "fen": "3bk3/8/4PP2/4K3/8/8/4B3/8 w - - 0 1", + "name": "Opposite Color Bishops XII" +}, { + "eco": "115", + "fen": "6k1/8/6PP/5K2/2B5/2b5/8/8 b - - 0 1", + "name": "Opposite Color Bishops XIII" +}, { + "eco": "116", + "fen": "8/4k3/8/4PP2/4K3/1b6/3B4/8 w - - 0 1", + "name": "Opposite Color Bishops XIV" +}, { + "eco": "117", + "fen": "2b5/4k3/8/4PP2/4K3/8/3B4/8 w - - 0 1", + "name": "Opposite Color Bishops XV" +}, { + "eco": "118", + "fen": "8/8/3k4/8/3PP3/4K3/8/4Bb2 b - - 0 1", + "name": "Opposite Color Bishops XVI" +}, { + "eco": "119", + "fen": "8/5kb1/8/8/6K1/3B4/4PP2/8 w - - 0 1", + "name": "Opposite Color Bishops XVII" +}, { + "eco": "120", + "fen": "k7/8/1p6/1P6/8/8/7K/8 w - - 0 1", + "name": "Pawns Ending V" +}, { + "eco": "121", + "fen": "8/2K5/4p3/4P3/6k1/8/8/8 w - - 0 1", + "name": "Pawns Ending VI" +}, { + "eco": "122", + "fen": "8/8/8/7k/3p2p1/3P4/6KP/8 b - - 0 1", + "name": "Pawns Ending VII" +}, { + "eco": "123", + "fen": "8/8/8/5p2/3k4/5P2/8/6K1 w - - 0 1", + "name": "Pawns Ending VIII" +}, { + "eco": "124", + "fen": "8/1p6/1P6/8/7K/8/8/1k6 w - - 0 1", + "name": "Pawns Ending IX" +}, { + "eco": "125", + "fen": "8/p4K2/P7/8/8/8/1k6/8 w - - 0 1", + "name": "Pawns Ending X" +}, { + "eco": "126", + "fen": "8/p4K2/P7/8/8/8/7k/8 w - - 0 1", + "name": "Pawns Ending XI" +}, { + "eco": "127", + "fen": "8/8/5p2/8/4P1k1/8/7K/8 w - - 0 1", + "name": "Pawns Ending XII" +}, { + "eco": "128", + "fen": "8/6p1/7k/8/1K6/8/1P6/8 w - - 0 1", + "name": "Pawns Ending XIII" +}, { + "eco": "129", + "fen": "7K/8/k1P5/7p/8/8/8/8 w - - 0 1", + "name": "Pawns Ending XIV" +}, { + "eco": "130", + "fen": "8/5p2/2k5/K7/8/1P6/8/8 b - - 0 1", + "name": "Pawns Ending XV" +}, { + "eco": "131", + "fen": "8/p7/P7/8/8/3k4/3P4/3K4 w - - 0 1", + "name": "Pawns Ending XVI" +}, { + "eco": "132", + "fen": "5k2/5P1p/4K3/8/8/8/7P/8 w - - 0 1", + "name": "Pawns Ending XVII" +}, { + "eco": "133", + "fen": "2k5/8/p1P5/P2K4/8/8/8/8 w - - 0 1", + "name": "Pawns Ending XVIII" +}, { + "eco": "134", + "fen": "K7/P4k2/8/8/8/8/4R3/1r6 w - - 0 1", + "name": "Rook vs Rook + h Pawn I" +}, { + "eco": "135", + "fen": "8/1K1k4/2R5/P7/8/8/8/7r w - - 0 1", + "name": "Rook vs Rook + h Pawn II" +}, { + "eco": "136", + "fen": "8/1K1k4/2R5/P7/8/8/8/7r b - - 0 1", + "name": "Rook vs Rook + h Pawn III" +}, { + "eco": "137", + "fen": "5k2/2K5/3P4/1b5B/8/8/8/8 w - - 0 1", + "name": "Same Color Bishops I" +}, { + "eco": "138", + "fen": "4B3/2K5/3P4/2k5/8/7b/8/8 w - - 0 1", + "name": "Same Color Bishops II" +}, { + "eco": "139", + "fen": "8/K7/1P6/k4B2/8/5b2/8/8 w - - 0 1", + "name": "Same Color Bishops III" +}, { + "eco": "140", + "fen": "5K2/5P2/3b1k1B/8/8/8/8/8 w - - 0 1", + "name": "Same Color Bishops IV" +}, { + "eco": "141", + "fen": "8/8/2k5/5PK1/8/2b5/7B/8 b - - 0 1", + "name": "Same Color Bishops VI" +}, { + "eco": "142", + "fen": "5k2/3b4/3P1K2/8/8/8/8/3B4 w - - 0 1", + "name": "Same Color Bishops VII" +}, { + "eco": "143", + "fen": "1K6/4B3/8/8/8/2n2p2/5k2/8 w - - 0 1", + "name": "Bishop vs Knight I" +}, { + "eco": "144", + "fen": "8/8/8/8/B6n/7p/6k1/4K3 w - - 0 1", + "name": "Bishop vs Knight II" +}, { + "eco": "145", + "fen": "8/8/5B2/8/1n6/8/p1k1K3/8 b - - 0 1", + "name": "Bishop vs Knight III" +}, { + "eco": "146", + "fen": "2K5/3Pkn2/8/8/8/5B2/8/8 w - - 0 1", + "name": "Bishop vs Knight IV" +}, { + "eco": "147", + "fen": "8/4K3/3P1n2/3k4/8/8/2B5/8 w - - 0 1", + "name": "Bishop vs Knight V" +}, { + "eco": "148", + "fen": "8/7p/5k2/8/5K2/8/6PP/8 b - - 0 1", + "name": "Pawns Ending XIX" +}, { + "eco": "149", + "fen": "8/7p/5k2/8/5K2/8/6PP/8 w - - 0 1", + "name": "Pawns Ending XX" +}, { + "eco": "150", + "fen": "8/7p/5k2/8/5K2/6P1/7P/8 w - - 0 1", + "name": "Pawns Ending XXI" +}, { + "eco": "151", + "fen": "8/7p/8/5k2/8/5K2/6PP/8 b - - 0 1", + "name": "Pawns Ending XXII" +}, { + "eco": "152", + "fen": "8/6k1/6P1/p2p3P/8/8/2K5/8 b - - 0 1", + "name": "Pawns Ending XXIII" +}, { + "eco": "153", + "fen": "8/6k1/6P1/p2p3P/8/8/2K5/8 w - - 0 1", + "name": "Pawns Ending XXIV" +}, { + "eco": "154", + "fen": "3k4/4r3/3K4/3B4/8/8/8/5R2 b - - 0 1", + "name": "Rook vs Rook + Bishop I" +}, { + "eco": "155", + "fen": "3k4/4r3/3K4/3B4/8/8/8/5R2 w - - 0 1", + "name": "Rook vs Rook + Bishop II" +}, { + "eco": "156", + "fen": "3k4/6R1/7r/2KP4/3P4/8/8/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns I" +}, { + "eco": "157", + "fen": "8/6p1/8/8/1R4pk/r7/6K1/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns II" +}, { + "eco": "158", + "fen": "6k1/1R6/5P1P/6K1/8/8/8/r7 b - - 0 1", + "name": "Rook vs Rook + 2 Pawns III" +}, { + "eco": "159", + "fen": "6k1/1R6/7P/5PK1/8/8/8/r7 b - - 0 1", + "name": "Rook vs Rook + 2 Pawns IV" +}, { + "eco": "160", + "fen": "8/6k1/R7/1r5P/5PK1/8/8/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns V" +}, { + "eco": "161", + "fen": "8/5k2/7P/6R1/5PK1/8/8/1r6 b - - 0 1", + "name": "Rook vs Rook + 2 Pawns VI" +}, { + "eco": "162", + "fen": "8/8/r5kP/6P1/1R3K2/8/8/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns VII" +}, { + "eco": "163", + "fen": "8/8/r4kP1/5P2/1R3K2/8/8/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns VIII" +}, { + "eco": "164", + "fen": "8/4r3/8/5K2/2Pk4/3P3R/8/8 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns IX" +}, { + "eco": "165", + "fen": "R7/P5k1/8/8/8/6P1/6K1/r7 w - - 0 1", + "name": "Rook vs Rook + 2 Pawns X" +}, { + "eco": "166", + "fen": "R7/6k1/8/8/P6P/6K1/8/4r3 b - - 0 1", + "name": "Rook vs Rook + 2 Pawns XI" +}, { + "eco": "167", + "fen": "8/7k/p3p1pP/6P1/8/2K5/8/8 w - - 0 1", + "name": "Pawns Ending XXV" +}, { + "eco": "168", + "fen": "8/7k/6pP/6P1/8/p1p5/8/1K6 b - - 0 1", + "name": "Pawns Ending XXVI" +}, { + "eco": "169", + "fen": "8/8/8/1p2kPp1/6P1/4K3/8/8 b - - 0 1", + "name": "Pawns Ending XXVII" +}, { + "eco": "170", + "fen": "8/8/8/p3kPp1/6P1/4K3/8/8 w - - 0 1", + "name": "Pawns Ending XXVIII" +}, { + "eco": "171", + "fen": "8/8/2p1kPp1/6P1/4K3/8/8/8 w - - 0 1", + "name": "Pawns Ending XXIX" +}, { + "eco": "172", + "fen": "8/8/3k4/1p2p3/1P2K3/8/7P/8 w - - 0 1", + "name": "Pawns Ending XXX" +}, { + "eco": "173", + "fen": "8/8/4r3/3k4/8/8/3K1Q2/8 w - - 0 1", + "name": "Queen vs Rook" +}] diff --git a/assets/positions.json b/assets/positions.json new file mode 100644 index 0000000000..dc5f7c7f7f --- /dev/null +++ b/assets/positions.json @@ -0,0 +1,688 @@ +[ + { + "name": "e4", + "positions": [ + { + "eco": "B00", + "fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 1 1", + "name": "King's Pawn" + }, + { + "eco": "B00", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2", + "name": "Open Game" + }, + { + "eco": "B02", + "fen": "rnbqkb1r/pppppppp/5n2/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 2 2", + "name": "Alekhine's Defence" + }, + { + "eco": "B04", + "fen": "rnbqkb1r/ppp1pppp/3p4/3nP3/3P4/5N2/PPP2PPP/RNBQKB1R b KQkq - 1 4", + "name": "Alekhine's Defence: Modern Variation" + }, + { + "eco": "C23", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/2B1P3/8/PPPP1PPP/RNBQK1NR b KQkq - 2 2", + "name": "Bishop's Opening" + }, + { + "eco": "B10", + "fen": "rnbqkbnr/pp1ppppp/2p5/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 1 2", + "name": "Caro-Kann Defence" + }, + { + "eco": "B12", + "fen": "rnbqkbnr/pp2pppp/2p5/3pP3/3P4/8/PPP2PPP/RNBQKBNR b KQkq - 1 3", + "name": "Caro-Kann Defence: Advance Variation" + }, + { + "eco": "B18", + "fen": "rn1qkbnr/pp2pppp/2p5/5b2/3PN3/8/PPP2PPP/R1BQKBNR w KQkq - 2 5", + "name": "Caro-Kann Defence: Classical Variation" + }, + { + "eco": "B13", + "fen": "rnbqkbnr/pp2pppp/2p5/3P4/3P4/8/PPP2PPP/RNBQKBNR b KQkq - 1 3", + "name": "Caro-Kann Defence: Exchange Variation" + }, + { + "eco": "B14", + "fen": "rnbqkb1r/pp3ppp/4pn2/3p4/2PP4/2N5/PP3PPP/R1BQKBNR w KQkq - 1 6", + "name": "Caro-Kann Defence: Panov-Botvinnik Attack" + }, + { + "eco": "B14", + "fen": "rnbqkb1r/pp3ppp/4pn2/3p4/2PP4/2N5/PP3PPP/R1BQKBNR w KQkq - 1 6", + "name": "Caro-Kann Defence: Steinitz Variation" + }, + { + "eco": "C21", + "fen": "rnbqkbnr/pppp1ppp/8/8/3pP3/2P5/PP3PPP/RNBQKBNR b KQkq - 1 3", + "name": "Danish Gambit" + }, + { + "eco": "C46", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/4p3/4P3/2N2N2/PPPP1PPP/R1BQKB1R w KQkq - 5 4", + "name": "Four Knights Game" + }, + { + "eco": "C47", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/4p3/3PP3/2N2N2/PPP2PPP/R1BQKB1R b KQkq d3 1 4", + "name": "Four Knights Game: Scotch Variation" + }, + { + "eco": "C48", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/2N2N2/PPPP1PPP/R1BQK2R b KQkq - 0 4", + "name": "Four Knights Game: Spanish Variation" + }, + { + "eco": "C00", + "fen": "rnbqkbnr/pppp1ppp/4p3/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 1 2", + "name": "French Defence" + }, + { + "eco": "C02", + "fen": "rnbqkbnr/ppp2ppp/4p3/3pP3/3P4/8/PPP2PPP/RNBQKBNR b KQkq - 1 3", + "name": "French Defence: Advance Variation" + }, + { + "eco": "C11", + "fen": "rnbqkb1r/ppp2ppp/4pn2/3p2B1/3PP3/2N5/PPP2PPP/R2QKBNR b KQkq - 1 4", + "name": "French Defence: Burn Variation" + }, + { + "eco": "C11", + "fen": "rnbqkb1r/ppp2ppp/4pn2/3p4/3PP3/2N5/PPP2PPP/R1BQKBNR w KQkq - 3 4", + "name": "French Defence: Classical Variation" + }, + { + "eco": "C01", + "fen": "rnbqkbnr/ppp2ppp/4p3/3P4/3P4/8/PPP2PPP/RNBQKBNR b KQkq - 1 3", + "name": "French Defence: Exchange Variation" + }, + { + "eco": "C10", + "fen": "rnbqkbnr/ppp2ppp/4p3/8/3Pp3/2N5/PPP2PPP/R1BQKBNR w KQkq - 1 4", + "name": "French Defence: Rubinstein Variation" + }, + { + "eco": "C03", + "fen": "rnbqkbnr/ppp2ppp/4p3/3p4/3PP3/8/PPPN1PPP/R1BQKBNR b KQkq - 2 3", + "name": "French Defence: Tarrasch Variation" + }, + { + "eco": "C15", + "fen": "rnbqk1nr/ppp2ppp/4p3/3p4/1b1PP3/2N5/PPP2PPP/R1BQKBNR w KQkq - 3 4", + "name": "French Defence: Winawer Variation" + }, + { + "eco": "C50", + "fen": "r1bqk1nr/pppp1ppp/2n5/2b1p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 5 4", + "name": "Giuoco Piano" + }, + { + "eco": "C50", + "fen": "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 4 3", + "name": "Italian Game" + }, + { + "eco": "C51", + "fen": "r1bqk1nr/pppp1ppp/2n5/2b1p3/1PB1P3/5N2/P1PP1PPP/RNBQK2R b KQkq b3 1 4", + "name": "Italian Game: Evans Gambit" + }, + { + "eco": "C50", + "fen": "r1bqk1nr/ppppbppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 5 4", + "name": "Italian Game: Hungarian Defence" + }, + { + "eco": "C55", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 5 4", + "name": "Italian Game: Two Knights Defence" + }, + { + "eco": "C30", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/4PP2/8/PPPP2PP/RNBQKBNR b KQkq f3 1 2", + "name": "King's Gambit" + }, + { + "eco": "C33", + "fen": "rnbqkbnr/pppp1ppp/8/8/4Pp2/8/PPPP2PP/RNBQKBNR w KQkq - 1 3", + "name": "King's Gambit Accepted" + }, + { + "eco": "C33", + "fen": "rnbqkbnr/pppp1ppp/8/8/2B1Pp2/8/PPPP2PP/RNBQK1NR b KQkq - 2 3", + "name": "King's Gambit Accepted: Bishop's Gambit" + }, + { + "eco": "C36", + "fen": "rnbqkbnr/ppp2ppp/8/3p4/4Pp2/5N2/PPPP2PP/RNBQKB1R w KQkq d6 1 4", + "name": "King's Gambit Accepted: Modern Defence" + }, + { + "eco": "C30", + "fen": "rnbqkbnr/pppp1p1p/8/6p1/4Pp2/5N2/PPPP2PP/RNBQKB1R w KQkq - 0 4", + "name": "King's Gambit Accepted: Classical Variation" + }, + { + "eco": "C30", + "fen": "rnbqk1nr/pppp1ppp/8/2b1p3/4PP2/8/PPPP2PP/RNBQKBNR w KQkq - 2 3", + "name": "King's Gambit Declined: Classical Variation" + }, + { + "eco": "C31", + "fen": "rnbqkbnr/ppp2ppp/8/3pp3/4PP2/8/PPPP2PP/RNBQKBNR w KQkq d6 1 3", + "name": "King's Gambit Declined: Falkbeer Countergambit" + }, + { + "eco": "B06", + "fen": "rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2", + "name": "Modern Defence" + }, + { + "eco": "B06", + "fen": "rnbqk1nr/ppppppbp/6p1/8/3PP3/2N5/PPP2PPP/R1BQKBNR b KQkq - 0 3", + "name": "Modern Defence: Robatsch Defence" + }, + { + "eco": "C41", + "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 1 3", + "name": "Philidor Defence" + }, + { + "eco": "B07", + "fen": "rnbqkb1r/ppp1pppp/3p1n2/8/3PP3/8/PPP2PPP/RNBQKBNR w KQkq - 2 3", + "name": "Pirc Defence" + }, + { + "eco": "B09", + "fen": "rnbqkb1r/ppp1pp1p/3p1np1/8/3PPP2/2N5/PPP3PP/R1BQKBNR b KQkq f3 1 4", + "name": "Pirc Defence: Austrian Attack" + }, + { + "eco": "B07", + "fen": "rnbqkb1r/ppp1pp1p/3p1np1/8/3PP3/2N2N2/PPP2PPP/R1BQKB1R b KQkq - 2 4", + "name": "Pirc Defence: Classical Variation" + }, + { + "eco": "C42", + "fen": "rnbqkb1r/pppp1ppp/5n2/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 3 3", + "name": "Petrov's Defence" + }, + { + "eco": "C42", + "fen": "rnbqkb1r/ppp2ppp/3p4/8/3Pn3/5N2/PPP2PPP/RNBQKB1R b KQkq d3 1 5", + "name": "Petrov's Defence: Classical Attack" + }, + { + "eco": "C43", + "fen": "rnbqkb1r/pppp1ppp/5n2/4p3/3PP3/5N2/PPP2PPP/RNBQKB1R b KQkq d3 1 3", + "name": "Petrov's Defence: Steinitz Attack" + }, + { + "eco": "C42", + "fen": "rnbqkb1r/pppp1ppp/5n2/4p3/4P3/2N2N2/PPPP1PPP/R1BQKB1R b KQkq - 4 3", + "name": "Petrov's Defence: Three Knights Game" + }, + { + "eco": "C60", + "fen": "r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 4 3", + "name": "Ruy Lopez" + }, + { + "eco": "C65", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 5 4", + "name": "Ruy Lopez: Berlin Defence" + }, + { + "eco": "C64", + "fen": "r1bqk1nr/pppp1ppp/2n5/1Bb1p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 5 4", + "name": "Ruy Lopez: Classical Variation" + }, + { + "eco": "C84", + "fen": "r1bqk2r/2ppbppp/p1n2n2/1p2p3/4P3/1B3N2/PPPP1PPP/RNBQR1K1 b kq - 0 7", + "name": "Ruy Lopez: Closed Variation" + }, + { + "eco": "C68", + "fen": "r1bqkbnr/1ppp1ppp/p1B5/4p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 1 4", + "name": "Ruy Lopez: Exchange Variation" + }, + { + "eco": "C89", + "fen": "r1bq1rk1/2p1bppp/p1n2n2/1p1pp3/4P3/1BP2N2/PP1P1PPP/RNBQR1K1 w - - 0 9", + "name": "Ruy Lopez: Marshall Attack" + }, + { + "eco": "C63", + "fen": "r1bqkbnr/pppp2pp/2n5/1B2pp2/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq f6 1 4", + "name": "Ruy Lopez: Schliemann Defence" + }, + { + "eco": "B01", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 1 2", + "name": "Scandinavian Defence" + }, + { + "eco": "B01", + "fen": "rnbqkb1r/ppp1pppp/5n2/3P4/3P4/8/PPP2PPP/RNBQKBNR b KQkq - 0 3", + "name": "Scandinavian Defence: Modern Variation" + }, + { + "eco": "C44", + "fen": "r1bqkbnr/pppp1ppp/2n5/4p3/3PP3/5N2/PPP2PPP/RNBQKB1R b KQkq d3 1 3", + "name": "Scotch Game" + }, + { + "eco": "C45", + "fen": "r1bqk1nr/pppp1ppp/2n5/2b5/3NP3/8/PPP2PPP/RNBQKB1R w KQkq - 2 5", + "name": "Scotch Game: Classical Variation" + }, + { + "eco": "C45", + "fen": "r1bqkb1r/p1pp1ppp/2p2n2/4P3/8/8/PPP2PPP/RNBQKB1R b KQkq - 1 6", + "name": "Scotch Game: Mieses Variation" + }, + { + "eco": "C45", + "fen": "r1b1kbnr/pppp1ppp/2n5/8/3NP2q/8/PPP2PPP/RNBQKB1R w KQkq - 2 5", + "name": "Scotch Game: Steinitz Variation" + }, + { + "eco": "B20", + "fen": "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 1 2", + "name": "Sicilian Defence" + }, + { + "eco": "B36", + "fen": "r1bqkbnr/pp1ppp1p/2n3p1/8/3NP3/8/PPP2PPP/RNBQKB1R w KQkq - 1 5", + "name": "Sicilian Defence: Accelerated Dragon" + }, + { + "eco": "B22", + "fen": "rnbqkbnr/pp1ppppp/8/2p5/4P3/2P5/PP1P1PPP/RNBQKBNR b KQkq - 1 2", + "name": "Sicilian Defence: Alapin Variation" + }, + { + "eco": "B23", + "fen": "rnbqkbnr/pp1ppppp/8/2p5/4P3/2N5/PPPP1PPP/R1BQKBNR b KQkq - 2 2", + "name": "Sicilian Defence: Closed Variation" + }, + { + "eco": "B70", + "fen": "rnbqkb1r/pp2pp1p/3p1np1/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 1 6", + "name": "Sicilian Defence: Dragon Variation" + }, + { + "eco": "B23", + "fen": "r1bqkbnr/pp1ppppp/2n5/2p5/4PP2/2N5/PPPP2PP/R1BQKBNR b KQkq f3 1 3", + "name": "Sicilian Defence: Grand Prix Attack" + }, + { + "eco": "B27", + "fen": "rnbqkbnr/pp1ppp1p/6p1/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 1 2", + "name": "Sicilian Defence: Hyper-Accelerated Dragon" + }, + { + "eco": "B41", + "fen": "rnbqkbnr/1p1p1ppp/p3p3/8/3NP3/8/PPP2PPP/RNBQKB1R w KQkq - 1 5", + "name": "Sicilian Defence: Kan Variation" + }, + { + "eco": "B90", + "fen": "rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 1 6", + "name": "Sicilian Defence: Najdorf Variation" + }, + { + "eco": "B60", + "fen": "r1bqkb1r/pp2pppp/2np1n2/6B1/3NP3/2N5/PPP2PPP/R2QKB1R b KQkq - 5 6", + "name": "Sicilian Defence: Richter-Rauzer Variation" + }, + { + "eco": "B80", + "fen": "rnbqkb1r/pp3ppp/3ppn2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 1 6", + "name": "Sicilian Defence: Scheveningen Variation" + }, + { + "eco": "B21", + "fen": "rnbqkbnr/pp1ppppp/8/8/3pP3/2P5/PP3PPP/RNBQKBNR b KQkq - 1 3", + "name": "Sicilian Defence: Smith-Morra Gambit" + }, + { + "eco": "C27", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/4P3/2N5/PPPP1PPP/R1BQKBNR b KQkq - 2 2", + "name": "Vienna Game" + }, + { + "eco": "C27", + "fen": "rnbqkb1r/pppp1ppp/8/4p3/2B1n3/2N5/PPPP1PPP/R1BQK1NR w KQkq - 0 4", + "name": "Frankenstein-Dracula Variation" + }, + { + "eco": "C47", + "fen": "r1bqkb1r/pppp1ppp/2n2n2/4N3/4P3/2N5/PPPP1PPP/R1BQKB1R b KQkq - 1 4", + "name": "Halloween Gambit" + }, + { + "eco": "420", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPPKPPP/RNBQ1BNR b kq - 0 2", + "name": "Bongcloud Attack" + } + ] + }, + { + "name": "d4", + "positions": [ + { + "eco": "A40", + "fen": "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq d3 1 1", + "name": "Queen's Pawn" + }, + { + "eco": "A57", + "fen": "rnbqkb1r/p2ppppp/5n2/1ppP4/2P5/8/PP2PPPP/RNBQKBNR w KQkq b6 1 4", + "name": "Benko Gambit" + }, + { + "eco": "A61", + "fen": "rnbqkb1r/pp1p1ppp/4pn2/2pP4/2P5/8/PP2PPPP/RNBQKBNR w KQkq - 0 4", + "name": "Benoni Defence: Modern Benoni" + }, + { + "eco": "A43", + "fen": "rnbqkb1r/pp1p1ppp/5n2/2pPp3/2P5/8/PP2PPPP/RNBQKBNR w KQkq - 0 4", + "name": "Benoni Defence: Czech Benoni" + }, + { + "eco": "D00", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/3PP3/8/PPP2PPP/RNBQKBNR b KQkq e3 1 2", + "name": "Blackmar-Diemer Gambit" + }, + { + "eco": "E11", + "fen": "rnbqk2r/pppp1ppp/4pn2/8/1bPP4/5N2/PP2PPPP/RNBQKB1R w KQkq - 3 4", + "name": "Bogo-Indian Defence" + }, + { + "eco": "E00", + "fen": "rnbqkb1r/pppp1ppp/4pn2/8/2PP4/6P1/PP2PP1P/RNBQKBNR b KQkq - 1 3", + "name": "Catalan Opening" + }, + { + "eco": "E06", + "fen": "rnbqk2r/ppp1bppp/4pn2/3p4/2PP4/5NP1/PP2PPBP/RNBQK2R b KQkq - 4 5", + "name": "Catalan Opening: Closed Variation" + }, + { + "eco": "A80", + "fen": "rnbqkbnr/ppppp1pp/8/5p2/3P4/8/PPP1PPPP/RNBQKBNR w KQkq f6 1 2", + "name": "Dutch Defence" + }, + { + "eco": "A87", + "fen": "rnbqk2r/ppppp1bp/5np1/5p2/2PP4/5NP1/PP2PPBP/RNBQK2R b KQkq - 4 5", + "name": "Dutch Defence: Leningrad Variation" + }, + { + "eco": "A83", + "fen": "rnbqkb1r/ppppp1pp/5n2/6B1/3Pp3/2N5/PPP2PPP/R2QKBNR b KQkq - 4 4", + "name": "Dutch Defence: Staunton Gambit" + }, + { + "eco": "A92", + "fen": "rnbq1rk1/ppp1b1pp/4pn2/3p1p2/2PP4/5NP1/PP2PPBP/RNBQ1RK1 w - d6 1 7", + "name": "Dutch Defence: Stonewall Variation" + }, + { + "eco": "D80", + "fen": "rnbqkb1r/ppp1pp1p/5np1/3p4/2PP4/2N5/PP2PPPP/R1BQKBNR w KQkq d6 1 4", + "name": "Gr\u00fcnfeld Defence" + }, + { + "eco": "D82", + "fen": "rnbqkb1r/ppp1pp1p/5np1/3p4/2PP1B2/2N5/PP2PPPP/R2QKBNR b KQkq - 2 4", + "name": "Gr\u00fcnfeld Defence: Brinckmann Attack" + }, + { + "eco": "D85", + "fen": "rnbqkb1r/ppp1pp1p/6p1/3n4/3P4/2N5/PP2PPPP/R1BQKBNR w KQkq - 1 5", + "name": "Gr\u00fcnfeld Defence: Exchange Variation" + }, + { + "eco": "D80", + "fen": "rnbqkb1r/ppp1pp1p/5np1/3p4/2PP4/1QN5/PP2PPPP/R1B1KBNR b KQkq - 0 4", + "name": "Gr\u00fcnfeld Defence: Russian Variation" + }, + { + "eco": "D90", + "fen": "rnbqk2r/ppp1ppbp/5np1/3p2B1/2PP4/2N2N2/PP2PPPP/R2QKB1R b KQkq - 0 5", + "name": "Gr\u00fcnfeld Defence: Taimanov Variation" + }, + { + "eco": "E61", + "fen": "rnbqkb1r/pppppp1p/5np1/8/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 1 3", + "name": "King's Indian Defence" + }, + { + "eco": "E77", + "fen": "rnbqk2r/ppp1ppbp/3p1np1/8/2PPP3/2N5/PP3PPP/R1BQKBNR w KQkq - 1 5", + "name": "King's Indian Defence: 4.e4" + }, + { + "eco": "E73", + "fen": "rnbq1rk1/ppp1ppbp/3p1np1/6B1/2PPP3/2N5/PP2BPPP/R2QK1NR b KQ - 4 6", + "name": "King's Indian Defence: Averbakh Variation" + }, + { + "eco": "E62", + "fen": "rnbqk2r/ppp1ppbp/3p1np1/8/2PP4/2N2NP1/PP2PP1P/R1BQKB1R b KQkq - 1 5", + "name": "King's Indian Defence: Fianchetto Variation" + }, + { + "eco": "E76", + "fen": "rnbqk2r/ppp1ppbp/3p1np1/8/2PPPP2/2N5/PP4PP/R1BQKBNR b KQkq f3 1 5", + "name": "King's Indian Defence: Four Pawns Attack" + }, + { + "eco": "E91", + "fen": "rnbq1rk1/ppp1ppbp/3p1np1/8/2PPP3/2N2N2/PP2BPPP/R1BQK2R b KQ - 4 6", + "name": "King's Indian Defence: Classical Variation" + }, + { + "eco": "E80", + "fen": "rnbqk2r/ppp1ppbp/3p1np1/8/2PPP3/2N2P2/PP4PP/R1BQKBNR b KQkq - 1 5", + "name": "King's Indian Defence: S\u00e4misch Variation" + }, + { + "eco": "A41", + "fen": "rnbqk1nr/ppp1ppbp/3p2p1/8/2PP4/2N5/PP2PPPP/R1BQKBNR w KQkq - 1 4", + "name": "Queens's Pawn Game: Modern Defence" + }, + { + "eco": "E20", + "fen": "rnbqk2r/pppp1ppp/4pn2/8/1bPP4/2N5/PP2PPPP/R1BQKBNR w KQkq - 3 4", + "name": "Nimzo-Indian Defence" + }, + { + "eco": "E32", + "fen": "rnbqk2r/pppp1ppp/4pn2/8/1bPP4/2N5/PPQ1PPPP/R1B1KBNR b KQkq - 4 4", + "name": "Nimzo-Indian Defence: Classical Variation" + }, + { + "eco": "E43", + "fen": "rnbqk2r/p1pp1ppp/1p2pn2/8/1bPP4/2N1P3/PP3PPP/R1BQKBNR w KQkq - 0 5", + "name": "Nimzo-Indian Defence: Fischer Variation", + "url": "https://lichess.org/opening/Nimzo-Indian_Defense_St_Petersburg_Variation/d4_Nf6_c4_e6_Nc3_Bb4_e3_b6" + }, + { + "eco": "E41", + "fen": "r1bqk2r/pp3ppp/2nppn2/2p5/2PP4/2PBPN2/P4PPP/R1BQK2R w KQkq - 0 8", + "name": "Nimzo-Indian Defence: H\u00fcbner Variation" + }, + { + "eco": "E21", + "fen": "rnbqk2r/pppp1ppp/4pn2/8/1bPP4/2N2N2/PP2PPPP/R1BQKB1R b KQkq - 0 4", + "name": "Nimzo-Indian Defence: Kasparov Variation" + }, + { + "eco": "E30", + "fen": "rnbqk2r/pppp1ppp/4pn2/6B1/1bPP4/2N5/PP2PPPP/R2QKBNR b KQkq - 0 4", + "name": "Nimzo-Indian Defence: Leningrad Variation" + }, + { + "eco": "E26", + "fen": "rnbqk2r/pppp1ppp/4pn2/8/2PP4/P1P5/4PPPP/R1BQKBNR b KQkq - 0 5", + "name": "Nimzo-Indian Defence: S\u00e4misch Variation" + }, + { + "eco": "A53", + "fen": "rnbqkb1r/ppp1pppp/3p1n2/8/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 1 3", + "name": "Old Indian Defence" + }, + { + "eco": "D06", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR b KQkq c3 1 2", + "name": "Queen's Gambit" + }, + { + "eco": "D20", + "fen": "rnbqkbnr/ppp1pppp/8/8/2pP4/8/PP2PPPP/RNBQKBNR w KQkq - 1 3", + "name": "Queen's Gambit Accepted" + }, + { + "eco": "D43", + "fen": "rnbqkb1r/pp3ppp/2p1pn2/3p4/2PP4/2N2N2/PP2PPPP/R1BQKB1R w KQkq - 1 5", + "name": "Queen's Gambit Declined: Semi-Slav Defence" + }, + { + "eco": "D10", + "fen": "rnbqkbnr/pp2pppp/2p5/3p4/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 0 3", + "name": "Queen's Gambit Declined: Slav Defence" + }, + { + "eco": "D40", + "fen": "rnbqkb1r/pp3ppp/4pn2/2pp4/2PP4/2N2N2/PP2PPPP/R1BQKB1R w KQkq c6 1 5", + "name": "Queen's Gambit Declined: Semi-Tarrasch Defence" + }, + { + "eco": "D32", + "fen": "rnbqkbnr/pp3ppp/4p3/2pp4/2PP4/2N5/PP2PPPP/R1BQKBNR w KQkq - 0 4", + "name": "Queen's Gambit Declined: Tarrasch Defence" + }, + { + "eco": "D08", + "fen": "rnbqkbnr/ppp2ppp/8/3pp3/2PP4/8/PP2PPPP/RNBQKBNR w KQkq e6 1 3", + "name": "Queen's Gambit Declined: Albin Countergambit" + }, + { + "eco": "D07", + "fen": "r1bqkbnr/ppp1pppp/2n5/3p4/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 2 3", + "name": "Queen's Gambit Declined: Chigorin Defence" + }, + { + "eco": "E12", + "fen": "rnbqkb1r/p1pp1ppp/1p2pn2/8/2PP4/5N2/PP2PPPP/RNBQKB1R w KQkq - 1 4", + "name": "Queen's Indian Defence" + }, + { + "eco": "D02", + "fen": "rnbqkb1r/ppp1pppp/5n2/3p4/3P1B2/5N2/PPP1PPPP/RN1QKB1R b KQkq - 4 3", + "name": "London System" + }, + { + "eco": "D03", + "fen": "rnbqkb1r/ppp1pppp/5n2/3p2B1/3P4/5N2/PPP1PPPP/RN1QKB1R b KQkq - 4 3", + "name": "Torre Attack" + }, + { + "eco": "D01", + "fen": "rnbqkb1r/ppp1pppp/5n2/3p2B1/3P4/2N5/PPP1PPPP/R2QKBNR b KQkq - 4 3", + "name": "Richter-Veresov Attack" + }, + { + "eco": "A52", + "fen": "rnbqkb1r/pppp1ppp/5n2/4p3/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 0 3", + "name": "Budapest Defence" + }, + { + "eco": "D00", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/3P4/8/PPP1PPPP/RNBQKBNR w KQkq - 0 2", + "name": "Closed Game" + }, + { + "eco": "A45", + "fen": "rnbqkb1r/pppppppp/5n2/6B1/3P4/8/PPP1PPPP/RN1QKBNR b KQkq - 3 2", + "name": "Trompowsky Attack" + } + ] + }, + { + "name": "Nf3", + "positions": [ + { + "eco": "A04", + "fen": "rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq - 1 1", + "name": "Zukertort Opening" + }, + { + "eco": "A07", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/8/5NP1/PPPPPP1P/RNBQKB1R b KQkq - 1 2", + "name": "King's Indian Attack" + }, + { + "eco": "A09", + "fen": "rnbqkbnr/ppp1pppp/8/3p4/2P5/5N2/PP1PPPPP/RNBQKB1R b KQkq c3 1 2", + "name": "R\u00e9ti Opening" + } + ] + }, + { + "name": "c4", + "positions": [ + { + "eco": "A10", + "fen": "rnbqkbnr/pppppppp/8/8/2P5/8/PP1PPPPP/RNBQKBNR b KQkq c3 1 1", + "name": "English Opening" + }, + { + "eco": "A20", + "fen": "rnbqkbnr/pppp1ppp/8/4p3/2P5/8/PP1PPPPP/RNBQKBNR w KQkq e6 1 2", + "name": "English Opening: Reversed Sicilian" + }, + { + "eco": "A30", + "fen": "rnbqkbnr/pp1ppppp/8/2p5/2P5/8/PP1PPPPP/RNBQKBNR w KQkq c6 1 2", + "name": "English Opening: Symmetrical Variation" + }, + { + "eco": "A26", + "fen": "r1bqk1nr/ppp2pbp/2np2p1/4p3/2P5/2NP2P1/PP2PPBP/R1BQK1NR w KQkq - 0 6", + "name": "English Opening: Closed System" + } + ] + }, + { + "name": "b3", + "positions": [ + { + "eco": "A01", + "fen": "rnbqkbnr/pppppppp/8/8/8/1P6/P1PPPPPP/RNBQKBNR b KQkq - 1 1", + "name": "Nimzo-Larsen Attack" + } + ] + }, + { + "name": "g3", + "positions": [ + { + "eco": "A00", + "fen": "rnbqkbnr/pppppppp/8/8/8/6P1/PPPPPP1P/RNBQKBNR b KQkq - 1 1", + "name": "Hungarian Opening" + } + ] + } +] diff --git a/lib/src/model/board_editor/position.dart b/lib/src/model/board_editor/position.dart new file mode 100644 index 0000000000..3ff9d08e41 --- /dev/null +++ b/lib/src/model/board_editor/position.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'position.freezed.dart'; + +@freezed +class Position with _$Position { + const factory Position({required String name, required String fen, required String eco}) = + _Position; + + factory Position.fromJson(Map json) => Position( + name: json['name'] as String, + fen: json['fen'] as String, + eco: json['eco'] as String, + ); +} diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index a8e60ec4cc..ebe565c0ad 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -1,10 +1,18 @@ -import 'package:dartchess/dartchess.dart'; +import 'dart:convert'; + +import 'package:dartchess/dartchess.dart' hide Position; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:lichess_mobile/src/constants.dart'; import 'package:lichess_mobile/src/model/board_editor/board_editor_controller.dart'; +import 'package:lichess_mobile/src/model/board_editor/position.dart'; import 'package:lichess_mobile/src/styles/styles.dart'; import 'package:lichess_mobile/src/utils/l10n_context.dart'; +import 'package:lichess_mobile/src/utils/navigation.dart'; import 'package:lichess_mobile/src/widgets/adaptive_bottom_sheet.dart'; +import 'package:lichess_mobile/src/widgets/buttons.dart'; +import 'package:lichess_mobile/src/widgets/list.dart'; +import 'package:lichess_mobile/src/widgets/platform_scaffold.dart'; class BoardEditorMenu extends ConsumerWidget { const BoardEditorMenu({required this.initialFen, super.key}); @@ -19,6 +27,42 @@ class BoardEditorMenu extends ConsumerWidget { return BottomSheetScrollableContainer( padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0), children: [ + Padding( + padding: Styles.horizontalBodyPadding, + child: Wrap( + alignment: WrapAlignment.spaceEvenly, + children: [ + SecondaryButton( + semanticsLabel: context.l10n.loadPosition, + child: Text(context.l10n.loadPosition), + onPressed: () { + final notifier = ref.read(editorController.notifier); + pushReplacementPlatformRoute( + context, + title: context.l10n.preferencesHowDoYouMovePieces, + rootNavigator: true, + builder: + (_) => SearchPositionScreen( + onPositionSelected: + (position) => { + notifier.loadFen(position.fen), + Navigator.of(context, rootNavigator: true).pop(), + }, + ), + ); + }, + ), + SecondaryButton( + semanticsLabel: context.l10n.clearBoard, + child: Text(context.l10n.clearBoard), + onPressed: () { + ref.read(editorController.notifier).loadFen(kEmptyFen); + Navigator.of(context, rootNavigator: true).pop(); + }, + ), + ], + ), + ), Padding( padding: Styles.horizontalBodyPadding, child: Wrap( @@ -93,3 +137,128 @@ class BoardEditorMenu extends ConsumerWidget { ); } } + +class SearchPositionScreen extends StatelessWidget { + const SearchPositionScreen({required this.onPositionSelected, super.key}); + + final void Function(Position position) onPositionSelected; + + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 2, + child: PlatformScaffold( + appBar: PlatformAppBar( + title: Text(context.l10n.loadPosition), + bottom: TabBar( + tabs: [Tab(text: context.l10n.openings), Tab(text: context.l10n.endgamePositions)], + ), + ), + body: TabBarView( + children: [ + _OpeningsTab(onPositionSelected: onPositionSelected), + _EndGamesTab(onPositionSelected: onPositionSelected), + ], + ), + ), + ); + } +} + +class _OpeningsTab extends StatefulWidget { + const _OpeningsTab({required this.onPositionSelected, super.key}); + + final void Function(Position position) onPositionSelected; + + @override + State<_OpeningsTab> createState() => _OpeningsTabState(); +} + +class _OpeningsTabState extends State<_OpeningsTab> { + // TODO Provider + late final Future>? _openings; + + @override + void initState() { + _openings = DefaultAssetBundle.of(context).loadString('assets/positions.json').then((s) { + final List result = []; + for (var opening in jsonDecode(s) as List) { + for (var position in opening['positions'] as List) { + result.add(Position.fromJson(position as Map)); + } + } + return result; + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _openings, + builder: (context, snapshot) { + if (snapshot.hasError) { + return Center(child: Text(snapshot.error.toString())); + } + return ListView.builder( + itemCount: snapshot.data?.length ?? 0, + itemBuilder: (context, index) { + final position = snapshot.data![index]; + return PlatformListTile( + title: Text(position.name), + onTap: () => widget.onPositionSelected(position), + ); + }, + ); + }, + ); + } +} + +class _EndGamesTab extends StatefulWidget { + const _EndGamesTab({required this.onPositionSelected, super.key}); + + final void Function(Position position) onPositionSelected; + + @override + State<_EndGamesTab> createState() => _EndGamesTabState(); +} + +class _EndGamesTabState extends State<_EndGamesTab> { + // TODO Provider + late final Future>? _endGames; + + @override + void initState() { + _endGames = DefaultAssetBundle.of(context).loadString('assets/endgames.json').then((s) { + final List result = []; + for (var position in jsonDecode(s) as List) { + result.add(Position.fromJson(position as Map)); + } + return result; + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _endGames, + builder: (context, snapshot) { + if (snapshot.hasError) { + return Center(child: Text(snapshot.error.toString())); + } + return ListView.builder( + itemCount: snapshot.data?.length ?? 0, + itemBuilder: (context, index) { + final position = snapshot.data![index]; + return PlatformListTile( + title: Text(position.name), + onTap: () => widget.onPositionSelected(position), + ); + }, + ); + }, + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 1220df7a11..8e095f54c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -112,6 +112,8 @@ flutter: - assets/sounds/standard/ - assets/sounds/sfx/ - assets/board-thumbnails/ + - assets/positions.json + - assets/endgames.json fonts: - family: LichessIcons From 1acb348e4f637cb6f68952694bdf051bffca4b9d Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Fri, 31 Jan 2025 17:00:44 +0100 Subject: [PATCH 2/9] run dart fix --- lib/src/view/board_editor/board_editor_menu.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index ebe565c0ad..ca6aa44350 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -166,7 +166,7 @@ class SearchPositionScreen extends StatelessWidget { } class _OpeningsTab extends StatefulWidget { - const _OpeningsTab({required this.onPositionSelected, super.key}); + const _OpeningsTab({required this.onPositionSelected}); final void Function(Position position) onPositionSelected; @@ -182,8 +182,8 @@ class _OpeningsTabState extends State<_OpeningsTab> { void initState() { _openings = DefaultAssetBundle.of(context).loadString('assets/positions.json').then((s) { final List result = []; - for (var opening in jsonDecode(s) as List) { - for (var position in opening['positions'] as List) { + for (final opening in jsonDecode(s) as List) { + for (final position in opening['positions'] as List) { result.add(Position.fromJson(position as Map)); } } @@ -216,7 +216,7 @@ class _OpeningsTabState extends State<_OpeningsTab> { } class _EndGamesTab extends StatefulWidget { - const _EndGamesTab({required this.onPositionSelected, super.key}); + const _EndGamesTab({required this.onPositionSelected}); final void Function(Position position) onPositionSelected; @@ -232,7 +232,7 @@ class _EndGamesTabState extends State<_EndGamesTab> { void initState() { _endGames = DefaultAssetBundle.of(context).loadString('assets/endgames.json').then((s) { final List result = []; - for (var position in jsonDecode(s) as List) { + for (final position in jsonDecode(s) as List) { result.add(Position.fromJson(position as Map)); } return result; From 5911cd551beaabab0d71b8e6d1c57ff0cab1785a Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Fri, 31 Jan 2025 17:20:10 +0100 Subject: [PATCH 3/9] fix: using wrong build context --- lib/src/view/board_editor/board_editor_menu.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index ca6aa44350..420f7602c6 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -42,7 +42,7 @@ class BoardEditorMenu extends ConsumerWidget { title: context.l10n.preferencesHowDoYouMovePieces, rootNavigator: true, builder: - (_) => SearchPositionScreen( + (context) => SearchPositionScreen( onPositionSelected: (position) => { notifier.loadFen(position.fen), From 29b70acb94081886cebad52037f57bed3c82dd85 Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Fri, 31 Jan 2025 17:21:35 +0100 Subject: [PATCH 4/9] silent warning --- lib/src/view/board_editor/board_editor_menu.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index 420f7602c6..ccabf6b5c0 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -183,6 +183,7 @@ class _OpeningsTabState extends State<_OpeningsTab> { _openings = DefaultAssetBundle.of(context).loadString('assets/positions.json').then((s) { final List result = []; for (final opening in jsonDecode(s) as List) { + // ignore: avoid_dynamic_calls for (final position in opening['positions'] as List) { result.add(Position.fromJson(position as Map)); } From ef30fc63d8ab54bab33ada4403f8feaceb159122 Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Wed, 12 Feb 2025 12:38:26 +0100 Subject: [PATCH 5/9] define buildRoute in SearchPositionScreen --- .../view/board_editor/board_editor_menu.dart | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index ccabf6b5c0..4ca84e51ea 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -37,18 +37,15 @@ class BoardEditorMenu extends ConsumerWidget { child: Text(context.l10n.loadPosition), onPressed: () { final notifier = ref.read(editorController.notifier); - pushReplacementPlatformRoute( - context, - title: context.l10n.preferencesHowDoYouMovePieces, - rootNavigator: true, - builder: - (context) => SearchPositionScreen( - onPositionSelected: - (position) => { - notifier.loadFen(position.fen), - Navigator.of(context, rootNavigator: true).pop(), - }, - ), + Navigator.of(context, rootNavigator: true).pushReplacement( + SearchPositionScreen.buildRoute( + context, + onPositionSelected: + (position) => { + notifier.loadFen(position.fen), + Navigator.of(context, rootNavigator: true).pop(), + }, + ), ); }, ), @@ -143,6 +140,17 @@ class SearchPositionScreen extends StatelessWidget { final void Function(Position position) onPositionSelected; + static Route buildRoute( + BuildContext context, { + required void Function(Position position) onPositionSelected, + }) { + return buildScreenRoute( + context, + screen: SearchPositionScreen(onPositionSelected: onPositionSelected), + title: context.l10n.preferencesHowDoYouMovePieces, + ); + } + @override Widget build(BuildContext context) { return DefaultTabController( From ddd51b04ea8b154ef88261d3948304480716007e Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Thu, 13 Feb 2025 21:23:12 +0100 Subject: [PATCH 6/9] refactor --- lib/src/view/board_editor/board_editor_menu.dart | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index 4ca84e51ea..57da3da680 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -183,17 +183,15 @@ class _OpeningsTab extends StatefulWidget { } class _OpeningsTabState extends State<_OpeningsTab> { - // TODO Provider late final Future>? _openings; @override void initState() { _openings = DefaultAssetBundle.of(context).loadString('assets/positions.json').then((s) { final List result = []; - for (final opening in jsonDecode(s) as List) { - // ignore: avoid_dynamic_calls - for (final position in opening['positions'] as List) { - result.add(Position.fromJson(position as Map)); + for (final opening in (jsonDecode(s) as List).cast>()) { + for (final position in (opening['positions'] as List).cast>()) { + result.add(Position.fromJson(position)); } } return result; @@ -234,15 +232,14 @@ class _EndGamesTab extends StatefulWidget { } class _EndGamesTabState extends State<_EndGamesTab> { - // TODO Provider late final Future>? _endGames; @override void initState() { _endGames = DefaultAssetBundle.of(context).loadString('assets/endgames.json').then((s) { final List result = []; - for (final position in jsonDecode(s) as List) { - result.add(Position.fromJson(position as Map)); + for (final position in (jsonDecode(s) as List).cast>()) { + result.add(Position.fromJson(position)); } return result; }); From cdf43822fc9231141e40fdaab8ea0d5baa23d2d1 Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Thu, 13 Feb 2025 21:50:56 +0100 Subject: [PATCH 7/9] fix wrong screen title --- lib/src/view/board_editor/board_editor_menu.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index 57da3da680..f06cc8506f 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -147,7 +147,7 @@ class SearchPositionScreen extends StatelessWidget { return buildScreenRoute( context, screen: SearchPositionScreen(onPositionSelected: onPositionSelected), - title: context.l10n.preferencesHowDoYouMovePieces, + title: context.l10n.loadPosition, ); } From 2bb177add30d1f66f462a509599d927cae01b0bb Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Thu, 13 Feb 2025 21:52:50 +0100 Subject: [PATCH 8/9] use PlatformWidget instead of PlatformScaffold --- .../view/board_editor/board_editor_menu.dart | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index f06cc8506f..5eca9065a5 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:dartchess/dartchess.dart' hide Position; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lichess_mobile/src/constants.dart'; @@ -12,7 +13,7 @@ import 'package:lichess_mobile/src/utils/navigation.dart'; import 'package:lichess_mobile/src/widgets/adaptive_bottom_sheet.dart'; import 'package:lichess_mobile/src/widgets/buttons.dart'; import 'package:lichess_mobile/src/widgets/list.dart'; -import 'package:lichess_mobile/src/widgets/platform_scaffold.dart'; +import 'package:lichess_mobile/src/widgets/platform.dart'; class BoardEditorMenu extends ConsumerWidget { const BoardEditorMenu({required this.initialFen, super.key}); @@ -37,13 +38,13 @@ class BoardEditorMenu extends ConsumerWidget { child: Text(context.l10n.loadPosition), onPressed: () { final notifier = ref.read(editorController.notifier); - Navigator.of(context, rootNavigator: true).pushReplacement( + Navigator.of(context).pushReplacement( SearchPositionScreen.buildRoute( context, onPositionSelected: (position) => { notifier.loadFen(position.fen), - Navigator.of(context, rootNavigator: true).pop(), + Navigator.of(context).pop(), }, ), ); @@ -153,21 +154,34 @@ class SearchPositionScreen extends StatelessWidget { @override Widget build(BuildContext context) { + final tabBar = TabBar( + tabs: [Tab(text: context.l10n.openings), Tab(text: context.l10n.endgamePositions)], + ); + final tabBarView = TabBarView( + children: [ + _OpeningsTab(onPositionSelected: onPositionSelected), + _EndGamesTab(onPositionSelected: onPositionSelected), + ], + ); + return DefaultTabController( length: 2, - child: PlatformScaffold( - appBar: PlatformAppBar( - title: Text(context.l10n.loadPosition), - bottom: TabBar( - tabs: [Tab(text: context.l10n.openings), Tab(text: context.l10n.endgamePositions)], - ), - ), - body: TabBarView( - children: [ - _OpeningsTab(onPositionSelected: onPositionSelected), - _EndGamesTab(onPositionSelected: onPositionSelected), - ], - ), + child: PlatformWidget( + iosBuilder: + (context) { + return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + middle: Text(context.l10n.loadPosition), + bottom: tabBar, + ), + child: tabBarView, + ); + }, + androidBuilder: + (context) => Scaffold( + appBar: AppBar(title: Text(context.l10n.loadPosition), bottom: tabBar), + body: tabBarView, + ), ), ); } From 5d1f5bae62a1739c9ed28f28f65d43c68c7da2ca Mon Sep 17 00:00:00 2001 From: Vincenzo De Petris Date: Thu, 13 Feb 2025 22:03:21 +0100 Subject: [PATCH 9/9] format file --- .../view/board_editor/board_editor_menu.dart | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/src/view/board_editor/board_editor_menu.dart b/lib/src/view/board_editor/board_editor_menu.dart index 5eca9065a5..4bd44226a2 100644 --- a/lib/src/view/board_editor/board_editor_menu.dart +++ b/lib/src/view/board_editor/board_editor_menu.dart @@ -167,16 +167,15 @@ class SearchPositionScreen extends StatelessWidget { return DefaultTabController( length: 2, child: PlatformWidget( - iosBuilder: - (context) { - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text(context.l10n.loadPosition), - bottom: tabBar, - ), - child: tabBarView, - ); - }, + iosBuilder: (context) { + return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar( + middle: Text(context.l10n.loadPosition), + bottom: tabBar, + ), + child: tabBarView, + ); + }, androidBuilder: (context) => Scaffold( appBar: AppBar(title: Text(context.l10n.loadPosition), bottom: tabBar), @@ -204,7 +203,8 @@ class _OpeningsTabState extends State<_OpeningsTab> { _openings = DefaultAssetBundle.of(context).loadString('assets/positions.json').then((s) { final List result = []; for (final opening in (jsonDecode(s) as List).cast>()) { - for (final position in (opening['positions'] as List).cast>()) { + for (final position + in (opening['positions'] as List).cast>()) { result.add(Position.fromJson(position)); } }