Spaces:
Sleeping
Sleeping
Commit Β·
054c349
1
Parent(s): 68b94c6
new version with csv
Browse files- Chess Opening Reference - Sheet1.csv +501 -0
- app.py +60 -194
- app_1.py +645 -234
- openings.py +3 -0
Chess Opening Reference - Sheet1.csv
ADDED
|
@@ -0,0 +1,501 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ECO Code,Name,Opening Moves
|
| 2 |
+
A00,Uncommon Opening,"1 g4, a3, h3, etc."
|
| 3 |
+
A01,Nimzovich-Larsen Attack,1 b3
|
| 4 |
+
A02,Bird's Opening,1 f4
|
| 5 |
+
A03,Bird's Opening,1 f4 d5
|
| 6 |
+
A04,Reti Opening,1 Nf3
|
| 7 |
+
A05,Reti Opening,1 Nf3 Nf6
|
| 8 |
+
A06,Reti Opening,1 Nf3 d5
|
| 9 |
+
A07,King's Indian Attack,1 Nf3 d5 2 g3
|
| 10 |
+
A08,King's Indian Attack,1 Nf3 d5 2 g3 c5 3 Bg2
|
| 11 |
+
A09,Reti Opening,1 Nf3 d5 2 c4
|
| 12 |
+
A10,English,1 c4
|
| 13 |
+
A11,"English, Caro-Kann Defensive System",1 c4 c6
|
| 14 |
+
A12,English with b3,1 c4 c6 2 Nf3 d5 3 b3
|
| 15 |
+
A13,English,1 c4 e6
|
| 16 |
+
A14,English,1 c4 e6 2 Nf3 d5 3 g3 Nf6 4 Bg2 Be7 5 O-O
|
| 17 |
+
A15,English,1 c4 Nf6
|
| 18 |
+
A16,English,1 c4 Nf6 2 Nc3
|
| 19 |
+
A17,English,1 c4 Nf6 2 Nc3 e6
|
| 20 |
+
A18,"English, Mikenas-Carls",1 c4 Nf6 2 Nc3 e6 3 e4
|
| 21 |
+
A19,"English, Mikenas-Carls, Sicilian Variation",1 c4 Nf6 2 Nc3 e6 3 e4 c5
|
| 22 |
+
A20,English,1 c4 e5
|
| 23 |
+
A21,English,1 c4 e5 2 Nc3
|
| 24 |
+
A22,English,1 c4 e5 2 Nc3 Nf6
|
| 25 |
+
A23,"English, Bremen System, Keres Variation",1 c4 e5 2 Nc3 Nf6 3 g3 c6
|
| 26 |
+
A24,"English, Bremen System with ...g6",1 c4 e5 2 Nc3 Nf6 3 g3 g6
|
| 27 |
+
A25,English,1 c4 e5 2 Nc3 Nc6
|
| 28 |
+
A26,English,1 c4 e5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 d3 d6
|
| 29 |
+
A27,"English, Three Knights System",1 c4 e5 2 Nc3 Nc6 3 Nf3
|
| 30 |
+
A28,English,1 c4 e5 2 Nc3 Nc6 3 Nf3 Nf6
|
| 31 |
+
A29,"English, Four Knights, Kingside Fianchetto",1 c4 e5 2 Nc3 Nc6 3 Nf3 Nf6 4 g3
|
| 32 |
+
A30,"English, Symmetrical",1 c4 c5
|
| 33 |
+
A31,"English, Symmetrical, Benoni Formation",1 c4 c5 2 Nf3 Nf6 3 d4
|
| 34 |
+
A32,"English, Symmetrical Variation",1 c4 c5 2 Nf3 Nf6 3 d4 cxd4 4 Nxd4 e6
|
| 35 |
+
A33,"English, Symmetrical",1 c4 c5 2 Nf3 Nf6 3 d4 cxd4 4 Nxd4 e6 5 Nc3 Nc6
|
| 36 |
+
A34,"English, Symmetrical",1 c4 c5 2 Nc3
|
| 37 |
+
A35,"English, Symmetrical",1 c4 c5 2 Nc3 Nc6
|
| 38 |
+
A36,English,1 c4 c5 2 Nc3 Nc6 3 g3
|
| 39 |
+
A37,"English, Symmetrical",1 c4 c5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 Nf3
|
| 40 |
+
A38,"English, Symmetrical",1 c4 c5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 Nf3 Nf6
|
| 41 |
+
A39,"English, Symmetrical, Main line with d4",1 c4 c5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 Nf3 Nf6 6 O-O O-O 7 d4
|
| 42 |
+
A40,Queen's Pawn Game,1 d4
|
| 43 |
+
A41,Queen's Pawn Game (with ...d6),1 d4 d6
|
| 44 |
+
A42,"Modern Defense, Averbakh System",1 d4 d6 2 c4 g6 3 Nc3 Bg7 4 e4
|
| 45 |
+
A43,Old Benoni,1 d4 c5
|
| 46 |
+
A44,Old Benoni Defense,1 d4 c5 2 d5 e5
|
| 47 |
+
A45,Queen's Pawn Game,1 d4 Nf6
|
| 48 |
+
A46,Queen's Pawn Game,1 d4 Nf6 2 Nf3
|
| 49 |
+
A47,Queen's Indian,1 d4 Nf6 2 Nf3 b6
|
| 50 |
+
A48,King's Indian,1 d4 Nf6 2 Nf3 g6
|
| 51 |
+
A49,"King's Indian, Fianchetto without c4",1 d4 Nf6 2 Nf3 g6 3 g3
|
| 52 |
+
A50,Queen's Pawn Game,1 d4 Nf6 2 c4
|
| 53 |
+
A51,Budapest Gambit,1 d4 Nf6 2 c4 e5
|
| 54 |
+
A52,Budapest Gambit,1 d4 Nf6 2 c4 e5 3 dxe5 Ng4
|
| 55 |
+
A53,Old Indian,1 d4 Nf6 2 c4 d6
|
| 56 |
+
A54,"Old Indian, Ukrainian Variation, 4.Nf3",1 d4 Nf6 2 c4 d6 3 Nc3 e5 4 Nf3
|
| 57 |
+
A55,"Old Indian, Main line",1 d4 Nf6 2 c4 d6 3 Nc3 e5 4 Nf3 Nbd7 5 e4
|
| 58 |
+
A56,Benoni Defense,1 d4 Nf6 2 c4 c5
|
| 59 |
+
A57,Benko Gambit,1 d4 Nf6 2 c4 c5 3 d5 b5
|
| 60 |
+
A58,Benko Gambit,1 d4 Nf6 2 c4 c5 3 d5 b5 4 cxb5 a6 5 bxa6
|
| 61 |
+
A59,Benko Gambit,1 d4 Nf6 2 c4 c5 3 d5 b5 4 cxb5 a6 5 bxa6 Bxa6 6 Nc3 d6 7 e4
|
| 62 |
+
A60,Benoni Defense,1 d4 Nf6 2 c4 c5 3 d5 e6
|
| 63 |
+
A61,Benoni,1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 Nf3 g6
|
| 64 |
+
A62,"Benoni, Fianchetto Variation",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 Nf3 g6 7 g3 Bg7 8 Bg2 O-O
|
| 65 |
+
A63,"Benoni, Fianchetto, 9...Nbd7",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 Nf3 g6 7 g3 Bg7 8 Bg2 O-O 9
|
| 66 |
+
A64,"Benoni, Fianchetto, 11...Re8",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 Nf3 g6 7 g3 Bg7 8 Bg2 O-O 9
|
| 67 |
+
A65,"Benoni, 6.e4",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4
|
| 68 |
+
A66,Benoni,1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 f4
|
| 69 |
+
A67,"Benoni, Taimanov Variation",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 f4 Bg7 8 Bb5+
|
| 70 |
+
A68,"Benoni, Four Pawns Attack",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 f4 Bg7 8 Nf3 O-O
|
| 71 |
+
A69,"Benoni, Four Pawns Attack, Main line",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 f4 Bg7 8 Nf3 O-O 9
|
| 72 |
+
A70,"Benoni, Classical with 7.Nf3",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3
|
| 73 |
+
A71,"Benoni, Classical, 8.Bg5",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Bg5
|
| 74 |
+
A72,"Benoni, Classical without 9.O-O",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O
|
| 75 |
+
A73,"Benoni, Classical, 9.O-O",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 76 |
+
A74,"Benoni, Classical, 9...a6, 10.a4",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 77 |
+
A75,"Benoni, Classical with ...a6 and 10...Bg4",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 78 |
+
A76,"Benoni, Classical, 9...Re8",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 79 |
+
A77,"Benoni, Classical, 9...Re8, 10.Nd2",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 80 |
+
A78,"Benoni, Classical with ...Re8 and ...Na6",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 81 |
+
A79,"Benoni, Classical, 11.f3",1 d4 Nf6 2 c4 c5 3 d5 e6 4 Nc3 exd5 5 cxd5 d6 6 e4 g6 7 Nf3 Bg7 8 Be2 O-O 9
|
| 82 |
+
A80,Dutch,1 d4 f5
|
| 83 |
+
A81,Dutch,1 d4 f5 2 g3
|
| 84 |
+
A82,"Dutch, Staunton Gambit",1 d4 f5 2 e4
|
| 85 |
+
A83,"Dutch, Staunton Gambit",1 d4 f5 2 e4 fxe4 3 Nc3 Nf6 4 Bg5
|
| 86 |
+
A84,Dutch,1 d4 f5 2 c4
|
| 87 |
+
A85,"Dutch, with c4 & Nc3",1 d4 f5 2 c4 Nf6 3 Nc3
|
| 88 |
+
A86,Dutch,1 d4 f5 2 c4 Nf6 3 g3
|
| 89 |
+
A87,"Dutch, Leningrad, Main Variation",1 d4 f5 2 c4 Nf6 3 g3 g6 4 Bg2 Bg7 5 Nf3
|
| 90 |
+
A88,"Dutch, Leningrad, Main Variation with c6",1 d4 f5 2 c4 Nf6 3 g3 g6 4 Bg2 Bg7 5 Nf3 O-O 6 O-O d6 7 Nc3 c6
|
| 91 |
+
A89,"Dutch, Leningrad, Main Variation with Nc6",1 d4 f5 2 c4 Nf6 3 g3 g6 4 Bg2 Bg7 5 Nf3 O-O 6 O-O d6 7 Nc3 Nc6
|
| 92 |
+
A90,Dutch,1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2
|
| 93 |
+
A91,Dutch Defense,1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7
|
| 94 |
+
A92,Dutch,1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O
|
| 95 |
+
A93,"Dutch, Stonewall, Botvinnik Variation",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d5 7 b3
|
| 96 |
+
A94,"Dutch, Stonewall with Ba3",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d5 7 b3 c6 8 Ba3
|
| 97 |
+
A95,"Dutch, Stonewall",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d5 7 Nc3 c6
|
| 98 |
+
A96,"Dutch, Classical Variation",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d6
|
| 99 |
+
A97,"Dutch, Ilyin-Genevsky",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d6 7 Nc3 Qe8
|
| 100 |
+
A98,"Dutch, Ilyin-Genevsky Variation with Qc2",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d6 7 Nc3 Qe8 8 Qc2
|
| 101 |
+
A99,"Dutch, Ilyin-Genevsky Variation with b3",1 d4 f5 2 c4 Nf6 3 g3 e6 4 Bg2 Be7 5 Nf3 O-O 6 O-O d6 7 Nc3 Qe8 8 b3
|
| 102 |
+
B00,Uncommon King's Pawn Opening,1 e4
|
| 103 |
+
B01,Scandinavian,1 e4 d5
|
| 104 |
+
B02,Alekhine's Defense,1 e4 Nf6
|
| 105 |
+
B03,Alekhine's Defense,1 e4 Nf6 2 e5 Nd5 3 d4
|
| 106 |
+
B04,"Alekhine's Defense, Modern",1 e4 Nf6 2 e5 Nd5 3 d4 d6 4 Nf3
|
| 107 |
+
B05,"Alekhine's Defense, Modern",1 e4 Nf6 2 e5 Nd5 3 d4 d6 4 Nf3 Bg4
|
| 108 |
+
B06,Robatsch,1 e4 g6
|
| 109 |
+
B07,Pirc,1 e4 d6 2 d4 Nf6
|
| 110 |
+
B08,"Pirc, Classical",1 e4 d6 2 d4 Nf6 3 Nc3 g6 4 Nf3
|
| 111 |
+
B09,"Pirc, Austrian Attack",1 e4 d6 2 d4 Nf6 3 Nc3 g6 4 f4
|
| 112 |
+
B10,Caro-Kann,1 e4 c6
|
| 113 |
+
B11,"Caro-Kann, Two Knights, 3...Bg4",1 e4 c6 2 Nc3 d5 3 Nf3 Bg4
|
| 114 |
+
B12,Caro-Kann Defense,1 e4 c6 2 d4
|
| 115 |
+
B13,"Caro-Kann, Exchange",1 e4 c6 2 d4 d5 3 exd5 cxd5
|
| 116 |
+
B14,"Caro-Kann, Panov-Botvinnik Attack",1 e4 c6 2 d4 d5 3 exd5 cxd5 4 c4 Nf6 5 Nc3 e6
|
| 117 |
+
B15,Caro-Kann,1 e4 c6 2 d4 d5 3 Nc3
|
| 118 |
+
B16,"Caro-Kann, Bronstein-Larsen Variation",1 e4 c6 2 d4 d5 3 Nc3 dxe4 4 Nxe4 Nf6 5 Nxf6+ gxf6
|
| 119 |
+
B17,"Caro-Kann, Steinitz Variation",1 e4 c6 2 d4 d5 3 Nc3 dxe4 4 Nxe4 Nd7
|
| 120 |
+
B18,"Caro-Kann, Classical",1 e4 c6 2 d4 d5 3 Nc3 dxe4 4 Nxe4 Bf5
|
| 121 |
+
B19,"Caro-Kann, Classical",1 e4 c6 2 d4 d5 3 Nc3 dxe4 4 Nxe4 Bf5 5 Ng3 Bg6 6 h4 h6 7 Nf3 Nd7
|
| 122 |
+
B20,Sicilian,1 e4 c5
|
| 123 |
+
B21,"Sicilian, 2.f4 and 2.d4",1 e4 c5 2 f4
|
| 124 |
+
B22,"Sicilian, Alapin",1 e4 c5 2 c3
|
| 125 |
+
B23,"Sicilian, Closed",1 e4 c5 2 Nc3
|
| 126 |
+
B24,"Sicilian, Closed",1 e4 c5 2 Nc3 Nc6 3 g3
|
| 127 |
+
B25,"Sicilian, Closed",1 e4 c5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 d3 d6
|
| 128 |
+
B26,"Sicilian, Closed, 6.Be3",1 e4 c5 2 Nc3 Nc6 3 g3 g6 4 Bg2 Bg7 5 d3 d6 6 Be3
|
| 129 |
+
B27,Sicilian,1 e4 c5 2 Nf3
|
| 130 |
+
B28,"Sicilian, O'Kelly Variation",1 e4 c5 2 Nf3 a6
|
| 131 |
+
B29,"Sicilian, Nimzovich-Rubinstein",1 e4 c5 2 Nf3 Nf6
|
| 132 |
+
B30,Sicilian,1 e4 c5 2 Nf3 Nc6
|
| 133 |
+
B31,"Sicilian, Rossolimo Variation",1 e4 c5 2 Nf3 Nc6 3 Bb5 g6
|
| 134 |
+
B32,Sicilian,1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 e5
|
| 135 |
+
B33,Sicilian,1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4
|
| 136 |
+
B34,"Sicilian, Accelerated Fianchetto",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 Nxc6
|
| 137 |
+
B35,"Sicilian, Accelerated Fianchetto, Modern Variation with Bc4",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 Nc3 Bg7 6 Be3 Nf6 7 Bc4
|
| 138 |
+
B36,"Sicilian, Accelerated Fianchetto",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 c4
|
| 139 |
+
B37,"Sicilian, Accelerated Fianchetto",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 c4 Bg7
|
| 140 |
+
B38,"Sicilian, Accelerated Fianchetto, Maroczy Bind, 6.Be3",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 c4 Bg7 6 Be3
|
| 141 |
+
B39,"Sicilian, Accelerated Fianchetto, Breyer Variation",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 g6 5 c4 Bg7 6 Be3 Nf6 7 Nc3 Ng4
|
| 142 |
+
B40,Sicilian,1 e4 c5 2 Nf3 e6
|
| 143 |
+
B41,"Sicilian, Kan",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 a6
|
| 144 |
+
B42,"Sicilian, Kan",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 a6 5 Bd3
|
| 145 |
+
B43,"Sicilian, Kan, 5.Nc3",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 a6 5 Nc3
|
| 146 |
+
B44,Sicilian,1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6
|
| 147 |
+
B45,"Sicilian, Taimanov",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6 5 Nc3
|
| 148 |
+
B46,"Sicilian, Taimanov Variation",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6 5 Nc3 a6
|
| 149 |
+
B47,"Sicilian, Taimanov (Bastrikov) Variation",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6 5 Nc3 Qc7
|
| 150 |
+
B48,"Sicilian, Taimanov Variation",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6 5 Nc3 Qc7 6 Be3
|
| 151 |
+
B49,"Sicilian, Taimanov Variation",1 e4 c5 2 Nf3 e6 3 d4 cxd4 4 Nxd4 Nc6 5 Nc3 Qc7 6 Be3 a6 7 Be2
|
| 152 |
+
B50,Sicilian,1 e4 c5 2 Nf3 d6
|
| 153 |
+
B51,"Sicilian, Canal-Sokolsky (Rossolimo) Attack",1 e4 c5 2 Nf3 d6 3 Bb5+
|
| 154 |
+
B52,"Sicilian, Canal-Sokolsky (Rossolimo) Attack",1 e4 c5 2 Nf3 d6 3 Bb5+ Bd7
|
| 155 |
+
B53,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Qxd4
|
| 156 |
+
B54,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4
|
| 157 |
+
B55,"Sicilian, Prins Variation, Venice Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 f3 e5 6 Bb5+
|
| 158 |
+
B56,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3
|
| 159 |
+
B57,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bc4
|
| 160 |
+
B58,Sicilian,1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 d6 6 Be2
|
| 161 |
+
B59,"Sicilian, Boleslavsky Variation, 7.Nb3",1 e4 c5 2 Nf3 Nc6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 d6 6 Be2 e5 7 Nb3
|
| 162 |
+
B60,"Sicilian, Richter-Rauzer",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5
|
| 163 |
+
B61,"Sicilian, Richter-Rauzer, Larsen Variation, 7.Qd2",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 Bd7 7 Qd2
|
| 164 |
+
B62,"Sicilian, Richter-Rauzer",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6
|
| 165 |
+
B63,"Sicilian, Richter-Rauzer Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2
|
| 166 |
+
B64,"Sicilian, Richter-Rauzer Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 Be7 8 O-O-O O-O 9 f4
|
| 167 |
+
B65,"Sicilian, Richter-Rauzer Attack, 7...Be7 Defense, 9...Nxd4",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 Be7 8 O-O-O O-O 9 f4 Nxd4 10 Qxd4
|
| 168 |
+
B66,"Sicilian, Richter-Rauzer Attack, 7...a6",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 a6
|
| 169 |
+
B67,"Sicilian, Richter-Rauzer Attack, 7...a6 Defense, 8...Bd7",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 a6 8 O-O-O Bd7
|
| 170 |
+
B68,"Sicilian, Richter-Rauzer Attack, 7...a6 Defense, 9...Be7",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 a6 8 O-O-O Bd7 9 f4 Be7
|
| 171 |
+
B69,"Sicilian, Richter-Rauzer Attack, 7...a6 Defense, 11.Bxf6",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 Nc6 6 Bg5 e6 7 Qd2 a6 8 O-O-O Bd7 9 f4 Be7 10 Nf3 b5 11 Bxf6
|
| 172 |
+
B70,"Sicilian, Dragon Variation",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6
|
| 173 |
+
B71,"Sicilian, Dragon, Levenfish Variation",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 f4
|
| 174 |
+
B72,"Sicilian, Dragon",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3
|
| 175 |
+
B73,"Sicilian, Dragon, Classical",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 Be2 Nc6 8 O-O
|
| 176 |
+
B74,"Sicilian, Dragon, Classical",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 Be2 Nc6 8 O-O O-O 9 Nb3
|
| 177 |
+
B75,"Sicilian, Dragon, Yugoslav Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 f3
|
| 178 |
+
B76,"Sicilian, Dragon, Yugoslav Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 f3 O-O
|
| 179 |
+
B77,"Sicilian, Dragon, Yugoslav Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 f3 O-O 8 Qd2 Nc6 9 Bc4
|
| 180 |
+
B78,"Sicilian, Dragon, Yugoslav Attack, 10.castle long",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 f3 O-O 8 Qd2 Nc6 9 Bc4 Bd7 10 O-O-O
|
| 181 |
+
B79,"Sicilian, Dragon, Yugoslav Attack, 12.h4",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 g6 6 Be3 Bg7 7 f3 O-O 8 Qd2 Nc6 9 Bc4 Bd7 10 O-O-O Qa5 11 Bb3 Rfc8 12 h4
|
| 182 |
+
B80,"Sicilian, Scheveningen",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6
|
| 183 |
+
B81,"Sicilian, Scheveningen, Keres Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 g4
|
| 184 |
+
B82,"Sicilian, Scheveningen",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 f4
|
| 185 |
+
B83,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Be2
|
| 186 |
+
B84,"Sicilian, Scheveningen",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Be2 a6
|
| 187 |
+
B85,"Sicilian, Scheveningen, Classical",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Be2 a6 7 O-O Qc7 8 f4 Nc6
|
| 188 |
+
B86,"Sicilian, Fischer-Sozin Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Bc4
|
| 189 |
+
B87,"Sicilian, Fischer-Sozin with ...a6 and ...b5",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Bc4 a6 7 Bb3 b5
|
| 190 |
+
B88,"Sicilian, Fischer-Sozin Attack",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Bc4 Nc6
|
| 191 |
+
B89,Sicilian,1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 e6 6 Bc4 Nc6 7 Be3
|
| 192 |
+
B90,"Sicilian, Najdorf",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6
|
| 193 |
+
B91,"Sicilian, Najdorf, Zagreb (Fianchetto) Variation",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 g3
|
| 194 |
+
B92,"Sicilian, Najdorf, Opocensky Variation",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Be2
|
| 195 |
+
B93,"Sicilian, Najdorf, 6.f4",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 f4
|
| 196 |
+
B94,"Sicilian, Najdorf",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5
|
| 197 |
+
B95,"Sicilian, Najdorf, 6...e6",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5 e6
|
| 198 |
+
B96,"Sicilian, Najdorf",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5 e6 7 f4
|
| 199 |
+
B97,"Sicilian, Najdorf",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5 e6 7 f4 Qb6
|
| 200 |
+
B98,"Sicilian, Najdorf",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5 e6 7 f4 Be7
|
| 201 |
+
B99,"Sicilian, Najdorf, 7...Be7 Main line",1 e4 c5 2 Nf3 d6 3 d4 cxd4 4 Nxd4 Nf6 5 Nc3 a6 6 Bg5 e6 7 f4 Be7 8 Qf3 Qc7 9 O-O-O Nbd7
|
| 202 |
+
C00,French Defense,1 e4 e6
|
| 203 |
+
C01,"French, Exchange",1 e4 e6 2 d4 d5 3 exd5 exd5 4 Nc3 Nf6 5 Bg5
|
| 204 |
+
C02,"French, Advance",1 e4 e6 2 d4 d5 3 e5
|
| 205 |
+
C03,"French, Tarrasch",1 e4 e6 2 d4 d5 3 Nd2
|
| 206 |
+
C04,"French, Tarrasch, Guimard Main line",1 e4 e6 2 d4 d5 3 Nd2 Nc6 4 Ngf3 Nf6
|
| 207 |
+
C05,"French, Tarrasch",1 e4 e6 2 d4 d5 3 Nd2 Nf6
|
| 208 |
+
C06,"French, Tarrasch",1 e4 e6 2 d4 d5 3 Nd2 Nf6 4 e5 Nfd7 5 Bd3 c5 6 c3 Nc6 7 Ne2 cxd4 8 cxd4
|
| 209 |
+
C07,"French, Tarrasch",1 e4 e6 2 d4 d5 3 Nd2 c5
|
| 210 |
+
C08,"French, Tarrasch, Open, 4.ed ed",1 e4 e6 2 d4 d5 3 Nd2 c5 4 exd5 exd5
|
| 211 |
+
C09,"French, Tarrasch, Open Variation, Main line",1 e4 e6 2 d4 d5 3 Nd2 c5 4 exd5 exd5 5 Ngf3 Nc6
|
| 212 |
+
C10,French,1 e4 e6 2 d4 d5 3 Nc3
|
| 213 |
+
C11,French,1 e4 e6 2 d4 d5 3 Nc3 Nf6
|
| 214 |
+
C12,"French, McCutcheon",1 e4 e6 2 d4 d5 3 Nc3 Nf6 4 Bg5 Bb4
|
| 215 |
+
C13,French,1 e4 e6 2 d4 d5 3 Nc3 Nf6 4 Bg5 Be7
|
| 216 |
+
C14,"French, Classical",1 e4 e6 2 d4 d5 3 Nc3 Nf6 4 Bg5 Be7 5 e5 Nfd7 6 Bxe7 Qxe7
|
| 217 |
+
C15,"French, Winawer",1 e4 e6 2 d4 d5 3 Nc3 Bb4
|
| 218 |
+
C16,"French, Winawer",1 e4 e6 2 d4 d5 3 Nc3 Bb4 4 e5
|
| 219 |
+
C17,"French, Winawer, Advance",1 e4 e6 2 d4 d5 3 Nc3 Bb4 4 e5 c5
|
| 220 |
+
C18,"French, Winawer",1 e4 e6 2 d4 d5 3 Nc3 Bb4 4 e5 c5 5 a3 Bxc3+ 6 bxc3
|
| 221 |
+
C19,"French, Winawer, Advance",1 e4 e6 2 d4 d5 3 Nc3 Bb4 4 e5 c5 5 a3 Bxc3+ 6 bxc3 Ne7
|
| 222 |
+
C20,King's Pawn Game,1 e4 e5
|
| 223 |
+
C21,Center Game,1 e4 e5 2 d4 exd4
|
| 224 |
+
C22,Center Game,1 e4 e5 2 d4 exd4 3 Qxd4 Nc6
|
| 225 |
+
C23,Bishop's Opening,1 e4 e5 2 Bc4
|
| 226 |
+
C24,Bishop's Opening,1 e4 e5 2 Bc4 Nf6
|
| 227 |
+
C25,Vienna,1 e4 e5 2 Nc3
|
| 228 |
+
C26,Vienna,1 e4 e5 2 Nc3 Nf6
|
| 229 |
+
C27,Vienna Game,1 e4 e5 2 Nc3 Nf6 3 Bc4 Nxe4
|
| 230 |
+
C28,Vienna Game,1 e4 e5 2 Nc3 Nf6 3 Bc4 Nc6
|
| 231 |
+
C29,Vienna Gambit,1 e4 e5 2 Nc3 Nf6 3 f4
|
| 232 |
+
C30,King's Gambit Declined,1 e4 e5 2 f4
|
| 233 |
+
C31,"King's Gambit Declined, Falkbeer Counter Gambit",1 e4 e5 2 f4 d5
|
| 234 |
+
C32,"King's Gambit Declined, Falkbeer Counter Gambit",1 e4 e5 2 f4 d5 3 exd5 e4 4 d3 Nf6
|
| 235 |
+
C33,King's Gambit Accepted,1 e4 e5 2 f4 exf4
|
| 236 |
+
C34,King's Gambit Accepted,1 e4 e5 2 f4 exf4 3 Nf3
|
| 237 |
+
C35,"King's Gambit Accepted, Cunningham",1 e4 e5 2 f4 exf4 3 Nf3 Be7
|
| 238 |
+
C36,"King's Gambit Accepted, Abbazia Defense",1 e4 e5 2 f4 exf4 3 Nf3 d5
|
| 239 |
+
C37,King's Gambit Accepted,1 e4 e5 2 f4 exf4 3 Nf3 g5 4 Nc3
|
| 240 |
+
C38,King's Gambit Accepted,1 e4 e5 2 f4 exf4 3 Nf3 g5 4 Bc4 Bg7
|
| 241 |
+
C39,King's Gambit Accepted,1 e4 e5 2 f4 exf4 3 Nf3 g5 4 h4
|
| 242 |
+
C40,King's Knight Opening,1 e4 e5 2 Nf3
|
| 243 |
+
C41,Philidor Defense,1 e4 e5 2 Nf3 d6
|
| 244 |
+
C42,Petrov Defense,1 e4 e5 2 Nf3 Nf6
|
| 245 |
+
C43,"Petrov, Modern Attack",1 e4 e5 2 Nf3 Nf6 3 d4 exd4 4 e5 Ne4 5 Qxd4
|
| 246 |
+
C44,King's Pawn Game,1 e4 e5 2 Nf3 Nc6
|
| 247 |
+
C45,Scotch Game,1 e4 e5 2 Nf3 Nc6 3 d4 exd4 4 Nxd4
|
| 248 |
+
C46,Three Knights,1 e4 e5 2 Nf3 Nc6 3 Nc3
|
| 249 |
+
C47,Four Knights,1 e4 e5 2 Nf3 Nc6 3 Nc3 Nf6
|
| 250 |
+
C48,Four Knights,1 e4 e5 2 Nf3 Nc6 3 Nc3 Nf6 4 Bb5
|
| 251 |
+
C49,Four Knights,1 e4 e5 2 Nf3 Nc6 3 Nc3 Nf6 4 Bb5 Bb4
|
| 252 |
+
C50,Giuoco Piano,1 e4 e5 2 Nf3 Nc6 3 Bc4 Bc5
|
| 253 |
+
C51,Evans Gambit,1 e4 e5 2 Nf3 Nc6 3 Bc4 Bc5 4 b4
|
| 254 |
+
C52,Evans Gambit,1 e4 e5 2 Nf3 Nc6 3 Bc4 Bc5 4 b4 Bxb4 5 c3 Ba5
|
| 255 |
+
C53,Giuoco Piano,1 e4 e5 2 Nf3 Nc6 3 Bc4 Bc5 4 c3
|
| 256 |
+
C54,Giuoco Piano,1 e4 e5 2 Nf3 Nc6 3 Bc4 Bc5 4 c3 Nf6 5 d4 exd4 6 cxd4
|
| 257 |
+
C55,Two Knights Defense,1 e4 e5 2 Nf3 Nc6 3 Bc4 Nf6
|
| 258 |
+
C56,Two Knights,1 e4 e5 2 Nf3 Nc6 3 Bc4 Nf6 4 d4 exd4 5 O-O Nxe4
|
| 259 |
+
C57,Two Knights,1 e4 e5 2 Nf3 Nc6 3 Bc4 Nf6 4 Ng5
|
| 260 |
+
C58,Two Knights,1 e4 e5 2 Nf3 Nc6 3 Bc4 Nf6 4 Ng5 d5 5 exd5 Na5
|
| 261 |
+
C59,Two Knights,1 e4 e5 2 Nf3 Nc6 3 Bc4 Nf6 4 Ng5 d5 5 exd5 Na5 6 Bb5+ c6 7 dxc6 bxc6 8 Be2 h6
|
| 262 |
+
C60,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5
|
| 263 |
+
C61,"Ruy Lopez, Bird's Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 Nd4
|
| 264 |
+
C62,"Ruy Lopez, Old Steinitz Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 d6
|
| 265 |
+
C63,"Ruy Lopez, Schliemann Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 f5
|
| 266 |
+
C64,"Ruy Lopez, Classical",1 e4 e5 2 Nf3 Nc6 3 Bb5 Bc5
|
| 267 |
+
C65,"Ruy Lopez, Berlin Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 Nf6
|
| 268 |
+
C66,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 Nf6 4 O-O d6
|
| 269 |
+
C67,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 Nf6 4 O-O Nxe4
|
| 270 |
+
C68,"Ruy Lopez, Exchange",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Bxc6
|
| 271 |
+
C69,"Ruy Lopez, Exchange, Gligoric Variation",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Bxc6 dc 5 O-O f6
|
| 272 |
+
C70,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4
|
| 273 |
+
C71,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6
|
| 274 |
+
C72,"Ruy Lopez, Modern Steinitz Defense, 5.O-O",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6 5 O-O
|
| 275 |
+
C73,"Ruy Lopez, Modern Steinitz Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6 5 Bxc6+ bxc6 6 d4
|
| 276 |
+
C74,"Ruy Lopez, Modern Steinitz Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6 5 c3
|
| 277 |
+
C75,"Ruy Lopez, Modern Steinitz Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6 5 c3 Bd7
|
| 278 |
+
C76,"Ruy Lopez, Modern Steinitz Defense, Fianchetto Variation",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 d6 5 c3 Bd7 6 d4 g6
|
| 279 |
+
C77,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6
|
| 280 |
+
C78,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O
|
| 281 |
+
C79,"Ruy Lopez, Steinitz Defense Deferred",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O d6
|
| 282 |
+
C80,"Ruy Lopez, Open",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Nxe4
|
| 283 |
+
C81,"Ruy Lopez, Open, Howell Attack",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Nxe4 6 d4 b5 7 Bb3 d5 8 dxe5 Be6 9 Qe2
|
| 284 |
+
C82,"Ruy Lopez, Open",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Nxe4 6 d4 b5 7 Bb3 d5 8 dxe5 Be6 9 c3
|
| 285 |
+
C83,"Ruy Lopez, Open",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Nxe4 6 d4 b5 7 Bb3 d5 8 dxe5 Be6
|
| 286 |
+
C84,"Ruy Lopez, Closed",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7
|
| 287 |
+
C85,"Ruy Lopez, Exchange Variation Doubly Deferred (DERLD)",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Bxc6 dxc6
|
| 288 |
+
C86,"Ruy Lopez, Worrall Attack",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Qe2
|
| 289 |
+
C87,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 d6
|
| 290 |
+
C88,Ruy Lopez,1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3
|
| 291 |
+
C89,"Ruy Lopez, Marshall",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d5
|
| 292 |
+
C90,"Ruy Lopez, Closed",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6
|
| 293 |
+
C91,"Ruy Lopez, Closed",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 d4
|
| 294 |
+
C92,"Ruy Lopez, Closed",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3
|
| 295 |
+
C93,"Ruy Lopez, Closed, Smyslov Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 h6
|
| 296 |
+
C94,"Ruy Lopez, Closed, Breyer Defense",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Nb8
|
| 297 |
+
C95,"Ruy Lopez, Closed, Breyer",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Nb8 10 d4
|
| 298 |
+
C96,"Ruy Lopez, Closed",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Na5 10 Bc2
|
| 299 |
+
C97,"Ruy Lopez, Closed, Chigorin",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Na5 10 Bc2 c5 11 d4 Qc7
|
| 300 |
+
C98,"Ruy Lopez, Closed, Chigorin",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Na5 10 Bc2 c5 11 d4 Qc7 12 Nbd2 Nc6
|
| 301 |
+
C99,"Ruy Lopez, Closed, Chigorin, 12...cd",1 e4 e5 2 Nf3 Nc6 3 Bb5 a6 4 Ba4 Nf6 5 O-O Be7 6 Re1 b5 7 Bb3 O-O 8 c3 d6 9 h3 Na5 10 Bc2 c5 11 d4 Qc7 12 Nbd2 cxd4 13 cxd4
|
| 302 |
+
D00,Queen's Pawn Game,1 d4 d5
|
| 303 |
+
D01,Richter-Veresov Attack,1 d4 d5 2 Nc3 Nf6 3 Bg5
|
| 304 |
+
D02,Queen's Pawn Game,1 d4 d5 2 Nf3
|
| 305 |
+
D03,Torre Attack (Tartakower Variation),1 d4 d5 2 Nf3 Nf6 3 Bg5
|
| 306 |
+
D04,Queen's Pawn Game,1 d4 d5 2 Nf3 Nf6 3 e3
|
| 307 |
+
D05,Queen's Pawn Game,1 d4 d5 2 Nf3 Nf6 3 e3 e6
|
| 308 |
+
D06,Queen's Gambit Declined,1 d4 d5 2 c4
|
| 309 |
+
D07,"Queen's Gambit Declined, Chigorin Defense",1 d4 d5 2 c4 Nc6
|
| 310 |
+
D08,"Queen's Gambit Declined, Albin Counter Gambit",1 d4 d5 2 c4 e5
|
| 311 |
+
D09,"Queen's Gambit Declined, Albin Counter Gambit, 5.g3",1 d4 d5 2 c4 e5 3 dxe5 d4 4 Nf3 Nc6 5 g3
|
| 312 |
+
D10,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6
|
| 313 |
+
D11,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6 3 Nf3
|
| 314 |
+
D12,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 e3 Bf5
|
| 315 |
+
D13,"Queen's Gambit Declined Slav, Exchange Variation",1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 cxd5 cxd5
|
| 316 |
+
D14,"Queen's Gambit Declined Slav, Exchange Variation",1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 cxd5 cxd5 5 Nc3 Nc6 6 Bf4 Bf5
|
| 317 |
+
D15,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 Nc3
|
| 318 |
+
D16,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 Nc3 dxc4 5 a4
|
| 319 |
+
D17,Queen's Gambit Declined Slav,1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 Nc3 dxc4 5 a4 Bf5
|
| 320 |
+
D18,"Queen's Gambit Declined Slav, Dutch",1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 Nc3 dxc4 5 a4 Bf5 6 e3
|
| 321 |
+
D19,"Queen's Gambit Declined Slav, Dutch",1 d4 d5 2 c4 c6 3 Nf3 Nf6 4 Nc3 dxc4 5 a4 Bf5 6 e3 e6 7 Bxc4 Bb4 8 O-O O-O 9 Qe2
|
| 322 |
+
D20,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4
|
| 323 |
+
D21,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3
|
| 324 |
+
D22,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3 a6 4 e3 Bg4 5 Bxc4 e6 6 d5
|
| 325 |
+
D23,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3 Nf6
|
| 326 |
+
D24,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 Nc3
|
| 327 |
+
D25,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 e3
|
| 328 |
+
D26,Queen's Gambit Accepted,1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 e3 e6
|
| 329 |
+
D27,"Queen's Gambit Accepted, Classical",1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 e3 e6 5 Bxc4 c5 6 O-O a6
|
| 330 |
+
D28,"Queen's Gambit Accepted, Classical",1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 e3 e6 5 Bxc4 c5 6 O-O a6 7 Qe2
|
| 331 |
+
D29,"Queen's Gambit Accepted, Classical",1 d4 d5 2 c4 dxc4 3 Nf3 Nf6 4 e3 e6 5 Bxc4 c5 6 O-O a6 7 Qe2 b5 8 Bb3 Bb7
|
| 332 |
+
D30,Queen's Gambit Declined,1 d4 d5 2 c4 e6
|
| 333 |
+
D31,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3
|
| 334 |
+
D32,"Queen's Gambit Declined, Tarrasch",1 d4 d5 2 c4 e6 3 Nc3 c5
|
| 335 |
+
D33,"Queen's Gambit Declined, Tarrasch",1 d4 d5 2 c4 e6 3 Nc3 c5 4 cxd5 exd5 5 Nf3 Nc6 6 g3
|
| 336 |
+
D34,"Queen's Gambit Declined, Tarrasch",1 d4 d5 2 c4 e6 3 Nc3 c5 4 cxd5 exd5 5 Nf3 Nc6 6 g3 Nf6 7 Bg2 Be7
|
| 337 |
+
D35,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6
|
| 338 |
+
D36,"Queen's Gambit Declined, Exchange, Positional line, 6.Qc2",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 cxd5 exd5 5 Bg5 c6 6 Qc2
|
| 339 |
+
D37,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3
|
| 340 |
+
D38,"Queen's Gambit Declined, Ragozin Variation",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 Bb4
|
| 341 |
+
D39,"Queen's Gambit Declined, Ragozin, Vienna Variation",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 Bb4 5 Bg5 dxc4
|
| 342 |
+
D40,"Queen's Gambit Declined, Semi-Tarrasch",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c5
|
| 343 |
+
D41,"Queen's Gambit Declined, Semi-Tarrasch",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c5 5 cxd5
|
| 344 |
+
D42,"Queen's Gambit Declined, Semi-Tarrasch, 7.Bd3",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c5 5 cxd5 Nxd5 6 e3 Nc6 7 Bd3
|
| 345 |
+
D43,Queen's Gambit Declined Semi-Slav,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6
|
| 346 |
+
D44,Queen's Gambit Declined Semi-Slav,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 Bg5 dxc4
|
| 347 |
+
D45,Queen's Gambit Declined Semi-Slav,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 e3
|
| 348 |
+
D46,Queen's Gambit Declined Semi-Slav,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 e3 Nbd7 6 Bd3
|
| 349 |
+
D47,Queen's Gambit Declined Semi-Slav,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 e3 Nbd7 6 Bd3 dxc4 7 Bxc4
|
| 350 |
+
D48,"Queen's Gambit Declined Semi-Slav, Meran",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 e3 Nbd7 6 Bd3 dxc4 7 Bxc4 b5 8 Bd3 a6
|
| 351 |
+
D49,"Queen's Gambit Declined Semi-Slav, Meran",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Nf3 c6 5 e3 Nbd7 6 Bd3 dxc4 7 Bxc4 b5 8 Bd3 a6 9 e4 c5 10 e5 cxd4 11 Nxb5
|
| 352 |
+
D50,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5
|
| 353 |
+
D51,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Nbd7
|
| 354 |
+
D52,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Nbd7 5 e3 c6 6 Nf3
|
| 355 |
+
D53,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7
|
| 356 |
+
D54,"Queen's Gambit Declined, Anti-Neo-Orthodox Variation",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Rc1
|
| 357 |
+
D55,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3
|
| 358 |
+
D56,Queen's Gambit Declined,1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 h6 7 Bh4
|
| 359 |
+
D57,"Queen's Gambit Declined, Lasker Defense",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 h6 7 Bh4 Ne4 8 Bxe7 Qxe7
|
| 360 |
+
D58,"Queen's Gambit Declined, Tartakower (Makagonov-Bondarevsky) System",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 h6 7 Bh4 b6
|
| 361 |
+
D59,"Queen's Gambit Declined, Tartakower",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 h6 7 Bh4 b6 8 cxd5 Nxd5
|
| 362 |
+
D60,"Queen's Gambit Declined, Orthodox Defense",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7
|
| 363 |
+
D61,"Queen's Gambit Declined, Orthodox, Rubinstein Attack",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Qc2
|
| 364 |
+
D62,"Queen's Gambit Declined, Orthodox, Rubinstein Attack",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Qc2 c5 8 cxd5
|
| 365 |
+
D63,"Queen's Gambit Declined, Orthodox Defense",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1
|
| 366 |
+
D64,"Queen's Gambit Declined, Orthodox, Rubinstein Attack",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Qc2
|
| 367 |
+
D65,"Queen's Gambit Declined, Orthodox, Rubinstein Attack, Main line",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Qc2 a6 9 cxd5
|
| 368 |
+
D66,"Queen's Gambit Declined, Orthodox Defense, Bd3 line",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Bd3
|
| 369 |
+
D67,"Queen's Gambit Declined, Orthodox Defense, Bd3 line",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Bd3 dxc4 9 Bxc4 Nd5
|
| 370 |
+
D68,"Queen's Gambit Declined, Orthodox Defense, Classical",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Bd3 dxc4
|
| 371 |
+
D69,"Queen's Gambit Declined, Orthodox Defense, Classical, 13.de",1 d4 d5 2 c4 e6 3 Nc3 Nf6 4 Bg5 Be7 5 e3 O-O 6 Nf3 Nbd7 7 Rc1 c6 8 Bd3 dxc4
|
| 372 |
+
D70,Neo-Grunfeld Defense,1 d4 Nf6 2 c4 g6 3 f3 d5
|
| 373 |
+
D71,Neo-Grunfeld,1 d4 Nf6 2 c4 g6 3 g3 d5
|
| 374 |
+
D72,"Neo-Grunfeld, 5.cd, Main line",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 cxd5 Nxd5 6 e4 Nb6 7 Ne2
|
| 375 |
+
D73,"Neo-Grunfeld, 5.Nf3",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3
|
| 376 |
+
D74,"Neo-Grunfeld, 6.cd Nxd5, 7.O-O",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 cxd5 Nxd5 7 O-O
|
| 377 |
+
D75,"Neo-Grunfeld, 6.cd Nxd5, 7.O-O c5, 8.dxc5",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 cxd5 Nxd5 7 O-O c5 8 dxc5
|
| 378 |
+
D76,"Neo-Grunfeld, 6.cd Nxd5, 7.O-O Nb6",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 cxd5 Nxd5 7 O-O Nb6
|
| 379 |
+
D77,"Neo-Grunfeld, 6.O-O",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 O-O
|
| 380 |
+
D78,"Neo-Grunfeld, 6.O-O c6",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 O-O c6
|
| 381 |
+
D79,"Neo-Grunfeld, 6.O-O, Main line",1 d4 Nf6 2 c4 g6 3 g3 d5 4 Bg2 Bg7 5 Nf3 O-O 6 O-O c6 7 cxd5 cxd5
|
| 382 |
+
D80,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5
|
| 383 |
+
D81,"Grunfeld, Russian Variation",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Qb3
|
| 384 |
+
D82,"Grunfeld, 4.Bf4",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Bf4
|
| 385 |
+
D83,"Grunfeld, Grunfeld Gambit",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Bf4 Bg7 5 e3 O-O
|
| 386 |
+
D84,"Grunfeld, Grunfeld Gambit Accepted",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Bf4 Bg7 5 e3 O-O 6 cxd5 Nxd5 7 Nxd5 Qxd5 8 Bxc7
|
| 387 |
+
D85,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 cxd5 Nxd5
|
| 388 |
+
D86,"Grunfeld, Exchange",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 cxd5 Nxd5 5 e4 Nxc3 6 bxc3 Bg7 7 Bc4
|
| 389 |
+
D87,"Grunfeld, Exchange",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 cxd5 Nxd5 5 e4 Nxc3 6 bxc3 Bg7 7 Bc4 O-O 8 Ne2 c5
|
| 390 |
+
D88,"Grunfeld, Spassky Variation, Main line, 10...cd, 11.cd",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 cxd5 Nxd5 5 e4 Nxc3 6 bxc3 Bg7 7 Bc4 O-O 8 Ne2
|
| 391 |
+
D89,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 cxd5 Nxd5 5 e4 Nxc3 6 bxc3 Bg7 7 Bc4 O-O 8 Ne2
|
| 392 |
+
D90,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3
|
| 393 |
+
D91,"Grunfeld, 5.Bg5",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Bg5
|
| 394 |
+
D92,"Grunfeld, 5.Bf4",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Bf4
|
| 395 |
+
D93,"Grunfeld, with Bf4 & e3",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Bf4 O-O 6 e3
|
| 396 |
+
D94,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 e3
|
| 397 |
+
D95,Grunfeld,1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 e3 O-O 6 Qb3
|
| 398 |
+
D96,"Grunfeld, Russian Variation",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Qb3
|
| 399 |
+
D97,"Grunfeld, Russian",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Qb3 dxc4 6 Qxc4 O-O 7 e4
|
| 400 |
+
D98,"Grunfeld, Russian",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Qb3 dxc4 6 Qxc4 O-O 7 e4 Bg4
|
| 401 |
+
D99,"Grunfeld Defense, Smyslov",1 d4 Nf6 2 c4 g6 3 Nc3 d5 4 Nf3 Bg7 5 Qb3 dxc4 6 Qxc4 O-O 7 e4 Bg4 8 Be3
|
| 402 |
+
E00,Queen's Pawn Game,1 d4 Nf6 2 c4 e6
|
| 403 |
+
E01,"Catalan, Closed",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2
|
| 404 |
+
E02,"Catalan, Open, 5.Qa4",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 dxc4 5 Qa4+
|
| 405 |
+
E03,"Catalan, Open",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 dxc4 5 Qa4+ Nbd7 6 Qxc4
|
| 406 |
+
E04,"Catalan, Open, 5.Nf3",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 dxc4 5 Nf3
|
| 407 |
+
E05,"Catalan, Open, Classical line",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 dxc4 5 Nf3 Be7
|
| 408 |
+
E06,"Catalan, Closed, 5.Nf3",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 Be7 5 Nf3
|
| 409 |
+
E07,"Catalan, Closed",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 Be7 5 Nf3 O-O 6 O-O Nbd7
|
| 410 |
+
E08,"Catalan, Closed",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 Be7 5 Nf3 O-O 6 O-O Nbd7 7 Qc2
|
| 411 |
+
E09,"Catalan, Closed",1 d4 Nf6 2 c4 e6 3 g3 d5 4 Bg2 Be7 5 Nf3 O-O 6 O-O Nbd7 7 Qc2 c6 8 Nbd2
|
| 412 |
+
E10,Queen's Pawn Game,1 d4 Nf6 2 c4 e6 3 Nf3
|
| 413 |
+
E11,Bogo-Indian Defense,1 d4 Nf6 2 c4 e6 3 Nf3 Bb4+
|
| 414 |
+
E12,Queen's Indian,1 d4 Nf6 2 c4 e6 3 Nf3 b6
|
| 415 |
+
E13,"Queen's Indian, 4.Nc3, Main line",1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 Nc3 Bb7 5 Bg5 h6 6 Bh4 Bb4
|
| 416 |
+
E14,Queen's Indian,1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 e3
|
| 417 |
+
E15,Queen's Indian,1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 g3
|
| 418 |
+
E16,Queen's Indian,1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 g3 Bb7 5 Bg2 Bb4+
|
| 419 |
+
E17,Queen's Indian,1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 g3 Bb7 5 Bg2 Be7
|
| 420 |
+
E18,"Queen's Indian, Old Main line, 7.Nc3",1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 g3 Bb7 5 Bg2 Be7 6 O-O O-O 7 Nc3
|
| 421 |
+
E19,"Queen's Indian, Old Main line, 9.Qxc3",1 d4 Nf6 2 c4 e6 3 Nf3 b6 4 g3 Bb7 5 Bg2 Be7 6 O-O O-O 7 Nc3 Ne4 8 Qc2 Nxc3
|
| 422 |
+
E20,Nimzo-Indian,1 d4 Nf6 2 c4 e6 3 Nc3 Bb4
|
| 423 |
+
E21,"Nimzo-Indian, Three Knights",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Nf3
|
| 424 |
+
E22,"Nimzo-Indian, Spielmann Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qb3
|
| 425 |
+
E23,"Nimzo-Indian, Spielmann",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qb3 c5 5 dxc5 Nc6
|
| 426 |
+
E24,"Nimzo-Indian, Samisch",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3
|
| 427 |
+
E25,"Nimzo-Indian, Samisch",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3 c5 6 f3 d5 7 cxd5
|
| 428 |
+
E26,"Nimzo-Indian, Samisch",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3 c5 6 e3
|
| 429 |
+
E27,"Nimzo-Indian, Samisch Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3 O-O
|
| 430 |
+
E28,"Nimzo-Indian, Samisch Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3 O-O 6 e3
|
| 431 |
+
E29,"Nimzo-Indian, Samisch",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 a3 Bxc3+ 5 bxc3 O-O 6 e3 c5 7 Bd3 Nc6
|
| 432 |
+
E30,"Nimzo-Indian, Leningrad",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Bg5
|
| 433 |
+
E31,"Nimzo-Indian, Leningrad, Main line",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Bg5 h6 5 Bh4 c5 6 d5 d6
|
| 434 |
+
E32,"Nimzo-Indian, Classical",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2
|
| 435 |
+
E33,"Nimzo-Indian, Classical",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 Nc6
|
| 436 |
+
E34,"Nimzo-Indian, Classical, Noa Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 d5
|
| 437 |
+
E35,"Nimzo-Indian, Classical, Noa Variation, 5.cd ed",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 d5 5 cxd5 exd5
|
| 438 |
+
E36,"Nimzo-Indian, Classical",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 d5 5 a3
|
| 439 |
+
E37,"Nimzo-Indian, Classical",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 d5 5 a3 Bxc3+ 6 Qxc3 Ne4 7 Qc2
|
| 440 |
+
E38,"Nimzo-Indian, Classical, 4...c5",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 c5
|
| 441 |
+
E39,"Nimzo-Indian, Classical, Pirc Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 Qc2 c5 5 dxc5 O-O
|
| 442 |
+
E40,"Nimzo-Indian, 4.e3",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3
|
| 443 |
+
E41,Nimzo-Indian,1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 c5
|
| 444 |
+
E42,"Nimzo-Indian, 4.e3 c5, 5.Ne2 (Rubinstein)",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 c5 5 Ne2
|
| 445 |
+
E43,"Nimzo-Indian, Fischer Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 b6
|
| 446 |
+
E44,"Nimzo-Indian, Fischer Variation, 5.Ne2",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 b6 5 Ne2
|
| 447 |
+
E45,"Nimzo-Indian, 4.e3, Bronstein (Byrne) Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 b6 5 Ne2 Ba6
|
| 448 |
+
E46,Nimzo-Indian,1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O
|
| 449 |
+
E47,"Nimzo-Indian, 4.e3 O-O 5.Bd3",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Bd3
|
| 450 |
+
E48,"Nimzo-Indian, 4.e3 O-O 5.Bd3 d5",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Bd3 d5
|
| 451 |
+
E49,"Nimzo-Indian, 4.e3, Botvinnik System",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Bd3 d5 6 a3 Bxc3+ 7 bxc3
|
| 452 |
+
E50,"Nimzo-Indian, 4.e3 O-O 5.Nf3, without ...d5",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3
|
| 453 |
+
E51,"Nimzo-Indian, 4.e3",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5
|
| 454 |
+
E52,"Nimzo-Indian, 4.e3, Main line with ...b6",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 b6
|
| 455 |
+
E53,"Nimzo-Indian, 4.e3",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5
|
| 456 |
+
E54,"Nimzo-Indian, 4.e3, Gligoric System",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O dxc4 8 Bxc4
|
| 457 |
+
E55,"Nimzo-Indian, 4.e3, Gligoric System, Bronstein Variation",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O dxc4 8 Bxc4 Nbd7
|
| 458 |
+
E56,"Nimzo-Indian, 4.e3, Main line with 7...Nc6",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O Nc6
|
| 459 |
+
E57,"Nimzo-Indian, 4.e3, Main line with 8...dc and 9...cd",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O Nc6 8 a3 dxc4 9 Bxc4
|
| 460 |
+
E58,"Nimzo-Indian, 4.e3, Main line with 8...Bxc3",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O Nc6 8 a3 Bxc3 9 bxc3
|
| 461 |
+
E59,"Nimzo-Indian, 4.e3, Main line",1 d4 Nf6 2 c4 e6 3 Nc3 Bb4 4 e3 O-O 5 Nf3 d5 6 Bd3 c5 7 O-O Nc6 8 a3 Bxc3 9 bxc3 dxc4 10 Bxc4
|
| 462 |
+
E60,King's Indian Defense,1 d4 Nf6 2 c4 g6
|
| 463 |
+
E61,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3
|
| 464 |
+
E62,"King's Indian, Fianchetto",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3
|
| 465 |
+
E63,"King's Indian, Fianchetto, Panno Variation",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 Nc6 7 O-O a6
|
| 466 |
+
E64,"King's Indian, Fianchetto, Yugoslav System",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 c5
|
| 467 |
+
E65,"King's Indian, Fianchetto, Yugoslav, 7.O-O",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 c5 7 O-O
|
| 468 |
+
E66,"King's Indian, Fianchetto, Yugoslav Panno",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 c5 7 O-O Nc6 8 d5
|
| 469 |
+
E67,"King's Indian, Fianchetto",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 Nbd7
|
| 470 |
+
E68,"King's Indian, Fianchetto, Classical Variation, 8.e4",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 Nbd7 7 O-O e5 8 e4
|
| 471 |
+
E69,"King's Indian, Fianchetto, Classical Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 Nf3 d6 5 g3 O-O 6 Bg2 Nbd7 7 O-O e5 8 e4 c6 9 h3
|
| 472 |
+
E70,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4
|
| 473 |
+
E71,"King's Indian, Makagonov System (5.h3)",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 h3
|
| 474 |
+
E72,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 g3
|
| 475 |
+
E73,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Be2
|
| 476 |
+
E74,"King's Indian, Averbakh, 6...c5",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Be2 O-O 6 Bg5 c5
|
| 477 |
+
E75,"King's Indian, Averbakh, Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Be2 O-O 6 Bg5 c5 7 d5 e6
|
| 478 |
+
E76,"King's Indian, Four Pawns Attack",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f4
|
| 479 |
+
E77,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f4 O-O 6 Be2
|
| 480 |
+
E78,"King's Indian, Four Pawns Attack, with Be2 and Nf3",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f4 O-O 6 Be2 c5 7 Nf3
|
| 481 |
+
E79,"King's Indian, Four Pawns Attack, Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f4 O-O 6 Be2 c5 7 Nf3 cxd4 8 Nxd4 Nc6 9 Be3
|
| 482 |
+
E80,"King's Indian, Samisch Variation",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3
|
| 483 |
+
E81,"King's Indian, Samisch",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O
|
| 484 |
+
E82,"King's Indian, Samisch, double Fianchetto Variation",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 b6
|
| 485 |
+
E83,"King's Indian, Samisch",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 Nc6
|
| 486 |
+
E84,"King's Indian, Samisch, Panno Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 Nc6 7 Nge2 a6 8 Qd2 Rb8
|
| 487 |
+
E85,"King's Indian, Samisch, Orthodox Variation",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 e5
|
| 488 |
+
E86,"King's Indian, Samisch, Orthodox, 7.Nge2 c6",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 e5 7 Nge2 c6
|
| 489 |
+
E87,"King's Indian, Samisch, Orthodox",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 e5 7 d5
|
| 490 |
+
E88,"King's Indian, Samisch, Orthodox, 7.d5 c6",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 e5 7 d5 c6
|
| 491 |
+
E89,"King's Indian, Samisch, Orthodox Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 f3 O-O 6 Be3 e5 7 d5 c6 8 Nge2 cxd5
|
| 492 |
+
E90,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3
|
| 493 |
+
E91,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2
|
| 494 |
+
E92,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5
|
| 495 |
+
E93,"King's Indian, Petrosian System",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 d5 Nbd7
|
| 496 |
+
E94,"King's Indian, Orthodox",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O
|
| 497 |
+
E95,"King's Indian, Orthodox, 7...Nbd7, 8.Re1",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O Nbd7 8 Re1
|
| 498 |
+
E96,"King's Indian, Orthodox, 7...Nbd7, Main line",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O Nbd7 8 Re1 c6 9 Bf1 a5
|
| 499 |
+
E97,King's Indian,1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O Nc6
|
| 500 |
+
E98,"King's Indian, Orthodox, Taimanov, 9.Ne1",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O Nc6 8 d5 Ne7 9 Ne1
|
| 501 |
+
E99,"King's Indian, Orthodox, Taimanov",1 d4 Nf6 2 c4 g6 3 Nc3 Bg7 4 e4 d6 5 Nf3 O-O 6 Be2 e5 7 O-O Nc6 8 d5 Ne7 9 Ne1 Nd7 10 f3 f5
|
app.py
CHANGED
|
@@ -1,17 +1,14 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import chess
|
| 3 |
import chess.pgn
|
| 4 |
-
import chess.svg
|
| 5 |
import io
|
| 6 |
import requests
|
| 7 |
import google.generativeai as genai
|
| 8 |
-
from collections import
|
| 9 |
import os
|
| 10 |
import time
|
| 11 |
-
import re
|
| 12 |
-
import chess.polyglot
|
| 13 |
import logging
|
| 14 |
-
|
| 15 |
|
| 16 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 17 |
logger = logging.getLogger(__name__)
|
|
@@ -20,34 +17,54 @@ GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
|
|
| 20 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 21 |
model = genai.GenerativeModel('gemini-2.0-flash-exp')
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
def get_user_games_from_chess_com(username):
|
| 24 |
try:
|
| 25 |
-
logger.info(f"
|
| 26 |
-
|
| 27 |
-
username = username_original.lower()
|
| 28 |
|
| 29 |
user_url = f"https://api.chess.com/pub/player/{username}"
|
| 30 |
response = requests.get(user_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 31 |
|
| 32 |
if response.status_code != 200:
|
| 33 |
-
|
| 34 |
-
return None, f"β Foydalanuvchi topilmadi: {username}. Chess.com'da mavjudligini tekshiring."
|
| 35 |
|
| 36 |
-
logger.info(f"User found: {username}")
|
| 37 |
archives_url = f"https://api.chess.com/pub/player/{username}/games/archives"
|
| 38 |
response = requests.get(archives_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 39 |
|
| 40 |
if response.status_code != 200:
|
| 41 |
-
logger.error("Archives not found")
|
| 42 |
return None, "β O'yinlar arxivi topilmadi."
|
| 43 |
|
| 44 |
archives = response.json()['archives']
|
| 45 |
if not archives:
|
| 46 |
-
logger.error("No archives available")
|
| 47 |
return None, "β O'yinlar topilmadi."
|
| 48 |
|
| 49 |
-
logger.info(f"Found {len(archives)} archives")
|
| 50 |
-
|
| 51 |
all_games = []
|
| 52 |
for archive_url in reversed(archives[-3:]):
|
| 53 |
time.sleep(0.3)
|
|
@@ -55,22 +72,16 @@ def get_user_games_from_chess_com(username):
|
|
| 55 |
if response.status_code == 200:
|
| 56 |
games = response.json()['games']
|
| 57 |
all_games.extend(games)
|
| 58 |
-
logger.info(f"Fetched {len(games)} games from archive")
|
| 59 |
if len(all_games) >= 50:
|
| 60 |
break
|
| 61 |
|
| 62 |
-
logger.info(f"Total games fetched: {len(all_games)}")
|
| 63 |
-
|
| 64 |
rapid_games = [g for g in all_games if g.get('time_class') in ['rapid', 'blitz']]
|
| 65 |
if not rapid_games:
|
| 66 |
rapid_games = all_games[:50]
|
| 67 |
|
| 68 |
pgn_list = [g['pgn'] for g in rapid_games[:50] if 'pgn' in g]
|
| 69 |
|
| 70 |
-
logger.info(f"Total PGN games prepared: {len(pgn_list)}")
|
| 71 |
-
|
| 72 |
if not pgn_list:
|
| 73 |
-
logger.error("No PGN games found")
|
| 74 |
return None, "β PGN formatdagi o'yinlar topilmadi."
|
| 75 |
|
| 76 |
return pgn_list, None
|
|
@@ -80,39 +91,31 @@ def get_user_games_from_chess_com(username):
|
|
| 80 |
return None, f"β Xatolik: {str(e)}"
|
| 81 |
|
| 82 |
def parse_pgn_content(pgn_content):
|
| 83 |
-
logger.info("Starting to parse PGN content")
|
| 84 |
games = []
|
| 85 |
if isinstance(pgn_content, list):
|
| 86 |
-
for
|
| 87 |
try:
|
| 88 |
game = chess.pgn.read_game(io.StringIO(pgn_text))
|
| 89 |
if game:
|
| 90 |
games.append(game)
|
| 91 |
-
except
|
| 92 |
-
logger.warning(f"Failed to parse game {idx}: {str(e)}")
|
| 93 |
pass
|
| 94 |
else:
|
| 95 |
pgn_io = io.StringIO(pgn_content)
|
| 96 |
-
idx = 0
|
| 97 |
while True:
|
| 98 |
try:
|
| 99 |
game = chess.pgn.read_game(pgn_io)
|
| 100 |
if game is None:
|
| 101 |
break
|
| 102 |
games.append(game)
|
| 103 |
-
|
| 104 |
-
except Exception as e:
|
| 105 |
-
logger.warning(f"Failed to parse game {idx}: {str(e)}")
|
| 106 |
break
|
| 107 |
|
| 108 |
-
logger.info(f"Successfully parsed {len(games)} games")
|
| 109 |
return games
|
| 110 |
|
| 111 |
-
|
| 112 |
def analyze_game_detailed(game, username):
|
| 113 |
board = game.board()
|
| 114 |
mistakes = []
|
| 115 |
-
|
| 116 |
move_number = 0
|
| 117 |
|
| 118 |
white_player = game.headers.get("White", "").strip().lower()
|
|
@@ -128,15 +131,12 @@ def analyze_game_detailed(game, username):
|
|
| 128 |
result = game.headers.get("Result", "*")
|
| 129 |
opening = detect_opening(game)
|
| 130 |
|
| 131 |
-
user_won = None
|
| 132 |
user_result = None
|
| 133 |
if user_color is not None and result != "*":
|
| 134 |
if result == "1-0":
|
| 135 |
-
|
| 136 |
-
user_result = "win" if user_won else "loss"
|
| 137 |
elif result == "0-1":
|
| 138 |
-
|
| 139 |
-
user_result = "win" if user_won else "loss"
|
| 140 |
elif result == "1/2-1/2":
|
| 141 |
user_result = "draw"
|
| 142 |
|
|
@@ -198,10 +198,7 @@ def analyze_game_detailed(game, username):
|
|
| 198 |
}
|
| 199 |
|
| 200 |
def categorize_mistakes(all_analyses):
|
| 201 |
-
logger.info("Categorizing mistakes from all games")
|
| 202 |
-
|
| 203 |
if not all_analyses:
|
| 204 |
-
logger.warning("No analyses provided for categorization")
|
| 205 |
return []
|
| 206 |
|
| 207 |
blunders = 0
|
|
@@ -232,12 +229,7 @@ def categorize_mistakes(all_analyses):
|
|
| 232 |
|
| 233 |
total = blunders + regular_mistakes + hanging + opening + middlegame + endgame
|
| 234 |
|
| 235 |
-
logger.info(f"Total mistakes found: {total}")
|
| 236 |
-
logger.info(f"Blunders: {blunders}, Mistakes: {regular_mistakes}, Hanging: {hanging}")
|
| 237 |
-
logger.info(f"Opening: {opening}, Middlegame: {middlegame}, Endgame: {endgame}")
|
| 238 |
-
|
| 239 |
if total == 0:
|
| 240 |
-
logger.warning("No mistakes found in any game")
|
| 241 |
return []
|
| 242 |
|
| 243 |
weaknesses = []
|
|
@@ -286,125 +278,26 @@ def categorize_mistakes(all_analyses):
|
|
| 286 |
|
| 287 |
weaknesses.sort(key=lambda x: x['count'], reverse=True)
|
| 288 |
|
| 289 |
-
logger.info(f"Total weakness categories: {len(weaknesses)}")
|
| 290 |
return weaknesses
|
| 291 |
|
| 292 |
-
import json
|
| 293 |
-
|
| 294 |
def fetch_lichess_puzzles(themes, count=5):
|
| 295 |
-
logger.info(f"Fetching {count} puzzles for themes: {themes}")
|
| 296 |
puzzles = []
|
| 297 |
|
| 298 |
-
theme_map = {
|
| 299 |
-
"Qo'pol xatolar": ['hangingPiece', 'discoveredAttack', 'fork'],
|
| 300 |
-
'Kichik xatolar': ['advantage', 'crushing', 'attackingF2F7'],
|
| 301 |
-
'Himoyasiz qoldirish': ['hangingPiece', 'pin', 'skewer'],
|
| 302 |
-
'Debyut xatolari': ['opening', 'short', 'middlegame'],
|
| 303 |
-
"O'rta o'yin xatolari": ['middlegame', 'attackingF2F7', 'advancedPawn'],
|
| 304 |
-
'Endshpil xatolari': ['endgame', 'queenEndgame', 'rookEndgame']
|
| 305 |
-
}
|
| 306 |
-
|
| 307 |
-
lichess_themes = []
|
| 308 |
-
for theme_name in themes:
|
| 309 |
-
if theme_name in theme_map:
|
| 310 |
-
lichess_themes.extend(theme_map[theme_name])
|
| 311 |
-
|
| 312 |
-
lichess_themes = list(set(lichess_themes))[:3]
|
| 313 |
-
logger.info(f"Selected Lichess themes: {lichess_themes}")
|
| 314 |
-
|
| 315 |
try:
|
| 316 |
-
|
| 317 |
-
for
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
response = requests.get(url, timeout=10, headers={
|
| 324 |
-
'User-Agent': 'Mozilla/5.0',
|
| 325 |
-
'Accept': 'application/x-ndjson'
|
| 326 |
})
|
| 327 |
-
|
| 328 |
-
if response.status_code == 200:
|
| 329 |
-
# Parse NDJSON (newline-delimited JSON)
|
| 330 |
-
lines = response.text.strip().split('\n')
|
| 331 |
-
for line in lines:
|
| 332 |
-
if len(puzzles) >= count:
|
| 333 |
-
break
|
| 334 |
-
if not line.strip():
|
| 335 |
-
continue
|
| 336 |
-
try:
|
| 337 |
-
puzzle_data = json.loads(line) # Use json.loads instead of eval
|
| 338 |
-
game_data = puzzle_data.get('game', {})
|
| 339 |
-
puzzle_info = puzzle_data.get('puzzle', {})
|
| 340 |
-
|
| 341 |
-
puzzle_id = puzzle_info.get('id', '')
|
| 342 |
-
|
| 343 |
-
if puzzle_id and not any(p['id'] == puzzle_id for p in puzzles):
|
| 344 |
-
puzzles.append({
|
| 345 |
-
'id': puzzle_id,
|
| 346 |
-
'fen': game_data.get('fen', ''),
|
| 347 |
-
'moves': ' '.join(puzzle_info.get('solution', [])),
|
| 348 |
-
'solution': puzzle_info.get('solution', []),
|
| 349 |
-
'rating': puzzle_info.get('rating', 1500),
|
| 350 |
-
'themes': puzzle_info.get('themes', []),
|
| 351 |
-
'url': f"https://lichess.org/training/{puzzle_id}"
|
| 352 |
-
})
|
| 353 |
-
logger.info(f"Added puzzle {puzzle_id} with rating {puzzle_info.get('rating')}")
|
| 354 |
-
except json.JSONDecodeError as e:
|
| 355 |
-
logger.warning(f"Failed to parse puzzle line: {str(e)}")
|
| 356 |
-
except Exception as e:
|
| 357 |
-
logger.warning(f"Error processing puzzle: {str(e)}")
|
| 358 |
-
|
| 359 |
-
time.sleep(0.3)
|
| 360 |
except Exception as e:
|
| 361 |
-
logger.error(f"Error
|
| 362 |
-
|
| 363 |
-
# Fill remaining with daily puzzle if needed
|
| 364 |
-
if len(puzzles) < count:
|
| 365 |
-
try:
|
| 366 |
-
url = "https://lichess.org/api/puzzle/daily"
|
| 367 |
-
response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 368 |
-
|
| 369 |
-
if response.status_code == 200:
|
| 370 |
-
daily_data = response.json()
|
| 371 |
-
game_data = daily_data.get('game', {})
|
| 372 |
-
puzzle_info = daily_data.get('puzzle', {})
|
| 373 |
-
puzzle_id = puzzle_info.get('id', '')
|
| 374 |
-
|
| 375 |
-
if puzzle_id and not any(p['id'] == puzzle_id for p in puzzles):
|
| 376 |
-
puzzles.append({
|
| 377 |
-
'id': puzzle_id,
|
| 378 |
-
'fen': game_data.get('fen', ''),
|
| 379 |
-
'moves': ' '.join(puzzle_info.get('solution', [])),
|
| 380 |
-
'solution': puzzle_info.get('solution', []),
|
| 381 |
-
'rating': puzzle_info.get('rating', 1500),
|
| 382 |
-
'themes': puzzle_info.get('themes', []),
|
| 383 |
-
'url': f"https://lichess.org/training/{puzzle_id}"
|
| 384 |
-
})
|
| 385 |
-
logger.info(f"Added daily puzzle {puzzle_id}")
|
| 386 |
-
except Exception as e:
|
| 387 |
-
logger.error(f"Error fetching daily puzzle: {str(e)}")
|
| 388 |
-
|
| 389 |
-
# Fill with fallback training links if still not enough
|
| 390 |
-
while len(puzzles) < count:
|
| 391 |
-
puzzles.append({
|
| 392 |
-
'id': f'training_{len(puzzles)+1}',
|
| 393 |
-
'fen': '',
|
| 394 |
-
'moves': '',
|
| 395 |
-
'solution': [],
|
| 396 |
-
'rating': 1500,
|
| 397 |
-
'themes': ['Mixed'],
|
| 398 |
-
'url': "https://lichess.org/training"
|
| 399 |
-
})
|
| 400 |
-
logger.info(f"Added fallback puzzle link {len(puzzles)}")
|
| 401 |
|
| 402 |
-
|
| 403 |
-
return puzzles[:count]
|
| 404 |
|
| 405 |
def get_comprehensive_analysis(weaknesses, opening_stats, color_stats, total_games):
|
| 406 |
-
logger.info("Generating AI comprehensive analysis")
|
| 407 |
-
|
| 408 |
weakness_text = "\n".join([f"- {w['category']}: {w['count']} marta ({w['percentage']:.1f}%)" for w in weaknesses])
|
| 409 |
|
| 410 |
opening_text = "\n".join([f"- {opening}: {stats['total']} o'yin (G'alabalar: {stats['wins']}, Yutqazishlar: {stats['losses']}, Duranglar: {stats['draws']})"
|
|
@@ -450,33 +343,27 @@ MUHIM: Javobni FAQAT O'ZBEK TILIDA yozing! Aniq va amaliy maslahatlar bering."""
|
|
| 450 |
|
| 451 |
try:
|
| 452 |
response = model.generate_content(prompt)
|
| 453 |
-
logger.info("AI analysis generated successfully")
|
| 454 |
return response.text
|
| 455 |
except Exception as e:
|
| 456 |
logger.error(f"AI analysis failed: {str(e)}")
|
| 457 |
return f"AI tahlil hozircha mavjud emas: {str(e)}"
|
| 458 |
|
| 459 |
def analyze_games(username_chesscom, pgn_file, username_pgn):
|
| 460 |
-
logger.info("=== Starting game analysis ===")
|
| 461 |
actual_username = None
|
| 462 |
pgn_content = None
|
| 463 |
|
| 464 |
if username_chesscom:
|
| 465 |
pgn_content, error = get_user_games_from_chess_com(username_chesscom)
|
| 466 |
if error:
|
| 467 |
-
logger.error(f"Failed to fetch games: {error}")
|
| 468 |
return error, "", "", "", None, None, None, None, None
|
| 469 |
actual_username = username_chesscom
|
| 470 |
|
| 471 |
-
# PGN file upload
|
| 472 |
elif pgn_file:
|
| 473 |
-
logger.info("Processing uploaded PGN file")
|
| 474 |
pgn_content = pgn_file.decode('utf-8') if isinstance(pgn_file, bytes) else pgn_file
|
| 475 |
|
| 476 |
if username_pgn and username_pgn.strip():
|
| 477 |
actual_username = username_pgn.strip()
|
| 478 |
else:
|
| 479 |
-
# Try to extract username from first game headers
|
| 480 |
try:
|
| 481 |
first_game = chess.pgn.read_game(io.StringIO(pgn_content))
|
| 482 |
if first_game:
|
|
@@ -487,21 +374,15 @@ def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
| 487 |
actual_username = "Player"
|
| 488 |
except:
|
| 489 |
actual_username = "Player"
|
| 490 |
-
|
| 491 |
-
logger.info(f"Extracted username from PGN: {actual_username}")
|
| 492 |
|
| 493 |
else:
|
| 494 |
-
logger.error("No username or file provided")
|
| 495 |
return "β Chess.com foydalanuvchi nomini kiriting yoki PGN faylni yuklang", "", "", "", None, None, None, None, None
|
| 496 |
|
| 497 |
games = parse_pgn_content(pgn_content)
|
| 498 |
|
| 499 |
if not games:
|
| 500 |
-
logger.error("No games parsed")
|
| 501 |
return "β O'yinlar topilmadi yoki tahlil qilinmadi", "", "", "", None, None, None, None, None
|
| 502 |
|
| 503 |
-
logger.info(f"Analyzing {len(games)} games")
|
| 504 |
-
|
| 505 |
all_analyses = []
|
| 506 |
opening_stats = defaultdict(lambda: {'wins': 0, 'losses': 0, 'draws': 0, 'total': 0})
|
| 507 |
color_stats = {
|
|
@@ -509,8 +390,7 @@ def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
| 509 |
'black': {'wins': 0, 'losses': 0, 'draws': 0}
|
| 510 |
}
|
| 511 |
|
| 512 |
-
for
|
| 513 |
-
logger.info(f"Analyzing game {idx + 1}/{len(games)}")
|
| 514 |
analysis = analyze_game_detailed(game, actual_username)
|
| 515 |
all_analyses.append(analysis)
|
| 516 |
|
|
@@ -518,8 +398,6 @@ def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
| 518 |
user_result = analysis.get('user_result')
|
| 519 |
user_color = analysis['user_color']
|
| 520 |
|
| 521 |
-
logger.info(f"Game {idx + 1}: {opening}, Result: {user_result}, Color: {user_color}")
|
| 522 |
-
|
| 523 |
if user_color is not None:
|
| 524 |
opening_stats[opening]['total'] += 1
|
| 525 |
|
|
@@ -536,15 +414,12 @@ def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
| 536 |
color_key = 'white' if user_color == chess.WHITE else 'black'
|
| 537 |
color_stats[color_key]['draws'] += 1
|
| 538 |
|
| 539 |
-
logger.info("Categorizing mistakes")
|
| 540 |
weaknesses = categorize_mistakes(all_analyses)
|
| 541 |
|
| 542 |
all_mistakes = []
|
| 543 |
for analysis in all_analyses:
|
| 544 |
all_mistakes.extend(analysis.get('mistakes', []))
|
| 545 |
|
| 546 |
-
logger.info(f"Total mistakes collected: {len(all_mistakes)}")
|
| 547 |
-
|
| 548 |
stats_report = f"## π {len(games)} ta o'yin tahlili\n\n"
|
| 549 |
stats_report += f"**Jami xatolar:** {len(all_mistakes)} ta\n\n"
|
| 550 |
|
|
@@ -589,28 +464,19 @@ def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
| 589 |
|
| 590 |
full_report = stats_report + opening_report + color_report
|
| 591 |
|
| 592 |
-
logger.info("Generating AI analysis")
|
| 593 |
ai_analysis = get_comprehensive_analysis(weaknesses, opening_stats, color_stats, len(games))
|
| 594 |
ai_report = f"## π€ AI Murabbiy: To'liq Tahlil va O'quv Rejasi\n\n{ai_analysis}"
|
| 595 |
|
| 596 |
weakness_themes = [w['category'] for w in weaknesses[:3]]
|
| 597 |
-
logger.info(f"Fetching puzzles for themes: {weakness_themes}")
|
| 598 |
puzzles = fetch_lichess_puzzles(weakness_themes, count=5)
|
| 599 |
|
| 600 |
puzzle_text = "## π§© Sizning shaxsiy masalalaringiz\n\n"
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
puzzle_text += f"**Puzzle {i}: {theme}** (Rating: {rating})\n"
|
| 608 |
-
puzzle_text += f"- [Solve on Lichess]({url})\n"
|
| 609 |
-
puzzle_text += f"- Position: `{fen}...`\n\n"
|
| 610 |
-
else:
|
| 611 |
-
puzzle_text += "- Masalalarni [Lichess.org](https://lichess.org/training) saytidan ishlang\n"
|
| 612 |
-
|
| 613 |
-
logger.info("=== Analysis completed successfully ===")
|
| 614 |
|
| 615 |
return (
|
| 616 |
full_report,
|
|
@@ -633,14 +499,14 @@ with gr.Blocks(title="Chess Study Plan Pro", theme=gr.themes.Soft()) as demo:
|
|
| 633 |
- π― Zaif tomonlar tahlili
|
| 634 |
- π€ AI murabbiy tavsiyalari
|
| 635 |
- π Kitoblar va kurslar tavsiyasi
|
| 636 |
-
- π§©
|
| 637 |
""")
|
| 638 |
|
| 639 |
with gr.Row():
|
| 640 |
with gr.Column():
|
| 641 |
-
gr.Markdown("### π
|
| 642 |
username_chesscom = gr.Textbox(
|
| 643 |
-
label="
|
| 644 |
placeholder="Foydalanuvchi nomini kiriting",
|
| 645 |
)
|
| 646 |
|
|
@@ -701,14 +567,14 @@ with gr.Blocks(title="Chess Study Plan Pro", theme=gr.themes.Soft()) as demo:
|
|
| 701 |
gr.Markdown("""
|
| 702 |
---
|
| 703 |
### π Qanday foydalanish:
|
| 704 |
-
- **
|
| 705 |
- **Lichess:** Profile β Games β Export orqali PGN faylni yuklang
|
| 706 |
-
- **Masalalar:**
|
| 707 |
|
| 708 |
-
### π―
|
| 709 |
- β
Debyut statistikasi (qaysi debyutlarda yaxshi/yomon o'ynaysiz)
|
| 710 |
- β
Oq/Qora rang bo'yicha natijalar
|
| 711 |
-
- β
|
| 712 |
- β
Shaxsiy o'quv rejasi (kundalik mashg'ulotlar)
|
| 713 |
- β
Kitoblar va kurslar tavsiyasi
|
| 714 |
""")
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import chess
|
| 3 |
import chess.pgn
|
|
|
|
| 4 |
import io
|
| 5 |
import requests
|
| 6 |
import google.generativeai as genai
|
| 7 |
+
from collections import defaultdict
|
| 8 |
import os
|
| 9 |
import time
|
|
|
|
|
|
|
| 10 |
import logging
|
| 11 |
+
import csv
|
| 12 |
|
| 13 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 14 |
logger = logging.getLogger(__name__)
|
|
|
|
| 17 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 18 |
model = genai.GenerativeModel('gemini-2.0-flash-exp')
|
| 19 |
|
| 20 |
+
def load_opening_database():
|
| 21 |
+
openings = {}
|
| 22 |
+
try:
|
| 23 |
+
with open('Chess Opening Reference - Sheet1.csv', 'r', encoding='utf-8') as f:
|
| 24 |
+
reader = csv.DictReader(f)
|
| 25 |
+
for row in reader:
|
| 26 |
+
eco = row.get('ECO Code', '').strip()
|
| 27 |
+
name = row.get('Name', '').strip()
|
| 28 |
+
if eco and name:
|
| 29 |
+
openings[eco] = name
|
| 30 |
+
except Exception as e:
|
| 31 |
+
logger.error(f"Failed to load openings CSV: {e}")
|
| 32 |
+
return openings
|
| 33 |
+
|
| 34 |
+
OPENING_DB = load_opening_database()
|
| 35 |
+
|
| 36 |
+
def detect_opening(game):
|
| 37 |
+
eco = game.headers.get("ECO", "")
|
| 38 |
+
opening = game.headers.get("Opening", "")
|
| 39 |
+
|
| 40 |
+
if eco and eco in OPENING_DB:
|
| 41 |
+
return OPENING_DB[eco]
|
| 42 |
+
elif opening:
|
| 43 |
+
return opening
|
| 44 |
+
else:
|
| 45 |
+
return "Unknown Opening"
|
| 46 |
+
|
| 47 |
def get_user_games_from_chess_com(username):
|
| 48 |
try:
|
| 49 |
+
logger.info(f"Fetching games for: {username}")
|
| 50 |
+
username = username.strip().lower()
|
|
|
|
| 51 |
|
| 52 |
user_url = f"https://api.chess.com/pub/player/{username}"
|
| 53 |
response = requests.get(user_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 54 |
|
| 55 |
if response.status_code != 200:
|
| 56 |
+
return None, f"β Foydalanuvchi topilmadi: {username}"
|
|
|
|
| 57 |
|
|
|
|
| 58 |
archives_url = f"https://api.chess.com/pub/player/{username}/games/archives"
|
| 59 |
response = requests.get(archives_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 60 |
|
| 61 |
if response.status_code != 200:
|
|
|
|
| 62 |
return None, "β O'yinlar arxivi topilmadi."
|
| 63 |
|
| 64 |
archives = response.json()['archives']
|
| 65 |
if not archives:
|
|
|
|
| 66 |
return None, "β O'yinlar topilmadi."
|
| 67 |
|
|
|
|
|
|
|
| 68 |
all_games = []
|
| 69 |
for archive_url in reversed(archives[-3:]):
|
| 70 |
time.sleep(0.3)
|
|
|
|
| 72 |
if response.status_code == 200:
|
| 73 |
games = response.json()['games']
|
| 74 |
all_games.extend(games)
|
|
|
|
| 75 |
if len(all_games) >= 50:
|
| 76 |
break
|
| 77 |
|
|
|
|
|
|
|
| 78 |
rapid_games = [g for g in all_games if g.get('time_class') in ['rapid', 'blitz']]
|
| 79 |
if not rapid_games:
|
| 80 |
rapid_games = all_games[:50]
|
| 81 |
|
| 82 |
pgn_list = [g['pgn'] for g in rapid_games[:50] if 'pgn' in g]
|
| 83 |
|
|
|
|
|
|
|
| 84 |
if not pgn_list:
|
|
|
|
| 85 |
return None, "β PGN formatdagi o'yinlar topilmadi."
|
| 86 |
|
| 87 |
return pgn_list, None
|
|
|
|
| 91 |
return None, f"β Xatolik: {str(e)}"
|
| 92 |
|
| 93 |
def parse_pgn_content(pgn_content):
|
|
|
|
| 94 |
games = []
|
| 95 |
if isinstance(pgn_content, list):
|
| 96 |
+
for pgn_text in pgn_content:
|
| 97 |
try:
|
| 98 |
game = chess.pgn.read_game(io.StringIO(pgn_text))
|
| 99 |
if game:
|
| 100 |
games.append(game)
|
| 101 |
+
except:
|
|
|
|
| 102 |
pass
|
| 103 |
else:
|
| 104 |
pgn_io = io.StringIO(pgn_content)
|
|
|
|
| 105 |
while True:
|
| 106 |
try:
|
| 107 |
game = chess.pgn.read_game(pgn_io)
|
| 108 |
if game is None:
|
| 109 |
break
|
| 110 |
games.append(game)
|
| 111 |
+
except:
|
|
|
|
|
|
|
| 112 |
break
|
| 113 |
|
|
|
|
| 114 |
return games
|
| 115 |
|
|
|
|
| 116 |
def analyze_game_detailed(game, username):
|
| 117 |
board = game.board()
|
| 118 |
mistakes = []
|
|
|
|
| 119 |
move_number = 0
|
| 120 |
|
| 121 |
white_player = game.headers.get("White", "").strip().lower()
|
|
|
|
| 131 |
result = game.headers.get("Result", "*")
|
| 132 |
opening = detect_opening(game)
|
| 133 |
|
|
|
|
| 134 |
user_result = None
|
| 135 |
if user_color is not None and result != "*":
|
| 136 |
if result == "1-0":
|
| 137 |
+
user_result = "win" if user_color == chess.WHITE else "loss"
|
|
|
|
| 138 |
elif result == "0-1":
|
| 139 |
+
user_result = "win" if user_color == chess.BLACK else "loss"
|
|
|
|
| 140 |
elif result == "1/2-1/2":
|
| 141 |
user_result = "draw"
|
| 142 |
|
|
|
|
| 198 |
}
|
| 199 |
|
| 200 |
def categorize_mistakes(all_analyses):
|
|
|
|
|
|
|
| 201 |
if not all_analyses:
|
|
|
|
| 202 |
return []
|
| 203 |
|
| 204 |
blunders = 0
|
|
|
|
| 229 |
|
| 230 |
total = blunders + regular_mistakes + hanging + opening + middlegame + endgame
|
| 231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
if total == 0:
|
|
|
|
| 233 |
return []
|
| 234 |
|
| 235 |
weaknesses = []
|
|
|
|
| 278 |
|
| 279 |
weaknesses.sort(key=lambda x: x['count'], reverse=True)
|
| 280 |
|
|
|
|
| 281 |
return weaknesses
|
| 282 |
|
|
|
|
|
|
|
| 283 |
def fetch_lichess_puzzles(themes, count=5):
|
|
|
|
| 284 |
puzzles = []
|
| 285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
try:
|
| 287 |
+
url = "https://lichess.org/training"
|
| 288 |
+
for i in range(count):
|
| 289 |
+
puzzles.append({
|
| 290 |
+
'id': f'puzzle_{i+1}',
|
| 291 |
+
'url': url,
|
| 292 |
+
'theme': themes[0] if themes else 'Tactics',
|
| 293 |
+
'rating': 1500
|
|
|
|
|
|
|
|
|
|
| 294 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
except Exception as e:
|
| 296 |
+
logger.error(f"Error generating puzzle links: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
|
| 298 |
+
return puzzles
|
|
|
|
| 299 |
|
| 300 |
def get_comprehensive_analysis(weaknesses, opening_stats, color_stats, total_games):
|
|
|
|
|
|
|
| 301 |
weakness_text = "\n".join([f"- {w['category']}: {w['count']} marta ({w['percentage']:.1f}%)" for w in weaknesses])
|
| 302 |
|
| 303 |
opening_text = "\n".join([f"- {opening}: {stats['total']} o'yin (G'alabalar: {stats['wins']}, Yutqazishlar: {stats['losses']}, Duranglar: {stats['draws']})"
|
|
|
|
| 343 |
|
| 344 |
try:
|
| 345 |
response = model.generate_content(prompt)
|
|
|
|
| 346 |
return response.text
|
| 347 |
except Exception as e:
|
| 348 |
logger.error(f"AI analysis failed: {str(e)}")
|
| 349 |
return f"AI tahlil hozircha mavjud emas: {str(e)}"
|
| 350 |
|
| 351 |
def analyze_games(username_chesscom, pgn_file, username_pgn):
|
|
|
|
| 352 |
actual_username = None
|
| 353 |
pgn_content = None
|
| 354 |
|
| 355 |
if username_chesscom:
|
| 356 |
pgn_content, error = get_user_games_from_chess_com(username_chesscom)
|
| 357 |
if error:
|
|
|
|
| 358 |
return error, "", "", "", None, None, None, None, None
|
| 359 |
actual_username = username_chesscom
|
| 360 |
|
|
|
|
| 361 |
elif pgn_file:
|
|
|
|
| 362 |
pgn_content = pgn_file.decode('utf-8') if isinstance(pgn_file, bytes) else pgn_file
|
| 363 |
|
| 364 |
if username_pgn and username_pgn.strip():
|
| 365 |
actual_username = username_pgn.strip()
|
| 366 |
else:
|
|
|
|
| 367 |
try:
|
| 368 |
first_game = chess.pgn.read_game(io.StringIO(pgn_content))
|
| 369 |
if first_game:
|
|
|
|
| 374 |
actual_username = "Player"
|
| 375 |
except:
|
| 376 |
actual_username = "Player"
|
|
|
|
|
|
|
| 377 |
|
| 378 |
else:
|
|
|
|
| 379 |
return "β Chess.com foydalanuvchi nomini kiriting yoki PGN faylni yuklang", "", "", "", None, None, None, None, None
|
| 380 |
|
| 381 |
games = parse_pgn_content(pgn_content)
|
| 382 |
|
| 383 |
if not games:
|
|
|
|
| 384 |
return "β O'yinlar topilmadi yoki tahlil qilinmadi", "", "", "", None, None, None, None, None
|
| 385 |
|
|
|
|
|
|
|
| 386 |
all_analyses = []
|
| 387 |
opening_stats = defaultdict(lambda: {'wins': 0, 'losses': 0, 'draws': 0, 'total': 0})
|
| 388 |
color_stats = {
|
|
|
|
| 390 |
'black': {'wins': 0, 'losses': 0, 'draws': 0}
|
| 391 |
}
|
| 392 |
|
| 393 |
+
for game in games:
|
|
|
|
| 394 |
analysis = analyze_game_detailed(game, actual_username)
|
| 395 |
all_analyses.append(analysis)
|
| 396 |
|
|
|
|
| 398 |
user_result = analysis.get('user_result')
|
| 399 |
user_color = analysis['user_color']
|
| 400 |
|
|
|
|
|
|
|
| 401 |
if user_color is not None:
|
| 402 |
opening_stats[opening]['total'] += 1
|
| 403 |
|
|
|
|
| 414 |
color_key = 'white' if user_color == chess.WHITE else 'black'
|
| 415 |
color_stats[color_key]['draws'] += 1
|
| 416 |
|
|
|
|
| 417 |
weaknesses = categorize_mistakes(all_analyses)
|
| 418 |
|
| 419 |
all_mistakes = []
|
| 420 |
for analysis in all_analyses:
|
| 421 |
all_mistakes.extend(analysis.get('mistakes', []))
|
| 422 |
|
|
|
|
|
|
|
| 423 |
stats_report = f"## π {len(games)} ta o'yin tahlili\n\n"
|
| 424 |
stats_report += f"**Jami xatolar:** {len(all_mistakes)} ta\n\n"
|
| 425 |
|
|
|
|
| 464 |
|
| 465 |
full_report = stats_report + opening_report + color_report
|
| 466 |
|
|
|
|
| 467 |
ai_analysis = get_comprehensive_analysis(weaknesses, opening_stats, color_stats, len(games))
|
| 468 |
ai_report = f"## π€ AI Murabbiy: To'liq Tahlil va O'quv Rejasi\n\n{ai_analysis}"
|
| 469 |
|
| 470 |
weakness_themes = [w['category'] for w in weaknesses[:3]]
|
|
|
|
| 471 |
puzzles = fetch_lichess_puzzles(weakness_themes, count=5)
|
| 472 |
|
| 473 |
puzzle_text = "## π§© Sizning shaxsiy masalalaringiz\n\n"
|
| 474 |
+
puzzle_text += "Masalalarni yechish uchun quyidagi havoladan foydalaning:\n\n"
|
| 475 |
+
for i, puzzle in enumerate(puzzles, 1):
|
| 476 |
+
theme = puzzle.get('theme', 'Tactics')
|
| 477 |
+
url = puzzle.get('url', 'https://lichess.org/training')
|
| 478 |
+
puzzle_text += f"**Puzzle {i}: {theme}**\n"
|
| 479 |
+
puzzle_text += f"- [Lichess Training]({url})\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
return (
|
| 482 |
full_report,
|
|
|
|
| 499 |
- π― Zaif tomonlar tahlili
|
| 500 |
- π€ AI murabbiy tavsiyalari
|
| 501 |
- π Kitoblar va kurslar tavsiyasi
|
| 502 |
+
- π§© Lichess mashq masalalari
|
| 503 |
""")
|
| 504 |
|
| 505 |
with gr.Row():
|
| 506 |
with gr.Column():
|
| 507 |
+
gr.Markdown("### π Chess.com dan tahlil")
|
| 508 |
username_chesscom = gr.Textbox(
|
| 509 |
+
label="Chess.com foydalanuvchi nomi",
|
| 510 |
placeholder="Foydalanuvchi nomini kiriting",
|
| 511 |
)
|
| 512 |
|
|
|
|
| 567 |
gr.Markdown("""
|
| 568 |
---
|
| 569 |
### π Qanday foydalanish:
|
| 570 |
+
- **Chess.com:** Foydalanuvchi nomingizni kiriting (oxirgi 30-50 ta o'yin tahlil qilinadi)
|
| 571 |
- **Lichess:** Profile β Games β Export orqali PGN faylni yuklang
|
| 572 |
+
- **Masalalar:** Lichess.org saytida mashq qiling
|
| 573 |
|
| 574 |
+
### π― Xususiyatlar:
|
| 575 |
- β
Debyut statistikasi (qaysi debyutlarda yaxshi/yomon o'ynaysiz)
|
| 576 |
- β
Oq/Qora rang bo'yicha natijalar
|
| 577 |
+
- β
Lichess mashq havolalari
|
| 578 |
- β
Shaxsiy o'quv rejasi (kundalik mashg'ulotlar)
|
| 579 |
- β
Kitoblar va kurslar tavsiyasi
|
| 580 |
""")
|
app_1.py
CHANGED
|
@@ -1,305 +1,716 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import chess
|
| 3 |
import chess.pgn
|
|
|
|
| 4 |
import io
|
| 5 |
import requests
|
| 6 |
import google.generativeai as genai
|
| 7 |
-
from collections import Counter
|
| 8 |
-
import json
|
| 9 |
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
# Configure Gemini API
|
| 12 |
GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
|
| 13 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 14 |
-
model = genai.GenerativeModel('gemini-2.
|
| 15 |
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
def
|
| 19 |
-
"
|
| 20 |
games = []
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
|
|
|
| 29 |
return games
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
board = game.board()
|
| 34 |
mistakes = []
|
|
|
|
| 35 |
move_number = 0
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
for move in game.mainline_moves():
|
| 38 |
move_number += 1
|
| 39 |
-
position_fen = board.fen()
|
| 40 |
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
board.push(move)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
-
# Simple heuristic-based mistake detection
|
| 45 |
-
mistake_type = detect_mistake_simple(board, move, position_fen)
|
| 46 |
if mistake_type:
|
| 47 |
mistakes.append({
|
| 48 |
-
'move_number': move_number,
|
| 49 |
-
'move': move.uci(),
|
| 50 |
'type': mistake_type,
|
| 51 |
-
'
|
|
|
|
| 52 |
})
|
| 53 |
|
| 54 |
-
return
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
return None
|
| 61 |
-
|
| 62 |
-
# Count material before and after
|
| 63 |
-
piece_values = {
|
| 64 |
-
chess.PAWN: 1,
|
| 65 |
-
chess.KNIGHT: 3,
|
| 66 |
-
chess.BISHOP: 3,
|
| 67 |
-
chess.ROOK: 5,
|
| 68 |
-
chess.QUEEN: 9,
|
| 69 |
-
chess.KING: 0
|
| 70 |
}
|
| 71 |
-
|
| 72 |
-
# Detect common tactical mistakes
|
| 73 |
-
from_square = move.from_square
|
| 74 |
-
to_square = move.to_square
|
| 75 |
-
|
| 76 |
-
# Check if moved piece is now attacked and undefended
|
| 77 |
-
moved_piece = board.piece_at(to_square)
|
| 78 |
-
if moved_piece and board.is_attacked_by(not board.turn, to_square):
|
| 79 |
-
attackers = len(board.attackers(not board.turn, to_square))
|
| 80 |
-
defenders = len(board.attackers(board.turn, to_square))
|
| 81 |
-
if attackers > defenders:
|
| 82 |
-
return "hanging_piece"
|
| 83 |
-
|
| 84 |
-
# Check if move allows opponent tactics
|
| 85 |
-
if moved_piece and moved_piece.piece_type == chess.KNIGHT:
|
| 86 |
-
# Simple check for knight positioning
|
| 87 |
-
return "knight_positioning"
|
| 88 |
-
|
| 89 |
-
# Detect pawn structure issues
|
| 90 |
-
if moved_piece and moved_piece.piece_type == chess.PAWN:
|
| 91 |
-
return "pawn_structure"
|
| 92 |
-
|
| 93 |
-
# Endgame detection
|
| 94 |
-
total_pieces = len(board.piece_map())
|
| 95 |
-
if total_pieces <= 10:
|
| 96 |
-
return "endgame_technique"
|
| 97 |
-
|
| 98 |
-
return None
|
| 99 |
|
| 100 |
-
def categorize_mistakes(
|
| 101 |
-
"
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
|
|
|
| 112 |
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
'
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
})
|
| 121 |
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
weakness_text = "\n".join([f"- {w['category']}: {w['percentage']:.1f}%" for w in weaknesses])
|
| 129 |
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
|
|
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
-
|
| 143 |
|
| 144 |
def fetch_lichess_puzzles(themes, count=5):
|
| 145 |
-
"
|
| 146 |
-
|
|
|
|
| 147 |
theme_map = {
|
| 148 |
-
'
|
| 149 |
-
'
|
| 150 |
-
'
|
| 151 |
-
'
|
|
|
|
|
|
|
| 152 |
}
|
| 153 |
|
| 154 |
-
|
| 155 |
-
|
| 156 |
for theme_name in themes:
|
| 157 |
-
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
try:
|
| 160 |
-
|
| 161 |
-
url =
|
| 162 |
-
response = requests.get(url, timeout=10)
|
| 163 |
|
| 164 |
if response.status_code == 200:
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
except Exception as e:
|
| 175 |
-
|
| 176 |
|
| 177 |
-
#
|
| 178 |
while len(puzzles) < count:
|
| 179 |
puzzles.append({
|
| 180 |
-
'id': f'
|
| 181 |
-
'fen': '
|
| 182 |
-
'moves':
|
|
|
|
| 183 |
'rating': 1500,
|
| 184 |
-
'
|
| 185 |
-
'url':
|
| 186 |
})
|
|
|
|
| 187 |
|
|
|
|
| 188 |
return puzzles[:count]
|
| 189 |
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
-
|
| 193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
try:
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
pgn_content = pgn_file.decode('utf-8') if isinstance(pgn_file, bytes) else pgn_file
|
| 200 |
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
|
| 228 |
-
|
| 229 |
-
ai_explanation = get_ai_explanation(top_weaknesses)
|
| 230 |
-
explanation_text = f"## π€ AI Coach Analysis\n\n{ai_explanation}"
|
| 231 |
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
|
| 236 |
-
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
for i, puzzle in enumerate(puzzles, 1):
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
|
| 250 |
-
|
| 251 |
-
"""
|
|
|
|
| 252 |
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
type="binary"
|
| 269 |
-
)
|
| 270 |
-
username_input = gr.Textbox(
|
| 271 |
-
label="Chess.com Username (optional)",
|
| 272 |
-
placeholder="Enter username to fetch games"
|
| 273 |
-
)
|
| 274 |
-
analyze_btn = gr.Button("π Analyze Games", variant="primary", size="lg")
|
| 275 |
-
|
| 276 |
-
with gr.Row():
|
| 277 |
-
weakness_output = gr.Markdown(label="Weaknesses")
|
| 278 |
-
|
| 279 |
-
with gr.Row():
|
| 280 |
-
explanation_output = gr.Markdown(label="AI Explanation")
|
| 281 |
|
| 282 |
-
with gr.
|
| 283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
inputs=[pgn_upload, username_input],
|
| 289 |
-
outputs=[weakness_output, explanation_output, puzzle_output]
|
| 290 |
-
)
|
| 291 |
|
| 292 |
-
gr.
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
|
| 303 |
-
|
| 304 |
-
demo = create_interface()
|
| 305 |
-
demo.launch()
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import chess
|
| 3 |
import chess.pgn
|
| 4 |
+
import chess.svg
|
| 5 |
import io
|
| 6 |
import requests
|
| 7 |
import google.generativeai as genai
|
| 8 |
+
from collections import Counter, defaultdict
|
|
|
|
| 9 |
import os
|
| 10 |
+
import time
|
| 11 |
+
import re
|
| 12 |
+
import chess.polyglot
|
| 13 |
+
import logging
|
| 14 |
+
from openings import get_opening_name_from_eco, detect_opening
|
| 15 |
+
|
| 16 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 17 |
+
logger = logging.getLogger(__name__)
|
| 18 |
|
|
|
|
| 19 |
GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
|
| 20 |
genai.configure(api_key=GEMINI_API_KEY)
|
| 21 |
+
model = genai.GenerativeModel('gemini-2.0-flash-exp')
|
| 22 |
|
| 23 |
+
def get_user_games_from_chess_com(username):
|
| 24 |
+
try:
|
| 25 |
+
logger.info(f"Starting to fetch games for user: {username}")
|
| 26 |
+
username_original = username.strip()
|
| 27 |
+
username = username_original.lower()
|
| 28 |
+
|
| 29 |
+
user_url = f"https://api.chess.com/pub/player/{username}"
|
| 30 |
+
response = requests.get(user_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 31 |
+
|
| 32 |
+
if response.status_code != 200:
|
| 33 |
+
logger.error(f"User not found: {username}")
|
| 34 |
+
return None, f"β Foydalanuvchi topilmadi: {username}. Chess.com'da mavjudligini tekshiring."
|
| 35 |
+
|
| 36 |
+
logger.info(f"User found: {username}")
|
| 37 |
+
archives_url = f"https://api.chess.com/pub/player/{username}/games/archives"
|
| 38 |
+
response = requests.get(archives_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 39 |
+
|
| 40 |
+
if response.status_code != 200:
|
| 41 |
+
logger.error("Archives not found")
|
| 42 |
+
return None, "β O'yinlar arxivi topilmadi."
|
| 43 |
+
|
| 44 |
+
archives = response.json()['archives']
|
| 45 |
+
if not archives:
|
| 46 |
+
logger.error("No archives available")
|
| 47 |
+
return None, "β O'yinlar topilmadi."
|
| 48 |
+
|
| 49 |
+
logger.info(f"Found {len(archives)} archives")
|
| 50 |
+
|
| 51 |
+
all_games = []
|
| 52 |
+
for archive_url in reversed(archives[-3:]):
|
| 53 |
+
time.sleep(0.3)
|
| 54 |
+
response = requests.get(archive_url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
| 55 |
+
if response.status_code == 200:
|
| 56 |
+
games = response.json()['games']
|
| 57 |
+
all_games.extend(games)
|
| 58 |
+
logger.info(f"Fetched {len(games)} games from archive")
|
| 59 |
+
if len(all_games) >= 50:
|
| 60 |
+
break
|
| 61 |
+
|
| 62 |
+
logger.info(f"Total games fetched: {len(all_games)}")
|
| 63 |
+
|
| 64 |
+
rapid_games = [g for g in all_games if g.get('time_class') in ['rapid', 'blitz']]
|
| 65 |
+
if not rapid_games:
|
| 66 |
+
rapid_games = all_games[:50]
|
| 67 |
+
|
| 68 |
+
pgn_list = [g['pgn'] for g in rapid_games[:50] if 'pgn' in g]
|
| 69 |
+
|
| 70 |
+
logger.info(f"Total PGN games prepared: {len(pgn_list)}")
|
| 71 |
+
|
| 72 |
+
if not pgn_list:
|
| 73 |
+
logger.error("No PGN games found")
|
| 74 |
+
return None, "β PGN formatdagi o'yinlar topilmadi."
|
| 75 |
+
|
| 76 |
+
return pgn_list, None
|
| 77 |
+
|
| 78 |
+
except Exception as e:
|
| 79 |
+
logger.error(f"Error fetching games: {str(e)}")
|
| 80 |
+
return None, f"β Xatolik: {str(e)}"
|
| 81 |
|
| 82 |
+
def parse_pgn_content(pgn_content):
|
| 83 |
+
logger.info("Starting to parse PGN content")
|
| 84 |
games = []
|
| 85 |
+
if isinstance(pgn_content, list):
|
| 86 |
+
for idx, pgn_text in enumerate(pgn_content):
|
| 87 |
+
try:
|
| 88 |
+
game = chess.pgn.read_game(io.StringIO(pgn_text))
|
| 89 |
+
if game:
|
| 90 |
+
games.append(game)
|
| 91 |
+
except Exception as e:
|
| 92 |
+
logger.warning(f"Failed to parse game {idx}: {str(e)}")
|
| 93 |
+
pass
|
| 94 |
+
else:
|
| 95 |
+
pgn_io = io.StringIO(pgn_content)
|
| 96 |
+
idx = 0
|
| 97 |
+
while True:
|
| 98 |
+
try:
|
| 99 |
+
game = chess.pgn.read_game(pgn_io)
|
| 100 |
+
if game is None:
|
| 101 |
+
break
|
| 102 |
+
games.append(game)
|
| 103 |
+
idx += 1
|
| 104 |
+
except Exception as e:
|
| 105 |
+
logger.warning(f"Failed to parse game {idx}: {str(e)}")
|
| 106 |
+
break
|
| 107 |
|
| 108 |
+
logger.info(f"Successfully parsed {len(games)} games")
|
| 109 |
return games
|
| 110 |
|
| 111 |
+
|
| 112 |
+
def analyze_game_detailed(game, username):
|
| 113 |
board = game.board()
|
| 114 |
mistakes = []
|
| 115 |
+
|
| 116 |
move_number = 0
|
| 117 |
|
| 118 |
+
white_player = game.headers.get("White", "").strip().lower()
|
| 119 |
+
black_player = game.headers.get("Black", "").strip().lower()
|
| 120 |
+
username_lower = username.strip().lower()
|
| 121 |
+
|
| 122 |
+
user_color = None
|
| 123 |
+
if username_lower == white_player:
|
| 124 |
+
user_color = chess.WHITE
|
| 125 |
+
elif username_lower == black_player:
|
| 126 |
+
user_color = chess.BLACK
|
| 127 |
+
|
| 128 |
+
result = game.headers.get("Result", "*")
|
| 129 |
+
opening = detect_opening(game)
|
| 130 |
+
|
| 131 |
+
user_won = None
|
| 132 |
+
user_result = None
|
| 133 |
+
if user_color is not None and result != "*":
|
| 134 |
+
if result == "1-0":
|
| 135 |
+
user_won = (user_color == chess.WHITE)
|
| 136 |
+
user_result = "win" if user_won else "loss"
|
| 137 |
+
elif result == "0-1":
|
| 138 |
+
user_won = (user_color == chess.BLACK)
|
| 139 |
+
user_result = "win" if user_won else "loss"
|
| 140 |
+
elif result == "1/2-1/2":
|
| 141 |
+
user_result = "draw"
|
| 142 |
+
|
| 143 |
+
material_values = {chess.PAWN: 1, chess.KNIGHT: 3, chess.BISHOP: 3, chess.ROOK: 5, chess.QUEEN: 9}
|
| 144 |
+
|
| 145 |
+
def count_material(board):
|
| 146 |
+
total = 0
|
| 147 |
+
for piece_type in material_values:
|
| 148 |
+
total += len(board.pieces(piece_type, chess.WHITE)) * material_values[piece_type]
|
| 149 |
+
total -= len(board.pieces(piece_type, chess.BLACK)) * material_values[piece_type]
|
| 150 |
+
return total
|
| 151 |
+
|
| 152 |
for move in game.mainline_moves():
|
| 153 |
move_number += 1
|
|
|
|
| 154 |
|
| 155 |
+
if user_color is not None and board.turn != user_color:
|
| 156 |
+
board.push(move)
|
| 157 |
+
continue
|
| 158 |
+
|
| 159 |
+
material_before = count_material(board)
|
| 160 |
board.push(move)
|
| 161 |
+
material_after = count_material(board)
|
| 162 |
+
|
| 163 |
+
material_loss = abs(material_after - material_before) if board.turn == chess.WHITE else abs(material_before - material_after)
|
| 164 |
+
|
| 165 |
+
moved_piece = board.piece_at(move.to_square)
|
| 166 |
+
mistake_type = None
|
| 167 |
+
|
| 168 |
+
if material_loss >= 3:
|
| 169 |
+
mistake_type = 'blunder'
|
| 170 |
+
elif material_loss >= 1:
|
| 171 |
+
mistake_type = 'mistake'
|
| 172 |
+
elif moved_piece and board.is_attacked_by(not board.turn, move.to_square):
|
| 173 |
+
attackers = len(board.attackers(not board.turn, move.to_square))
|
| 174 |
+
defenders = len(board.attackers(board.turn, move.to_square))
|
| 175 |
+
if attackers > defenders:
|
| 176 |
+
mistake_type = 'hanging_piece'
|
| 177 |
+
|
| 178 |
+
if move_number <= 10:
|
| 179 |
+
phase = 'opening'
|
| 180 |
+
elif len(board.piece_map()) <= 10:
|
| 181 |
+
phase = 'endgame'
|
| 182 |
+
else:
|
| 183 |
+
phase = 'middlegame'
|
| 184 |
|
|
|
|
|
|
|
| 185 |
if mistake_type:
|
| 186 |
mistakes.append({
|
|
|
|
|
|
|
| 187 |
'type': mistake_type,
|
| 188 |
+
'phase': phase,
|
| 189 |
+
'move_number': move_number
|
| 190 |
})
|
| 191 |
|
| 192 |
+
return {
|
| 193 |
+
'mistakes': mistakes,
|
| 194 |
+
'opening': opening,
|
| 195 |
+
'result': result,
|
| 196 |
+
'user_color': user_color,
|
| 197 |
+
'user_result': user_result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
|
| 200 |
+
def categorize_mistakes(all_analyses):
|
| 201 |
+
logger.info("Categorizing mistakes from all games")
|
| 202 |
+
|
| 203 |
+
if not all_analyses:
|
| 204 |
+
logger.warning("No analyses provided for categorization")
|
| 205 |
+
return []
|
| 206 |
+
|
| 207 |
+
blunders = 0
|
| 208 |
+
regular_mistakes = 0
|
| 209 |
+
hanging = 0
|
| 210 |
+
opening = 0
|
| 211 |
+
middlegame = 0
|
| 212 |
+
endgame = 0
|
| 213 |
|
| 214 |
+
for analysis in all_analyses:
|
| 215 |
+
for mistake in analysis.get('mistakes', []):
|
| 216 |
+
mistake_type = mistake.get('type')
|
| 217 |
+
phase = mistake.get('phase')
|
| 218 |
+
|
| 219 |
+
if mistake_type == 'blunder':
|
| 220 |
+
blunders += 1
|
| 221 |
+
elif mistake_type == 'mistake':
|
| 222 |
+
regular_mistakes += 1
|
| 223 |
+
elif mistake_type == 'hanging_piece':
|
| 224 |
+
hanging += 1
|
| 225 |
+
|
| 226 |
+
if phase == 'opening':
|
| 227 |
+
opening += 1
|
| 228 |
+
elif phase == 'middlegame':
|
| 229 |
+
middlegame += 1
|
| 230 |
+
elif phase == 'endgame':
|
| 231 |
+
endgame += 1
|
| 232 |
+
|
| 233 |
+
total = blunders + regular_mistakes + hanging + opening + middlegame + endgame
|
| 234 |
+
|
| 235 |
+
logger.info(f"Total mistakes found: {total}")
|
| 236 |
+
logger.info(f"Blunders: {blunders}, Mistakes: {regular_mistakes}, Hanging: {hanging}")
|
| 237 |
+
logger.info(f"Opening: {opening}, Middlegame: {middlegame}, Endgame: {endgame}")
|
| 238 |
+
|
| 239 |
+
if total == 0:
|
| 240 |
+
logger.warning("No mistakes found in any game")
|
| 241 |
+
return []
|
| 242 |
+
|
| 243 |
+
weaknesses = []
|
| 244 |
+
|
| 245 |
+
if blunders > 0:
|
| 246 |
+
weaknesses.append({
|
| 247 |
+
'category': "Qo'pol xatolar",
|
| 248 |
+
'count': blunders,
|
| 249 |
+
'percentage': (blunders / total * 100)
|
| 250 |
})
|
| 251 |
|
| 252 |
+
if regular_mistakes > 0:
|
| 253 |
+
weaknesses.append({
|
| 254 |
+
'category': 'Kichik xatolar',
|
| 255 |
+
'count': regular_mistakes,
|
| 256 |
+
'percentage': (regular_mistakes / total * 100)
|
| 257 |
+
})
|
|
|
|
| 258 |
|
| 259 |
+
if hanging > 0:
|
| 260 |
+
weaknesses.append({
|
| 261 |
+
'category': 'Himoyasiz qoldirish',
|
| 262 |
+
'count': hanging,
|
| 263 |
+
'percentage': (hanging / total * 100)
|
| 264 |
+
})
|
| 265 |
|
| 266 |
+
if opening > 0:
|
| 267 |
+
weaknesses.append({
|
| 268 |
+
'category': 'Debyut xatolari',
|
| 269 |
+
'count': opening,
|
| 270 |
+
'percentage': (opening / total * 100)
|
| 271 |
+
})
|
| 272 |
+
|
| 273 |
+
if middlegame > 0:
|
| 274 |
+
weaknesses.append({
|
| 275 |
+
'category': "O'rta o'yin xatolari",
|
| 276 |
+
'count': middlegame,
|
| 277 |
+
'percentage': (middlegame / total * 100)
|
| 278 |
+
})
|
| 279 |
+
|
| 280 |
+
if endgame > 0:
|
| 281 |
+
weaknesses.append({
|
| 282 |
+
'category': 'Endshpil xatolari',
|
| 283 |
+
'count': endgame,
|
| 284 |
+
'percentage': (endgame / total * 100)
|
| 285 |
+
})
|
| 286 |
+
|
| 287 |
+
weaknesses.sort(key=lambda x: x['count'], reverse=True)
|
| 288 |
+
|
| 289 |
+
logger.info(f"Total weakness categories: {len(weaknesses)}")
|
| 290 |
+
return weaknesses
|
| 291 |
|
| 292 |
+
import json
|
| 293 |
|
| 294 |
def fetch_lichess_puzzles(themes, count=5):
|
| 295 |
+
logger.info(f"Fetching {count} puzzles for themes: {themes}")
|
| 296 |
+
puzzles = []
|
| 297 |
+
|
| 298 |
theme_map = {
|
| 299 |
+
"Qo'pol xatolar": ['hangingPiece', 'discoveredAttack', 'fork'],
|
| 300 |
+
'Kichik xatolar': ['advantage', 'crushing', 'attackingF2F7'],
|
| 301 |
+
'Himoyasiz qoldirish': ['hangingPiece', 'pin', 'skewer'],
|
| 302 |
+
'Debyut xatolari': ['opening', 'short', 'middlegame'],
|
| 303 |
+
"O'rta o'yin xatolari": ['middlegame', 'attackingF2F7', 'advancedPawn'],
|
| 304 |
+
'Endshpil xatolari': ['endgame', 'queenEndgame', 'rookEndgame']
|
| 305 |
}
|
| 306 |
|
| 307 |
+
lichess_themes = []
|
|
|
|
| 308 |
for theme_name in themes:
|
| 309 |
+
if theme_name in theme_map:
|
| 310 |
+
lichess_themes.extend(theme_map[theme_name])
|
| 311 |
+
|
| 312 |
+
lichess_themes = list(set(lichess_themes))[:3]
|
| 313 |
+
logger.info(f"Selected Lichess themes: {lichess_themes}")
|
| 314 |
+
|
| 315 |
+
try:
|
| 316 |
+
# Fetch puzzles using the daily puzzle API and database
|
| 317 |
+
for theme in lichess_themes:
|
| 318 |
+
if len(puzzles) >= count:
|
| 319 |
+
break
|
| 320 |
+
|
| 321 |
+
# Use Lichess puzzle database API
|
| 322 |
+
url = f"https://lichess.org/api/puzzle/batch/mix?nb=2&themes={theme}"
|
| 323 |
+
response = requests.get(url, timeout=10, headers={
|
| 324 |
+
'User-Agent': 'Mozilla/5.0',
|
| 325 |
+
'Accept': 'application/x-ndjson'
|
| 326 |
+
})
|
| 327 |
+
|
| 328 |
+
if response.status_code == 200:
|
| 329 |
+
# Parse NDJSON (newline-delimited JSON)
|
| 330 |
+
lines = response.text.strip().split('\n')
|
| 331 |
+
for line in lines:
|
| 332 |
+
if len(puzzles) >= count:
|
| 333 |
+
break
|
| 334 |
+
if not line.strip():
|
| 335 |
+
continue
|
| 336 |
+
try:
|
| 337 |
+
puzzle_data = json.loads(line) # Use json.loads instead of eval
|
| 338 |
+
game_data = puzzle_data.get('game', {})
|
| 339 |
+
puzzle_info = puzzle_data.get('puzzle', {})
|
| 340 |
+
|
| 341 |
+
puzzle_id = puzzle_info.get('id', '')
|
| 342 |
+
|
| 343 |
+
if puzzle_id and not any(p['id'] == puzzle_id for p in puzzles):
|
| 344 |
+
puzzles.append({
|
| 345 |
+
'id': puzzle_id,
|
| 346 |
+
'fen': game_data.get('fen', ''),
|
| 347 |
+
'moves': ' '.join(puzzle_info.get('solution', [])),
|
| 348 |
+
'solution': puzzle_info.get('solution', []),
|
| 349 |
+
'rating': puzzle_info.get('rating', 1500),
|
| 350 |
+
'themes': puzzle_info.get('themes', []),
|
| 351 |
+
'url': f"https://lichess.org/training/{puzzle_id}"
|
| 352 |
+
})
|
| 353 |
+
logger.info(f"Added puzzle {puzzle_id} with rating {puzzle_info.get('rating')}")
|
| 354 |
+
except json.JSONDecodeError as e:
|
| 355 |
+
logger.warning(f"Failed to parse puzzle line: {str(e)}")
|
| 356 |
+
except Exception as e:
|
| 357 |
+
logger.warning(f"Error processing puzzle: {str(e)}")
|
| 358 |
+
|
| 359 |
+
time.sleep(0.3)
|
| 360 |
+
except Exception as e:
|
| 361 |
+
logger.error(f"Error fetching puzzles: {str(e)}")
|
| 362 |
+
|
| 363 |
+
# Fill remaining with daily puzzle if needed
|
| 364 |
+
if len(puzzles) < count:
|
| 365 |
try:
|
| 366 |
+
url = "https://lichess.org/api/puzzle/daily"
|
| 367 |
+
response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
|
|
|
|
| 368 |
|
| 369 |
if response.status_code == 200:
|
| 370 |
+
daily_data = response.json()
|
| 371 |
+
game_data = daily_data.get('game', {})
|
| 372 |
+
puzzle_info = daily_data.get('puzzle', {})
|
| 373 |
+
puzzle_id = puzzle_info.get('id', '')
|
| 374 |
+
|
| 375 |
+
if puzzle_id and not any(p['id'] == puzzle_id for p in puzzles):
|
| 376 |
+
puzzles.append({
|
| 377 |
+
'id': puzzle_id,
|
| 378 |
+
'fen': game_data.get('fen', ''),
|
| 379 |
+
'moves': ' '.join(puzzle_info.get('solution', [])),
|
| 380 |
+
'solution': puzzle_info.get('solution', []),
|
| 381 |
+
'rating': puzzle_info.get('rating', 1500),
|
| 382 |
+
'themes': puzzle_info.get('themes', []),
|
| 383 |
+
'url': f"https://lichess.org/training/{puzzle_id}"
|
| 384 |
+
})
|
| 385 |
+
logger.info(f"Added daily puzzle {puzzle_id}")
|
| 386 |
except Exception as e:
|
| 387 |
+
logger.error(f"Error fetching daily puzzle: {str(e)}")
|
| 388 |
|
| 389 |
+
# Fill with fallback training links if still not enough
|
| 390 |
while len(puzzles) < count:
|
| 391 |
puzzles.append({
|
| 392 |
+
'id': f'training_{len(puzzles)+1}',
|
| 393 |
+
'fen': '',
|
| 394 |
+
'moves': '',
|
| 395 |
+
'solution': [],
|
| 396 |
'rating': 1500,
|
| 397 |
+
'themes': ['Mixed'],
|
| 398 |
+
'url': "https://lichess.org/training"
|
| 399 |
})
|
| 400 |
+
logger.info(f"Added fallback puzzle link {len(puzzles)}")
|
| 401 |
|
| 402 |
+
logger.info(f"Total puzzles prepared: {len(puzzles)}")
|
| 403 |
return puzzles[:count]
|
| 404 |
|
| 405 |
+
def get_comprehensive_analysis(weaknesses, opening_stats, color_stats, total_games):
|
| 406 |
+
logger.info("Generating AI comprehensive analysis")
|
| 407 |
+
|
| 408 |
+
weakness_text = "\n".join([f"- {w['category']}: {w['count']} marta ({w['percentage']:.1f}%)" for w in weaknesses])
|
| 409 |
+
|
| 410 |
+
opening_text = "\n".join([f"- {opening}: {stats['total']} o'yin (G'alabalar: {stats['wins']}, Yutqazishlar: {stats['losses']}, Duranglar: {stats['draws']})"
|
| 411 |
+
for opening, stats in list(opening_stats.items())[:5]])
|
| 412 |
+
|
| 413 |
+
color_text = f"Oq rangda: {color_stats['white']['wins']}G-{color_stats['white']['losses']}Y-{color_stats['white']['draws']}D\n"
|
| 414 |
+
color_text += f"Qora rangda: {color_stats['black']['wins']}G-{color_stats['black']['losses']}Y-{color_stats['black']['draws']}D"
|
| 415 |
+
|
| 416 |
+
prompt = f"""Siz professional ΡΠ°Ρ
ΠΌΠ°Ρ murabbiy va tahlilchisiz. O'yinchining {total_games} ta o'yinini tahlil qildingiz.
|
| 417 |
+
|
| 418 |
+
STATISTIKA:
|
| 419 |
+
|
| 420 |
+
Zaif tomonlar:
|
| 421 |
+
{weakness_text}
|
| 422 |
|
| 423 |
+
Eng ko'p o'ynaladigan debyutlar:
|
| 424 |
+
{opening_text}
|
| 425 |
+
|
| 426 |
+
Rang bo'yicha natijalar:
|
| 427 |
+
{color_text}
|
| 428 |
+
|
| 429 |
+
Quyidagilarni taqdim eting:
|
| 430 |
+
|
| 431 |
+
1. **ZAIF TOMONLAR TAHLILI**: Har bir zaif tomonni chuqur tahlil qiling va nima uchun bu muammo kelib chiqayotganini tushuntiring.
|
| 432 |
+
|
| 433 |
+
2. **SHAXSIY O'QUV REJASI**: Kundalik mashg'ulotlar rejasini tuzing:
|
| 434 |
+
- Har kuni nechta masala yechish kerak va qanday turdagi masalalar
|
| 435 |
+
- Qaysi debyutlarni o'rganish kerak
|
| 436 |
+
- Qaysi o'yin bosqichiga ko'proq e'tibor berish kerak
|
| 437 |
+
- Kompyuter yoki botlar bilan qanday mashq qilish kerak
|
| 438 |
+
|
| 439 |
+
3. **TAVSIYA ETILGAN RESURSLAR**:
|
| 440 |
+
- Kitoblar (muallif va nom bilan)
|
| 441 |
+
- Onlayn kurslar (Uzchess, Chess.com, Lichess)
|
| 442 |
+
- YouTube kanallari
|
| 443 |
+
- Mashq uchun maxsus botlar yoki dasturlar
|
| 444 |
+
|
| 445 |
+
4. **DEBYUT TAVSIYALARI**: Statistikaga asoslanib, qaysi debyutlarni davom ettirish va qaysilarini o'zgartirish kerak.
|
| 446 |
+
|
| 447 |
+
5. **MOTIVATSION XULOSA**: Qisqa va rag'batlantiruvchi xulosa.
|
| 448 |
+
|
| 449 |
+
MUHIM: Javobni FAQAT O'ZBEK TILIDA yozing! Aniq va amaliy maslahatlar bering."""
|
| 450 |
+
|
| 451 |
try:
|
| 452 |
+
response = model.generate_content(prompt)
|
| 453 |
+
logger.info("AI analysis generated successfully")
|
| 454 |
+
return response.text
|
| 455 |
+
except Exception as e:
|
| 456 |
+
logger.error(f"AI analysis failed: {str(e)}")
|
| 457 |
+
return f"AI tahlil hozircha mavjud emas: {str(e)}"
|
| 458 |
+
|
| 459 |
+
def analyze_games(username_chesscom, pgn_file, username_pgn):
|
| 460 |
+
logger.info("=== Starting game analysis ===")
|
| 461 |
+
actual_username = None
|
| 462 |
+
pgn_content = None
|
| 463 |
+
|
| 464 |
+
if username_chesscom:
|
| 465 |
+
pgn_content, error = get_user_games_from_chess_com(username_chesscom)
|
| 466 |
+
if error:
|
| 467 |
+
logger.error(f"Failed to fetch games: {error}")
|
| 468 |
+
return error, "", "", "", None, None, None, None, None
|
| 469 |
+
actual_username = username_chesscom
|
| 470 |
+
|
| 471 |
+
# PGN file upload
|
| 472 |
+
elif pgn_file:
|
| 473 |
+
logger.info("Processing uploaded PGN file")
|
| 474 |
pgn_content = pgn_file.decode('utf-8') if isinstance(pgn_file, bytes) else pgn_file
|
| 475 |
|
| 476 |
+
if username_pgn and username_pgn.strip():
|
| 477 |
+
actual_username = username_pgn.strip()
|
| 478 |
+
else:
|
| 479 |
+
# Try to extract username from first game headers
|
| 480 |
+
try:
|
| 481 |
+
first_game = chess.pgn.read_game(io.StringIO(pgn_content))
|
| 482 |
+
if first_game:
|
| 483 |
+
white = first_game.headers.get("White", "")
|
| 484 |
+
black = first_game.headers.get("Black", "")
|
| 485 |
+
actual_username = white if white else black if black else "Player"
|
| 486 |
+
else:
|
| 487 |
+
actual_username = "Player"
|
| 488 |
+
except:
|
| 489 |
+
actual_username = "Player"
|
| 490 |
+
|
| 491 |
+
logger.info(f"Extracted username from PGN: {actual_username}")
|
| 492 |
+
|
| 493 |
+
else:
|
| 494 |
+
logger.error("No username or file provided")
|
| 495 |
+
return "β Chess.com foydalanuvchi nomini kiriting yoki PGN faylni yuklang", "", "", "", None, None, None, None, None
|
| 496 |
+
|
| 497 |
+
games = parse_pgn_content(pgn_content)
|
| 498 |
+
|
| 499 |
+
if not games:
|
| 500 |
+
logger.error("No games parsed")
|
| 501 |
+
return "β O'yinlar topilmadi yoki tahlil qilinmadi", "", "", "", None, None, None, None, None
|
| 502 |
+
|
| 503 |
+
logger.info(f"Analyzing {len(games)} games")
|
| 504 |
+
|
| 505 |
+
all_analyses = []
|
| 506 |
+
opening_stats = defaultdict(lambda: {'wins': 0, 'losses': 0, 'draws': 0, 'total': 0})
|
| 507 |
+
color_stats = {
|
| 508 |
+
'white': {'wins': 0, 'losses': 0, 'draws': 0},
|
| 509 |
+
'black': {'wins': 0, 'losses': 0, 'draws': 0}
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
for idx, game in enumerate(games):
|
| 513 |
+
logger.info(f"Analyzing game {idx + 1}/{len(games)}")
|
| 514 |
+
analysis = analyze_game_detailed(game, actual_username)
|
| 515 |
+
all_analyses.append(analysis)
|
| 516 |
|
| 517 |
+
opening = analysis['opening']
|
| 518 |
+
user_result = analysis.get('user_result')
|
| 519 |
+
user_color = analysis['user_color']
|
| 520 |
|
| 521 |
+
logger.info(f"Game {idx + 1}: {opening}, Result: {user_result}, Color: {user_color}")
|
|
|
|
|
|
|
| 522 |
|
| 523 |
+
if user_color is not None:
|
| 524 |
+
opening_stats[opening]['total'] += 1
|
| 525 |
+
|
| 526 |
+
if user_result == 'win':
|
| 527 |
+
opening_stats[opening]['wins'] += 1
|
| 528 |
+
color_key = 'white' if user_color == chess.WHITE else 'black'
|
| 529 |
+
color_stats[color_key]['wins'] += 1
|
| 530 |
+
elif user_result == 'loss':
|
| 531 |
+
opening_stats[opening]['losses'] += 1
|
| 532 |
+
color_key = 'white' if user_color == chess.WHITE else 'black'
|
| 533 |
+
color_stats[color_key]['losses'] += 1
|
| 534 |
+
elif user_result == 'draw':
|
| 535 |
+
opening_stats[opening]['draws'] += 1
|
| 536 |
+
color_key = 'white' if user_color == chess.WHITE else 'black'
|
| 537 |
+
color_stats[color_key]['draws'] += 1
|
| 538 |
+
|
| 539 |
+
logger.info("Categorizing mistakes")
|
| 540 |
+
weaknesses = categorize_mistakes(all_analyses)
|
| 541 |
+
|
| 542 |
+
all_mistakes = []
|
| 543 |
+
for analysis in all_analyses:
|
| 544 |
+
all_mistakes.extend(analysis.get('mistakes', []))
|
| 545 |
+
|
| 546 |
+
logger.info(f"Total mistakes collected: {len(all_mistakes)}")
|
| 547 |
+
|
| 548 |
+
stats_report = f"## π {len(games)} ta o'yin tahlili\n\n"
|
| 549 |
+
stats_report += f"**Jami xatolar:** {len(all_mistakes)} ta\n\n"
|
| 550 |
+
|
| 551 |
+
stats_report += "### π― Eng zaif 3 tomoningiz:\n\n"
|
| 552 |
+
if weaknesses:
|
| 553 |
+
for i, w in enumerate(weaknesses[:3], 1):
|
| 554 |
+
stats_report += f"**{i}. {w['category']}** - {w['count']} marta ({w['percentage']:.1f}%)\n"
|
| 555 |
+
else:
|
| 556 |
+
stats_report += "Xatolar topilmadi yoki tahlil qilinmadi.\n"
|
| 557 |
+
|
| 558 |
+
opening_report = "\n\n## π Debyut Statistikasi\n\n"
|
| 559 |
+
sorted_openings = sorted(opening_stats.items(), key=lambda x: x[1]['total'], reverse=True)[:10]
|
| 560 |
+
|
| 561 |
+
for opening, stats in sorted_openings:
|
| 562 |
+
total = stats['total']
|
| 563 |
+
wins = stats['wins']
|
| 564 |
+
losses = stats['losses']
|
| 565 |
+
draws = stats['draws']
|
| 566 |
+
win_rate = (wins / total * 100) if total > 0 else 0
|
| 567 |
|
| 568 |
+
opening_report += f"**{opening}** ({total} o'yin)\n"
|
| 569 |
+
opening_report += f"- G'alabalar: {wins} ({win_rate:.1f}%) | Yutqazishlar: {losses} | Duranglar: {draws}\n\n"
|
| 570 |
+
|
| 571 |
+
color_report = "\n\n## βͺβ« Rang bo'yicha natijalar\n\n"
|
| 572 |
+
|
| 573 |
+
white_total = sum(color_stats['white'].values())
|
| 574 |
+
black_total = sum(color_stats['black'].values())
|
| 575 |
+
|
| 576 |
+
if white_total > 0:
|
| 577 |
+
white_wr = color_stats['white']['wins'] / white_total * 100
|
| 578 |
+
color_report += f"**Oq figuralar bilan:**\n"
|
| 579 |
+
color_report += f"- G'alabalar: {color_stats['white']['wins']} ({white_wr:.1f}%)\n"
|
| 580 |
+
color_report += f"- Yutqazishlar: {color_stats['white']['losses']}\n"
|
| 581 |
+
color_report += f"- Duranglar: {color_stats['white']['draws']}\n\n"
|
| 582 |
+
|
| 583 |
+
if black_total > 0:
|
| 584 |
+
black_wr = color_stats['black']['wins'] / black_total * 100
|
| 585 |
+
color_report += f"**Qora figuralar bilan:**\n"
|
| 586 |
+
color_report += f"- G'alabalar: {color_stats['black']['wins']} ({black_wr:.1f}%)\n"
|
| 587 |
+
color_report += f"- Yutqazishlar: {color_stats['black']['losses']}\n"
|
| 588 |
+
color_report += f"- Duranglar: {color_stats['black']['draws']}\n"
|
| 589 |
+
|
| 590 |
+
full_report = stats_report + opening_report + color_report
|
| 591 |
+
|
| 592 |
+
logger.info("Generating AI analysis")
|
| 593 |
+
ai_analysis = get_comprehensive_analysis(weaknesses, opening_stats, color_stats, len(games))
|
| 594 |
+
ai_report = f"## π€ AI Murabbiy: To'liq Tahlil va O'quv Rejasi\n\n{ai_analysis}"
|
| 595 |
+
|
| 596 |
+
weakness_themes = [w['category'] for w in weaknesses[:3]]
|
| 597 |
+
logger.info(f"Fetching puzzles for themes: {weakness_themes}")
|
| 598 |
+
puzzles = fetch_lichess_puzzles(weakness_themes, count=5)
|
| 599 |
+
|
| 600 |
+
puzzle_text = "## π§© Sizning shaxsiy masalalaringiz\n\n"
|
| 601 |
+
if puzzles:
|
| 602 |
for i, puzzle in enumerate(puzzles, 1):
|
| 603 |
+
theme = puzzle.get('themes', ['Tactics'])[0].title() if puzzle.get('themes') else 'Tactics'
|
| 604 |
+
rating = puzzle.get('rating', 1500)
|
| 605 |
+
url = puzzle.get('url', 'https://lichess.org/training')
|
| 606 |
+
fen = puzzle.get('fen', '')[:40] if puzzle.get('fen') else 'N/A'
|
| 607 |
+
puzzle_text += f"**Puzzle {i}: {theme}** (Rating: {rating})\n"
|
| 608 |
+
puzzle_text += f"- [Solve on Lichess]({url})\n"
|
| 609 |
+
puzzle_text += f"- Position: `{fen}...`\n\n"
|
| 610 |
+
else:
|
| 611 |
+
puzzle_text += "- Masalalarni [Lichess.org](https://lichess.org/training) saytidan ishlang\n"
|
| 612 |
+
|
| 613 |
+
logger.info("=== Analysis completed successfully ===")
|
| 614 |
+
|
| 615 |
+
return (
|
| 616 |
+
full_report,
|
| 617 |
+
ai_report,
|
| 618 |
+
puzzle_text,
|
| 619 |
+
"",
|
| 620 |
+
None,
|
| 621 |
+
"",
|
| 622 |
+
None,
|
| 623 |
+
"",
|
| 624 |
+
None
|
| 625 |
+
)
|
| 626 |
|
| 627 |
+
with gr.Blocks(title="Chess Study Plan Pro", theme=gr.themes.Soft()) as demo:
|
| 628 |
+
gr.Markdown("""
|
| 629 |
+
# βοΈ Professional Π¨Π°Ρ
ΠΌΠ°Ρ O'quv Rejasi
|
| 630 |
|
| 631 |
+
### To'liq tahlil va shaxsiy o'quv rejasi:
|
| 632 |
+
- π Batafsil statistika (debyutlar, ranglar, natijalar)
|
| 633 |
+
- π― Zaif tomonlar tahlili
|
| 634 |
+
- π€ AI murabbiy tavsiyalari
|
| 635 |
+
- π Kitoblar va kurslar tavsiyasi
|
| 636 |
+
- π§© Interaktiv masalalar (gradio interfeysi ichida)
|
| 637 |
+
""")
|
| 638 |
+
|
| 639 |
+
with gr.Row():
|
| 640 |
+
with gr.Column():
|
| 641 |
+
gr.Markdown("### π Uzchess.com dan tahlil")
|
| 642 |
+
username_chesscom = gr.Textbox(
|
| 643 |
+
label="Uzchess.com foydalanuvchi nomi",
|
| 644 |
+
placeholder="Foydalanuvchi nomini kiriting",
|
| 645 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 646 |
|
| 647 |
+
with gr.Column():
|
| 648 |
+
gr.Markdown("### π PGN fayl yuklash")
|
| 649 |
+
pgn_upload = gr.File(
|
| 650 |
+
label="PGN faylni yuklang",
|
| 651 |
+
file_types=[".pgn"],
|
| 652 |
+
type="binary"
|
| 653 |
+
)
|
| 654 |
+
username_pgn = gr.Textbox(
|
| 655 |
+
label="Foydalanuvchi nomi (PGN uchun)",
|
| 656 |
+
placeholder="PGN dagi o'yinchi nomi (ixtiyoriy)",
|
| 657 |
+
info="Bo'sh qoldiring, avtomatik aniqlanadi"
|
| 658 |
+
)
|
| 659 |
+
|
| 660 |
+
analyze_btn = gr.Button("π To'liq tahlil qilish", variant="primary", size="lg")
|
| 661 |
+
|
| 662 |
+
with gr.Row():
|
| 663 |
+
stats_output = gr.Markdown(label="Statistika")
|
| 664 |
+
|
| 665 |
+
with gr.Row():
|
| 666 |
+
ai_output = gr.Markdown(label="AI Tahlil")
|
| 667 |
+
|
| 668 |
+
gr.Markdown("---")
|
| 669 |
+
|
| 670 |
+
puzzle_header = gr.Markdown()
|
| 671 |
+
|
| 672 |
+
with gr.Row():
|
| 673 |
+
with gr.Column():
|
| 674 |
+
puzzle1_info = gr.Markdown()
|
| 675 |
+
puzzle1_board = gr.HTML()
|
| 676 |
|
| 677 |
+
with gr.Column():
|
| 678 |
+
puzzle2_info = gr.Markdown()
|
| 679 |
+
puzzle2_board = gr.HTML()
|
|
|
|
|
|
|
|
|
|
| 680 |
|
| 681 |
+
with gr.Column():
|
| 682 |
+
puzzle3_info = gr.Markdown()
|
| 683 |
+
puzzle3_board = gr.HTML()
|
| 684 |
+
|
| 685 |
+
analyze_btn.click(
|
| 686 |
+
fn=analyze_games,
|
| 687 |
+
inputs=[username_chesscom, pgn_upload, username_pgn],
|
| 688 |
+
outputs=[
|
| 689 |
+
stats_output,
|
| 690 |
+
ai_output,
|
| 691 |
+
puzzle_header,
|
| 692 |
+
puzzle1_info,
|
| 693 |
+
puzzle1_board,
|
| 694 |
+
puzzle2_info,
|
| 695 |
+
puzzle2_board,
|
| 696 |
+
puzzle3_info,
|
| 697 |
+
puzzle3_board
|
| 698 |
+
]
|
| 699 |
+
)
|
| 700 |
+
|
| 701 |
+
gr.Markdown("""
|
| 702 |
+
---
|
| 703 |
+
### π Qanday foydalanish:
|
| 704 |
+
- **Uzchess.com:** Foydalanuvchi nomingizni kiriting (oxirgi 30-50 ta o'yin tahlil qilinadi)
|
| 705 |
+
- **Lichess:** Profile β Games β Export orqali PGN faylni yuklang
|
| 706 |
+
- **Masalalar:** Har bir masalani tahlil qiling va eng yaxshi yurishni toping
|
| 707 |
+
|
| 708 |
+
### π― Yangi xususiyatlar:
|
| 709 |
+
- β
Debyut statistikasi (qaysi debyutlarda yaxshi/yomon o'ynaysiz)
|
| 710 |
+
- β
Oq/Qora rang bo'yicha natijalar
|
| 711 |
+
- β
Interaktiv masalalar (gradio interfeysi ichida)
|
| 712 |
+
- β
Shaxsiy o'quv rejasi (kundalik mashg'ulotlar)
|
| 713 |
+
- β
Kitoblar va kurslar tavsiyasi
|
| 714 |
+
""")
|
| 715 |
|
| 716 |
+
demo.launch()
|
|
|
|
|
|
openings.py
CHANGED
|
@@ -36,6 +36,7 @@ def get_opening_name_from_eco(eco_code):
|
|
| 36 |
'B50': 'Sicilian Defense: 2...d6',
|
| 37 |
'B90': 'Sicilian Defense: Najdorf',
|
| 38 |
'C00': 'French Defense',
|
|
|
|
| 39 |
'C02': 'French Defense: Advance Variation',
|
| 40 |
'C10': 'French Defense: Rubinstein Variation',
|
| 41 |
'C20': 'King Pawn Game',
|
|
@@ -45,6 +46,8 @@ def get_opening_name_from_eco(eco_code):
|
|
| 45 |
'C42': 'Russian Game (Petrov Defense)',
|
| 46 |
'C44': 'Scotch Game',
|
| 47 |
'C50': 'Italian Game',
|
|
|
|
|
|
|
| 48 |
'C60': 'Spanish Opening (Ruy Lopez)',
|
| 49 |
'C65': 'Spanish Opening: Berlin Defense',
|
| 50 |
'C70': 'Spanish Opening',
|
|
|
|
| 36 |
'B50': 'Sicilian Defense: 2...d6',
|
| 37 |
'B90': 'Sicilian Defense: Najdorf',
|
| 38 |
'C00': 'French Defense',
|
| 39 |
+
"C01": 'French Defense: Exchange Variation',
|
| 40 |
'C02': 'French Defense: Advance Variation',
|
| 41 |
'C10': 'French Defense: Rubinstein Variation',
|
| 42 |
'C20': 'King Pawn Game',
|
|
|
|
| 46 |
'C42': 'Russian Game (Petrov Defense)',
|
| 47 |
'C44': 'Scotch Game',
|
| 48 |
'C50': 'Italian Game',
|
| 49 |
+
"C54": "Italian Game: Giuoco Piano",
|
| 50 |
+
'C55': 'Italian Game: Two Knights Defense',
|
| 51 |
'C60': 'Spanish Opening (Ruy Lopez)',
|
| 52 |
'C65': 'Spanish Opening: Berlin Defense',
|
| 53 |
'C70': 'Spanish Opening',
|