[LIB-13] Lichess format entities for JSON parsing
authorgotty <gotty@hedgecode.org>
Fri, 17 Jan 2020 23:46:36 +0000 (02:46 +0300)
committergotty <gotty@hedgecode.org>
Fri, 17 Jan 2020 23:46:36 +0000 (02:46 +0300)
21 files changed:
src/main/java/org/hedgecode/chess/scanner/entity/PGNTournament.java
src/main/java/org/hedgecode/chess/scanner/format/lichess/Clock.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/Format.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/FormatBuilder.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/Game.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/GameData.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/GameFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/Player.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/Status.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/lichess/User.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/format/JSONGameFormat.java
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONClock.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONFormatBuilder.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGame.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameData.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONMove.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONPlayer.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONStatus.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONUser.java [new file with mode: 0644]
src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.lichess.FormatBuilder [new file with mode: 0644]

index 80603b0..8da5339 100644 (file)
@@ -20,7 +20,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
 import java.util.Collection;
 import java.util.List;
 
-import static org.hedgecode.chess.scanner.ChessHogScannerConstants.*;
+import static org.hedgecode.chess.scanner.format.PGNConstants.*;
 
 /**
  * PGNTournament
 
 /**
  * PGNTournament
@@ -79,7 +79,7 @@ public class PGNTournament implements PGNEntity {
             sb.append(
                     game.pgn()
             ).append(
             sb.append(
                     game.pgn()
             ).append(
-                    CRLF
+                    PGN_CRLF
             );
         }
         return sb.toString();
             );
         }
         return sb.toString();
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/Clock.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/Clock.java
new file mode 100644 (file)
index 0000000..62def59
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * Clock
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Clock {
+
+    boolean running();
+
+    int initial();
+
+    int increment();
+
+    float white();
+
+    float black();
+
+    int emerg();
+
+    int moretime();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/Format.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/Format.java
new file mode 100644 (file)
index 0000000..f1a399a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+import org.hedgecode.chess.scanner.spi.ServiceRegistry;
+
+/**
+ * Format
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class Format {
+
+    private static Format _instance;
+
+    private final FormatBuilder formatBuilder;
+
+    private Format() {
+        formatBuilder = ServiceRegistry.singleProvider(
+                FormatBuilder.class
+        );
+    }
+
+    public static GameFormat formatGame(String game) {
+        return getFormat().builder().buildGame(game);
+    }
+
+    private FormatBuilder builder() {
+        return formatBuilder;
+    }
+
+    private static Format getFormat() {
+        if (_instance == null) {
+            _instance = new Format();
+        }
+        return _instance;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/FormatBuilder.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/FormatBuilder.java
new file mode 100644 (file)
index 0000000..6372b8f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * FormatBuilder
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface FormatBuilder {
+
+    GameFormat buildGame(String game);
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/Game.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/Game.java
new file mode 100644 (file)
index 0000000..23a0b94
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * Game
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Game {
+
+    String id();
+
+    String speed();
+
+    boolean rated();
+
+    String initialFen();
+
+    String fen();
+
+    String player();
+
+    int turns();
+
+    int startedAtTurn();
+
+    Status status();
+
+    long createdAt();
+
+    String winner();
+
+    String lastMove();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/GameData.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/GameData.java
new file mode 100644 (file)
index 0000000..8c965ea
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+import org.hedgecode.chess.scanner.format.Move;
+
+/**
+ * GameData
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface GameData {
+
+    Game game();
+
+    Player player();
+
+    Player opponent();
+
+    Clock clock();
+
+    Move[] moves();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/GameFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/GameFormat.java
new file mode 100644 (file)
index 0000000..0ebda8c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+import org.hedgecode.chess.scanner.entity.PGNEntity;
+
+/**
+ * GameFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface GameFormat extends PGNEntity {
+
+    String id();
+
+    GameData gameData();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/Player.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/Player.java
new file mode 100644 (file)
index 0000000..c020a7b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * Player
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Player {
+
+    String color();
+
+    User user();
+
+    int rating();
+
+    int ratingDiff();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/Status.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/Status.java
new file mode 100644 (file)
index 0000000..93b751b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * Status
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Status {
+
+    String name();
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/lichess/User.java b/src/main/java/org/hedgecode/chess/scanner/format/lichess/User.java
new file mode 100644 (file)
index 0000000..0f29a92
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.format.lichess;
+
+/**
+ * User
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface User {
+
+    String id();
+
+    String username();
+
+}
index 0db8233..28d250e 100644 (file)
@@ -41,7 +41,7 @@ public class JSONGameFormat extends AbstractBaseFormat implements GameFormat {
     @Override
     public String id() {
         return Integer.toString(
     @Override
     public String id() {
         return Integer.toString(
-                gameData().game().id()
+                gameData.game().id()
         );
     }
 
         );
     }
 
@@ -50,7 +50,6 @@ public class JSONGameFormat extends AbstractBaseFormat implements GameFormat {
         return gameData;
     }
 
         return gameData;
     }
 
-
     @Override
     public String pgn() {
         PGNFormat pgnFormat = ServiceRegistry.singleProvider(
     @Override
     public String pgn() {
         PGNFormat pgnFormat = ServiceRegistry.singleProvider(
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONClock.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONClock.java
new file mode 100644 (file)
index 0000000..3f99a2d
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.lichess.Clock;
+
+/**
+ * JSONClock
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONClock implements Clock {
+
+    @SerializedName("running")
+    private boolean running;
+
+    @SerializedName("initial")
+    private int initial;
+
+    @SerializedName("increment")
+    private int increment;
+
+    @SerializedName("white")
+    private float white;
+
+    @SerializedName("black")
+    private float black;
+
+    @SerializedName("emerg")
+    private int emerg;
+
+    @SerializedName("moretime")
+    private int moretime;
+
+    JSONClock() {
+    }
+
+    @Override
+    public boolean running() {
+        return running;
+    }
+
+    @Override
+    public int initial() {
+        return initial;
+    }
+
+    @Override
+    public int increment() {
+        return increment;
+    }
+
+    @Override
+    public float white() {
+        return white;
+    }
+
+    @Override
+    public float black() {
+        return black;
+    }
+
+    @Override
+    public int emerg() {
+        return emerg;
+    }
+
+    @Override
+    public int moretime() {
+        return moretime;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONFormatBuilder.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONFormatBuilder.java
new file mode 100644 (file)
index 0000000..99b936d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import org.hedgecode.chess.scanner.format.lichess.FormatBuilder;
+import org.hedgecode.chess.scanner.format.lichess.GameFormat;
+
+/**
+ * JSONFormatBuilder
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONFormatBuilder implements FormatBuilder {
+
+    private static final Gson GSON = new GsonBuilder().create();
+
+    @Override
+    public GameFormat buildGame(String jsonGame) {
+        return GSON.fromJson(
+                jsonGame,
+                JSONGameFormat.class
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGame.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGame.java
new file mode 100644 (file)
index 0000000..5037cda
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.lichess.Game;
+import org.hedgecode.chess.scanner.format.lichess.Status;
+
+/**
+ * JSONGame
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONGame implements Game {
+
+    @SerializedName("id")
+    private String id;
+
+    @SerializedName("speed")
+    private String speed;
+
+    @SerializedName("rated")
+    private boolean rated;
+
+    @SerializedName("initialFen")
+    private String initialFen;
+
+    @SerializedName("fen")
+    private String fen;
+
+    @SerializedName("player")
+    private String player;
+
+    @SerializedName("turns")
+    private int turns;
+
+    @SerializedName("startedAtTurn")
+    private int startedAtTurn;
+
+    @SerializedName("status")
+    private JSONStatus status;
+
+    @SerializedName("createdAt")
+    private long createdAt;
+
+    @SerializedName("winner")
+    private String winner;
+
+    @SerializedName("lastMove")
+    private String lastMove;
+
+    JSONGame() {
+    }
+
+    @Override
+    public String id() {
+        return id;
+    }
+
+    @Override
+    public String speed() {
+        return speed;
+    }
+
+    @Override
+    public boolean rated() {
+        return rated;
+    }
+
+    @Override
+    public String initialFen() {
+        return initialFen;
+    }
+
+    @Override
+    public String fen() {
+        return fen;
+    }
+
+    @Override
+    public String player() {
+        return player;
+    }
+
+    @Override
+    public int turns() {
+        return turns;
+    }
+
+    @Override
+    public int startedAtTurn() {
+        return startedAtTurn;
+    }
+
+    @Override
+    public Status status() {
+        return status;
+    }
+
+    @Override
+    public long createdAt() {
+        return createdAt;
+    }
+
+    @Override
+    public String winner() {
+        return winner;
+    }
+
+    @Override
+    public String lastMove() {
+        return lastMove;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameData.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameData.java
new file mode 100644 (file)
index 0000000..4562b88
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.Move;
+import org.hedgecode.chess.scanner.format.lichess.Clock;
+import org.hedgecode.chess.scanner.format.lichess.Game;
+import org.hedgecode.chess.scanner.format.lichess.GameData;
+import org.hedgecode.chess.scanner.format.lichess.Player;
+
+/**
+ * JSONGameData
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONGameData implements GameData {
+
+    private static final String PLAYER_WHITE = "white";
+    private static final String PLAYER_BLACK = "black";
+
+    private static final String GAME_DRAW = "draw";
+
+    private static final Map<String, String> RESULT = new HashMap<String, String>() {
+        {
+            put( PLAYER_WHITE, "1-0" );
+            put( PLAYER_BLACK, "0-1" );
+            put( GAME_DRAW, "1/2-1/2");
+        }
+    };
+
+    private static final Map<Boolean, String> RATED_GAME = new HashMap<Boolean, String>() {
+        {
+            put( Boolean.FALSE, "Unrated" );
+            put( Boolean.TRUE,  "Rated"   );
+        }
+    };
+
+    private static final String EVENT_GAME_FORMAT = "%s %s game";
+
+    @SerializedName("game")
+    private JSONGame game;
+
+    @SerializedName("player")
+    private JSONPlayer player;
+
+    @SerializedName("opponent")
+    private JSONPlayer opponent;
+
+    @SerializedName("clock")
+    private JSONClock clock;
+
+    @SerializedName("steps")
+    private JSONMove[] steps;
+
+    @SerializedName("treeParts")
+    private JSONMove[] treeParts;
+
+    @Expose
+    private Move[] moves;
+
+    JSONGameData() {
+    }
+
+    @Override
+    public Game game() {
+        return game;
+    }
+
+    @Override
+    public Player player() {
+        return player;
+    }
+
+    @Override
+    public Player opponent() {
+        return opponent;
+    }
+
+    public String event() {
+        return String.format(
+                EVENT_GAME_FORMAT,
+                RATED_GAME.get(game.rated()),
+                game.speed()
+        );
+    }
+
+    public Player white() {
+        return player.color().equals(PLAYER_WHITE)
+                ? player
+                : opponent.color().equals(PLAYER_WHITE)
+                ? opponent
+                : null;
+    }
+
+    public Player black() {
+        return player.color().equals(PLAYER_BLACK)
+                ? player
+                : opponent.color().equals(PLAYER_BLACK)
+                ? opponent
+                : null;
+    }
+
+    public String result() {
+        String result = null;
+        if (game.winner() != null) {
+            if (PLAYER_WHITE.equals(game.winner())) {
+                result = PLAYER_WHITE;
+            } else if (PLAYER_BLACK.equals(game.winner())) {
+                result = PLAYER_BLACK;
+            }
+        } else if (GAME_DRAW.equals(game.status().name())) {
+            result = GAME_DRAW;
+        }
+        return RESULT.get(result);
+    }
+
+    @Override
+    public Clock clock() {
+        return clock;
+    }
+
+    @Override
+    public Move[] moves() {
+        if (moves == null) {
+            moves = steps != null ? steps : treeParts;
+            List<Move> movesList = new ArrayList<>(Arrays.asList(moves));
+            movesList.removeIf(move -> move.move() == null);
+            moves = movesList.toArray(
+                    new Move[movesList.size()]
+            );
+        }
+        return moves;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameFormat.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONGameFormat.java
new file mode 100644 (file)
index 0000000..973ee64
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import java.util.Date;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.PGNFormat;
+import org.hedgecode.chess.scanner.format.PGNTag;
+import org.hedgecode.chess.scanner.format.TypeMovesFormat;
+import org.hedgecode.chess.scanner.format.lichess.GameData;
+import org.hedgecode.chess.scanner.format.lichess.GameFormat;
+import org.hedgecode.chess.scanner.spi.ServiceRegistry;
+
+/**
+ * JSONGameFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONGameFormat implements GameFormat {
+
+    private static final String TIME_CONTROL_FORMAT = "%d+%d";
+
+    @SerializedName("data")
+    private JSONGameData gameData;
+
+    JSONGameFormat() {
+    }
+
+    @Override
+    public String id() {
+        return gameData.game().id();
+    }
+
+    @Override
+    public GameData gameData() {
+        return gameData;
+    }
+
+    @Override
+    public String pgn() {
+        PGNFormat pgnFormat = ServiceRegistry.singleProvider(
+                PGNFormat.class
+        );
+        Date startDate = new Date(gameData.game().createdAt());
+        pgnFormat.addTag(PGNTag.EVENT, gameData.event());
+        pgnFormat.addTag(PGNTag.DATE, pgnFormat.formatDate(startDate));
+        pgnFormat.addTag(PGNTag.WHITE, gameData.white().user().username());
+        pgnFormat.addTag(PGNTag.BLACK, gameData.black().user().username());
+        pgnFormat.addTag(PGNTag.WHITE_ELO, Integer.toString(gameData.white().rating()));
+        pgnFormat.addTag(PGNTag.BLACK_ELO, Integer.toString(gameData.black().rating()));
+        pgnFormat.addTag(PGNTag.TIME, pgnFormat.formatTime(startDate));
+        pgnFormat.addTag(PGNTag.TIME_CONTROL,
+                String.format(
+                        TIME_CONTROL_FORMAT, gameData.clock().initial(), gameData.clock().increment()
+                )
+        );
+        pgnFormat.addTag(PGNTag.RESULT, gameData.result());
+        if (gameData.game().turns() > 0) {
+            pgnFormat.addTag(PGNTag.PLY_COUNT, Integer.toString(gameData.game().turns()));
+        }
+        if (gameData.game().startedAtTurn() > 0) {
+            pgnFormat.addTag(PGNTag.FEN, gameData.game().fen());
+        }
+        pgnFormat.addMoves(
+                TypeMovesFormat.WRAP.format(gameData.moves())
+        );
+        return pgnFormat.format();
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONMove.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONMove.java
new file mode 100644 (file)
index 0000000..8bc50f8
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.Move;
+
+/**
+ * JSONMove
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONMove implements Move {
+
+    @SerializedName("ply")
+    private int ply;
+
+    @SerializedName("uci")
+    private String uci;
+
+    @SerializedName("san")
+    private String san;
+
+    @SerializedName("fen")
+    private String fen;
+
+    JSONMove() {
+    }
+
+    @Override
+    public int ply() {
+        return ply;
+    }
+
+    @Override
+    public String move() {
+        return san;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONPlayer.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONPlayer.java
new file mode 100644 (file)
index 0000000..8c475e5
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.lichess.Player;
+import org.hedgecode.chess.scanner.format.lichess.User;
+
+/**
+ * JSONPlayer
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONPlayer implements Player {
+
+    @SerializedName("color")
+    private String color;
+
+    @SerializedName("user")
+    private JSONUser user;
+
+    @SerializedName("rating")
+    private int rating;
+
+    @SerializedName("ratingDiff")
+    private int ratingDiff;
+
+    JSONPlayer() {
+    }
+
+    @Override
+    public String color() {
+        return color;
+    }
+
+    @Override
+    public User user() {
+        return user;
+    }
+
+    @Override
+    public int rating() {
+        return rating;
+    }
+
+    @Override
+    public int ratingDiff() {
+        return ratingDiff;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONStatus.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONStatus.java
new file mode 100644 (file)
index 0000000..5cc889f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.lichess.Status;
+
+/**
+ * JSONStatus
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONStatus implements Status {
+
+    @SerializedName("name")
+    private String name;
+
+    JSONStatus() {
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONUser.java b/src/main/java/org/hedgecode/chess/scanner/json/lichess/JSONUser.java
new file mode 100644 (file)
index 0000000..5717158
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.chess.scanner.json.lichess;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.chess.scanner.format.lichess.User;
+
+/**
+ * JSONUser
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JSONUser implements User {
+
+    @SerializedName("id")
+    private String id;
+
+    @SerializedName("username")
+    private String username;
+
+    JSONUser() {
+    }
+
+    @Override
+    public String id() {
+        return id;
+    }
+
+    @Override
+    public String username() {
+        return username;
+    }
+
+}
diff --git a/src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.lichess.FormatBuilder b/src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.lichess.FormatBuilder
new file mode 100644 (file)
index 0000000..715d801
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.scanner.json.lichess.JSONFormatBuilder
\ No newline at end of file