[LIB-13] Add PGN format classes
authorgotty <gotty@hedgecode.org>
Fri, 17 Jan 2020 16:01:41 +0000 (19:01 +0300)
committergotty <gotty@hedgecode.org>
Fri, 17 Jan 2020 16:01:41 +0000 (19:01 +0300)
14 files changed:
src/main/java/org/hedgecode/chess/scanner/format/AbstractPGNFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/GameData.java
src/main/java/org/hedgecode/chess/scanner/format/Move.java
src/main/java/org/hedgecode/chess/scanner/format/MovesFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/PGNConstants.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/PGNFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/PGNTag.java [moved from src/main/java/org/hedgecode/chess/scanner/entity/PGNTag.java with 85% similarity]
src/main/java/org/hedgecode/chess/scanner/format/ReducePGNFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/format/TypeMovesFormat.java [new file with mode: 0644]
src/main/java/org/hedgecode/chess/scanner/json/format/AbstractPGNFormat.java [deleted file]
src/main/java/org/hedgecode/chess/scanner/json/format/JSONGameData.java
src/main/java/org/hedgecode/chess/scanner/json/format/JSONGameFormat.java
src/main/java/org/hedgecode/chess/scanner/json/format/JSONMove.java
src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.PGNFormat [new file with mode: 0644]

diff --git a/src/main/java/org/hedgecode/chess/scanner/format/AbstractPGNFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/AbstractPGNFormat.java
new file mode 100644 (file)
index 0000000..3aee762
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * AbstractPGNFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class AbstractPGNFormat implements PGNFormat {
+
+    private static final String MOVES_FORMAT = "%s %s";
+
+    private final DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");
+    private final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+
+    private final Map<PGNTag, String> pgnTags = new HashMap<>();
+
+    private String pgnMoves;
+
+    @Override
+    public void addTag(PGNTag tag, String value) {
+        pgnTags.put(tag, value);
+    }
+
+    public String getTag(PGNTag tag) {
+        return pgnTags.get(tag);
+    }
+
+    @Override
+    public void addMoves(String moves) {
+        pgnMoves = moves;
+    }
+
+    @Override
+    public String formatDate(Date date) {
+        return dateFormat.format(date);
+    }
+
+    @Override
+    public String formatTime(Date time) {
+        return timeFormat.format(time);
+    }
+
+    protected String formatMoves() {
+        return String.format(
+                MOVES_FORMAT, moves(), result()
+        );
+    }
+
+    protected String formatTagValue(String value) {
+        return value.replaceAll("([\\\\\"])", "\\\\$1");
+    }
+
+    private String moves() {
+        return pgnMoves != null ? pgnMoves : PGNTag.EMPTY;
+    }
+
+    private String result() {
+        String result = pgnTags.get(PGNTag.RESULT);
+        return result != null ? result : PGNTag.RESULT.defaultValue();
+    }
+
+}
index 8b9a02e..a4bc9af 100644 (file)
@@ -21,10 +21,15 @@ package org.hedgecode.chess.scanner.format;
  *
  * @author Dmitry Samoshin aka gotty
  */
-public interface Move {
+public interface Move extends Comparable<Move> {
 
-    int number();
+    int ply();
 
     String move();
 
+    @Override
+    default int compareTo(Move move) {
+        return this.ply() - move.ply();
+    }
+
 }
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/MovesFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/MovesFormat.java
new file mode 100644 (file)
index 0000000..5317efa
--- /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;
+
+/**
+ * MovesFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface MovesFormat {
+
+    String format(Move[] moves);
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/PGNConstants.java b/src/main/java/org/hedgecode/chess/scanner/format/PGNConstants.java
new file mode 100644 (file)
index 0000000..02b8bca
--- /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.format;
+
+/**
+ * PGNConstants
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class PGNConstants {
+
+    public static final int PGN_DEF_LINE_LENGTH = 80;
+    public static final int PGN_MAX_LINE_LENGTH = 255;
+
+    public static final String PGN_CRLF = "\n";
+
+    public static final String WHITE_MOVE_FORMAT = "%d. %s ";
+    public static final String BLACK_MOVE_FORMAT = "%s ";
+
+
+    private PGNConstants() {
+        throw new AssertionError(
+                String.format("No %s instances!", getClass().getName())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/PGNFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/PGNFormat.java
new file mode 100644 (file)
index 0000000..fe7d4ab
--- /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;
+
+import java.util.Date;
+
+/**
+ * PGNFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface PGNFormat {
+
+    void addTag(PGNTag tag, String value);
+
+    void addMoves(String moves);
+
+    String format();
+
+    String formatDate(Date date);
+
+    String formatTime(Date time);
+
+}
  * limitations under the License.
  */
 
-package org.hedgecode.chess.scanner.entity;
+package org.hedgecode.chess.scanner.format;
+
+import java.util.Arrays;
+import java.util.Comparator;
 
 /**
  * PGNTag
@@ -26,10 +29,10 @@ public enum PGNTag {
     EVENT         ( "Event",        true,        PGNTag.QUESTION      ),
     SITE          ( "Site",         true,        PGNTag.QUESTION      ),
     DATE          ( "Date",         true,        PGNTag.QUESTION_DATE ),
-    TIME          ( "Time",         false,       PGNTag.QUESTION_TIME ),
     ROUND         ( "Round",        true,        PGNTag.QUESTION      ),
     WHITE         ( "White",        true,        PGNTag.QUESTION      ),
     BLACK         ( "Black",        true,        PGNTag.QUESTION      ),
+    RESULT        ( "Result",       true,        PGNTag.NON_RESULT    ),
     WHITE_TITLE   ( "WhiteTitle",   false,       PGNTag.HYPHEN        ),
     BLACK_TITLE   ( "BlackTitle",   false,       PGNTag.HYPHEN        ),
     WHITE_ELO     ( "WhiteElo",     false,       PGNTag.HYPHEN        ),
@@ -50,16 +53,16 @@ public enum PGNTag {
     SUBVARIATION  ( "SubVariation", false,       PGNTag.EMPTY         ),
     ECO           ( "ECO",          false,       PGNTag.EMPTY         ),
     NIC           ( "NIC",          false,       PGNTag.EMPTY         ),
-    UTC_DATE      ( "UTCDate",      false,       PGNTag.QUESTION_DATE ),
+    TIME          ( "Time",         false,       PGNTag.QUESTION_TIME ),
     UTC_TIME      ( "UTCTime",      false,       PGNTag.QUESTION_TIME ),
+    UTC_DATE      ( "UTCDate",      false,       PGNTag.QUESTION_DATE ),
     TIME_CONTROL  ( "TimeControl",  false,       PGNTag.QUESTION      ),
     SETUP         ( "SetUp",        false,       PGNTag.ZERO          ),
     FEN           ( "FEN",          false,       PGNTag.EMPTY         ),
     TERMINATION   ( "Termination",  false,       PGNTag.EMPTY         ),
     ANNOTATOR     ( "Annotator",    false,       PGNTag.EMPTY         ),
     MODE          ( "Mode",         false,       PGNTag.EMPTY         ),
-    PLY_COUNT     ( "PlyCount",     false,       PGNTag.EMPTY         ),
-    RESULT        ( "Result",       true,        PGNTag.NON_RESULT    );
+    PLY_COUNT     ( "PlyCount",     false,       PGNTag.EMPTY         );
 
     public static final String EMPTY = "";
     public static final String HYPHEN = "-";
@@ -93,4 +96,27 @@ public enum PGNTag {
         return defaultValue;
     }
 
+    public static PGNTag[] tags() {
+        PGNTag[] tags = values();
+        Arrays.sort(
+                tags, new TagComparator()
+        );
+        return tags;
+    }
+
+    static class TagComparator implements Comparator<PGNTag> {
+
+        @Override
+        public int compare(PGNTag tag1, PGNTag tag2) {
+            if (tag1.isRequired && tag2.isRequired) {
+                return tag1.ordinal() - tag2.ordinal();
+            } else {
+                return tag1.isRequired ? -1
+                        : tag2.isRequired ? 1
+                        : tag1.name().compareTo(tag2.name());
+            }
+        }
+
+    }
+
 }
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/ReducePGNFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/ReducePGNFormat.java
new file mode 100644 (file)
index 0000000..f595dd7
--- /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.format;
+
+import static org.hedgecode.chess.scanner.format.PGNConstants.*;
+
+/**
+ * ReducePGNFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ReducePGNFormat extends AbstractPGNFormat {
+
+    @Override
+    public String format() {
+        StringBuilder sb = new StringBuilder();
+        for (PGNTag tag : PGNTag.tags()) {
+            String tagValue = getTag(tag);
+            if (tag.isRequired() || tagValue != null) {
+                sb.append(
+                        String.format(
+                                PGNTag.TAG_FORMAT,
+                                tag.getName(),
+                                tagValue != null ? formatTagValue(tagValue) : tag.defaultValue()
+                        )
+                ).append(PGN_CRLF);
+            }
+        }
+        sb.append(PGN_CRLF).append(
+                formatMoves()
+        ).append(PGN_CRLF);
+        return sb.toString();
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/format/TypeMovesFormat.java b/src/main/java/org/hedgecode/chess/scanner/format/TypeMovesFormat.java
new file mode 100644 (file)
index 0000000..da2bfbc
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+
+import static org.hedgecode.chess.scanner.format.PGNConstants.*;
+
+/**
+ * TypeMovesFormat
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum TypeMovesFormat {
+
+    LINE ( new LineMovesFormat() ),
+    WRAP ( new WrapMovesFormat() );
+
+    private MovesFormat movesFormat;
+
+    TypeMovesFormat(MovesFormat movesFormat) {
+        this.movesFormat = movesFormat;
+    }
+
+    public String format(Move[] moves) {
+        return movesFormat.format(moves);
+    }
+
+    static class LineMovesFormat extends WrapMovesFormat {
+
+        LineMovesFormat() {
+            super(PGN_MAX_LINE_LENGTH);
+        }
+
+    }
+
+    static class WrapMovesFormat implements MovesFormat {
+
+        private int lineLength;
+
+        WrapMovesFormat() {
+            this(PGN_DEF_LINE_LENGTH);
+        }
+
+        WrapMovesFormat(int length) {
+            lineLength = length;
+        }
+
+        @Override
+        public String format(Move[] moves) {
+            Arrays.sort(moves);
+            int maxLength = lineLength - PGN_CRLF.length();
+            int length = 0;
+            StringBuilder sb = new StringBuilder();
+            for (Move move : moves) {
+                String nextMove = move.ply() % 2 != 0
+                        ? String.format(WHITE_MOVE_FORMAT, move.ply() / 2 + 1, move.move())
+                        : String.format(BLACK_MOVE_FORMAT, move.move());
+                if (length + nextMove.length() > maxLength) {
+                    sb.append(PGN_CRLF);
+                    length = 0;
+                }
+                sb.append(nextMove);
+                length += nextMove.length();
+            }
+            return sb.toString().trim();
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/chess/scanner/json/format/AbstractPGNFormat.java b/src/main/java/org/hedgecode/chess/scanner/json/format/AbstractPGNFormat.java
deleted file mode 100644 (file)
index d0a3b84..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.format;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.hedgecode.chess.scanner.entity.PGNEntity;
-import org.hedgecode.chess.scanner.entity.PGNTag;
-
-import static org.hedgecode.chess.scanner.ChessHogScannerConstants.*;
-
-/**
- * AbstractPGNFormat
- *
- * @author Dmitry Samoshin aka gotty
- */
-public abstract class AbstractPGNFormat extends AbstractBaseFormat implements PGNEntity {
-
-    private static final String EMPTY = "";
-
-    private static final String MOVES_FORMAT = "%s %s";
-
-    private final Map<PGNTag, String> pgnTags = new HashMap<>();
-    private String pgnMoves;
-
-    protected abstract void assignPGN();
-
-    protected void addTag(PGNTag tag, String value) {
-        pgnTags.put(tag, value);
-    }
-
-    protected void addMoves(String moves) {
-        pgnMoves = moves;
-    }
-
-    private String moves() {
-        return pgnMoves != null ? pgnMoves : EMPTY;
-    }
-
-    private String result() {
-        String result = pgnTags.get(PGNTag.RESULT);
-        return result != null ? result : PGNTag.RESULT.defaultValue();
-    }
-
-    @Override
-    public String pgn() {
-        assignPGN();
-        StringBuilder sb = new StringBuilder();
-        for (PGNTag tag : PGNTag.values()) {
-            String tagValue = pgnTags.get(tag);
-            if (tag.isRequired() || tagValue != null) {
-                sb.append(
-                        String.format(
-                                PGNTag.TAG_FORMAT,
-                                tag.getName(),
-                                tagValue != null ? tagValue : tag.defaultValue()
-                        )
-                ).append(CRLF);
-            }
-        }
-        sb.append(CRLF).append(
-                String.format(MOVES_FORMAT, moves(), result())
-        ).append(CRLF);
-        return sb.toString();
-    }
-
-}
index 9761b01..33091a8 100644 (file)
@@ -30,9 +30,6 @@ import org.hedgecode.chess.scanner.format.Room;
  */
 public class JSONGameData implements GameData {
 
-    private static final String WHITE_MOVE_FORMAT = "%d. %s ";
-    private static final String BLACK_MOVE_FORMAT = "%s ";
-
     @SerializedName("game")
     private JSONGame game;
 
@@ -60,21 +57,4 @@ public class JSONGameData implements GameData {
         return moves;
     }
 
-    @Override
-    public String formatMoves() {
-        StringBuilder sb = new StringBuilder();
-        for (Move move : moves) {
-            if (move.number() % 2 == 0) {
-                sb.append(
-                        String.format(WHITE_MOVE_FORMAT, move.number() / 2 + 1, move.move())
-                );
-            } else {
-                sb.append(
-                        String.format(BLACK_MOVE_FORMAT, move.move())
-                );
-            }
-        }
-        return sb.toString();
-    }
-
 }
index 2092d01..0db8233 100644 (file)
 
 package org.hedgecode.chess.scanner.json.format;
 
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-
 import com.google.gson.annotations.SerializedName;
 
-import org.hedgecode.chess.scanner.entity.PGNTag;
+import org.hedgecode.chess.scanner.format.PGNFormat;
+import org.hedgecode.chess.scanner.format.PGNTag;
 import org.hedgecode.chess.scanner.format.GameData;
 import org.hedgecode.chess.scanner.format.GameFormat;
+import org.hedgecode.chess.scanner.format.TypeMovesFormat;
+import org.hedgecode.chess.scanner.spi.ServiceRegistry;
 
 /**
  * JSONGameFormat
  *
  * @author Dmitry Samoshin aka gotty
  */
-public class JSONGameFormat extends AbstractPGNFormat implements GameFormat {
-
-    private final DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");
-    private final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+public class JSONGameFormat extends AbstractBaseFormat implements GameFormat {
 
     @SerializedName("gameData")
     private JSONGameData gameData;
@@ -53,25 +50,31 @@ public class JSONGameFormat extends AbstractPGNFormat implements GameFormat {
         return gameData;
     }
 
+
     @Override
-    protected void assignPGN() {
-        addTag(PGNTag.EVENT, gameData.room().name());
-        addTag(PGNTag.DATE, dateFormat.format(gameData.game().startAt()));
-        addTag(PGNTag.TIME, timeFormat.format(gameData.game().startAt()));
-        addTag(PGNTag.ROUND, gameData.game().roundSlug());
-        addTag(PGNTag.WHITE, gameData.game().white().name());
-        addTag(PGNTag.BLACK, gameData.game().black().name());
-        addTag(PGNTag.WHITE_TITLE, gameData.game().white().title());
-        addTag(PGNTag.BLACK_TITLE, gameData.game().black().title());
-        addTag(PGNTag.WHITE_ELO, Integer.toString(gameData.game().whiteElo()));
-        addTag(PGNTag.BLACK_ELO, Integer.toString(gameData.game().blackElo()));
-        addTag(PGNTag.EVENT_DATE, dateFormat.format(gameData.room().startAt()));
-        addTag(PGNTag.RESULT, gameData.game().result());
+    public String pgn() {
+        PGNFormat pgnFormat = ServiceRegistry.singleProvider(
+                PGNFormat.class
+        );
+        pgnFormat.addTag(PGNTag.EVENT, gameData.room().name());
+        pgnFormat.addTag(PGNTag.DATE, pgnFormat.formatDate(gameData.game().startAt()));
+        pgnFormat.addTag(PGNTag.ROUND, gameData.game().roundSlug());
+        pgnFormat.addTag(PGNTag.WHITE, gameData.game().white().name());
+        pgnFormat.addTag(PGNTag.BLACK, gameData.game().black().name());
+        pgnFormat.addTag(PGNTag.WHITE_TITLE, gameData.game().white().title());
+        pgnFormat.addTag(PGNTag.BLACK_TITLE, gameData.game().black().title());
+        pgnFormat.addTag(PGNTag.WHITE_ELO, Integer.toString(gameData.game().whiteElo()));
+        pgnFormat.addTag(PGNTag.BLACK_ELO, Integer.toString(gameData.game().blackElo()));
+        pgnFormat.addTag(PGNTag.EVENT_DATE, pgnFormat.formatDate(gameData.room().startAt()));
+        pgnFormat.addTag(PGNTag.TIME, pgnFormat.formatTime(gameData.game().startAt()));
+        pgnFormat.addTag(PGNTag.RESULT, gameData.game().result());
         if (gameData.moves().length > 0) {
-            addTag(PGNTag.PLY_COUNT, Integer.toString(gameData.moves().length));
+            pgnFormat.addTag(PGNTag.PLY_COUNT, Integer.toString(gameData.moves().length));
         }
-
-        addMoves(gameData.formatMoves());
+        pgnFormat.addMoves(
+                TypeMovesFormat.WRAP.format(gameData.moves())
+        );
+        return pgnFormat.format();
     }
 
 }
index 6a65e40..0b65d36 100644 (file)
@@ -39,8 +39,8 @@ public class JSONMove implements Move {
     }
 
     @Override
-    public int number() {
-        return ply;
+    public int ply() {
+        return ply + 1;
     }
 
     @Override
diff --git a/src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.PGNFormat b/src/main/resources/META-INF/services/org.hedgecode.chess.scanner.format.PGNFormat
new file mode 100644 (file)
index 0000000..e1c3f84
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.scanner.format.ReducePGNFormat
\ No newline at end of file