diff --git a/src/main/java/featurecat/lizzie/gui/MoveListFrame.java b/src/main/java/featurecat/lizzie/gui/MoveListFrame.java index d7db83e00..bf0efb35b 100644 --- a/src/main/java/featurecat/lizzie/gui/MoveListFrame.java +++ b/src/main/java/featurecat/lizzie/gui/MoveListFrame.java @@ -1321,8 +1321,8 @@ public void actionPerformed(ActionEvent evt) { ((JLabel) headerRenderer2).setHorizontalAlignment(JLabel.CENTER); } headerMint2.setDefaultRenderer(headerRenderer2); - - checkBlack.setSelected(true); + + checkBlack.setSelected(true); checkWhite.setSelected(true); checkBlack.addItemListener( diff --git a/src/main/java/featurecat/lizzie/rules/SGFParser.java b/src/main/java/featurecat/lizzie/rules/SGFParser.java index 752f7a964..de31ac1a2 100644 --- a/src/main/java/featurecat/lizzie/rules/SGFParser.java +++ b/src/main/java/featurecat/lizzie/rules/SGFParser.java @@ -2854,11 +2854,19 @@ private static String parseResult(String value) { * * @return */ - public static String propertiesString(Map props) { - StringBuilder sb = new StringBuilder(); - props.forEach((key, value) -> sb.append(nodeString(key, value))); - return sb.toString(); - } + public static String propertiesString(Map props) { + StringBuilder sb = new StringBuilder(); + if (props.containsKey("CA")) { + sb.append(nodeString("CA", props.get("CA"))); + } + props.forEach( + (key, value) -> { + if (!"CA".equals(key)) { + sb.append(nodeString(key, value)); + } + }); + return sb.toString(); + } /** * Get node string by the key and value diff --git a/src/test/java/featurecat/lizzie/analysis/LeelazDisplayNameTest.java b/src/test/java/featurecat/lizzie/analysis/LeelazDisplayNameTest.java index b49ad2d39..ebb71295e 100644 --- a/src/test/java/featurecat/lizzie/analysis/LeelazDisplayNameTest.java +++ b/src/test/java/featurecat/lizzie/analysis/LeelazDisplayNameTest.java @@ -45,4 +45,21 @@ void tensorRtBackendNameDoesNotReplaceWeightDisplayName() { assertEquals("zhizi 28B muonfd2", Leelaz.friendlyEngineName("KataGo TensorRT", command)); } + + @Test + void weightDisplayHandlesMultipleSpacesAfterModelFlag() { + String command = + "\"/tmp/katago\" gtp -model \"/tmp/weights/kata1-b28c512nbt-s12763923712-d5805955894.bin.gz\"" + + " -config \"/tmp/gtp.cfg\""; + + assertEquals("28B", Leelaz.friendlyEngineName("KataGo Auto Setup", command)); + } + + @Test + void weightDisplayHandlesEqualsStyleWeightsFlag() { + String command = + "\"/tmp/leelaz\" --weights=/tmp/weights/kata1-zhizi-b28c512nbt-muonfd2.bin.gz"; + + assertEquals("zhizi 28B muonfd2", Leelaz.friendlyEngineName("KataGo Auto Setup", command)); + } } diff --git a/src/test/java/featurecat/lizzie/rules/BoardNodeKindHistoryPipelineTest.java b/src/test/java/featurecat/lizzie/rules/BoardNodeKindHistoryPipelineTest.java index 115dda2c3..7b5cbc4d1 100644 --- a/src/test/java/featurecat/lizzie/rules/BoardNodeKindHistoryPipelineTest.java +++ b/src/test/java/featurecat/lizzie/rules/BoardNodeKindHistoryPipelineTest.java @@ -28,8 +28,10 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Optional; import java.util.ResourceBundle; import java.util.regex.Matcher; @@ -40,6 +42,14 @@ class BoardNodeKindHistoryPipelineTest { private static final int BOARD_SIZE = 3; private static final int BOARD_AREA = BOARD_SIZE * BOARD_SIZE; + @Test + void asCoordinatesParsesExtendedGtpColumnsOnLargeBoards() { + Optional coord = Board.asCoordinates("BA4", 60); + + assertTrue(coord.isPresent(), "extended GTP coordinates should parse on large boards."); + assertArrayEquals(new int[] {50, 56}, coord.get()); + } + @Test void addOrGotoKeepsPassAndSnapshotAsSeparateChildren() throws Exception { TestEnvironment env = TestEnvironment.open(); @@ -2725,21 +2735,43 @@ void detachedParseSgfLzopKeepsLiveBoardAnalysisStateUntouched() throws Exception } } + @Test + void parseSgfKeepsSemicolonsInsideRootCommentValues() throws Exception { + TestEnvironment env = TestEnvironment.open(); + try { + BoardHistoryList parsed = SGFParser.parseSgf("(;SZ[3]C[a;b;c;];B[aa])", false); + + assertEquals("a;b;c;", parsed.getStart().getData().comment); + } finally { + env.close(); + } + } + + @Test + void propertiesStringSerializesCharsetBeforeLocalizedProperties() { + Map props = new LinkedHashMap<>(); + props.put("PB", "黑棋"); + props.put("PW", "白棋"); + props.put("CA", "UTF-8"); + + assertEquals("CA[UTF-8]PB[黑棋]PW[白棋]", SGFParser.propertiesString(props)); + } + @Test void parseSgfDetachedAnalysisShorthandKPlayoutsKeepLegacyScaleOnRoundTrip() throws Exception { TestEnvironment env = TestEnvironment.open(); try { String sgf = - "(;SZ[3]LZOP[MainEngine 44.0 1.2k\n" - + "move D4 visits 1.2k winrate 5600 prior 5000 pv D4 C4])"; + "(;SZ[3]LZOP[MainEngine 44.0 1.5k\n" + + "move D4 visits 1.5k winrate 5600 prior 5000 pv D4 C4])"; BoardHistoryList parsed = SGFParser.parseSgf(sgf, false); - assertEquals(1200, parsed.getStart().getData().getPlayouts()); + assertEquals(1500, parsed.getStart().getData().getPlayouts()); Lizzie.board.setHistory(parsed); String exported = SGFParser.saveToString(false); BoardData roundTripRoot = SGFParser.parseSgf(exported, false).getStart().getData(); - assertEquals(1200, roundTripRoot.getPlayouts()); + assertEquals(1500, roundTripRoot.getPlayouts()); } finally { env.close(); } @@ -2782,9 +2814,9 @@ void saveRootSetupKeepsSetupOnlyOnRootAndStaysStableAcrossRoundTrip() throws Exc Lizzie.board.setHistory(history); String expected = - "(;AB[aa]AW[cc]PL[W]SZ[3]KM[6.5]PW[White]PB[Black]DT[2020-01-02]AP[LizzieYzy Next: " + "(;CA[UTF-8]AB[aa]AW[cc]PL[W]SZ[3]KM[6.5]PW[White]PB[Black]DT[2020-01-02]AP[LizzieYzy Next: " + Lizzie.nextVersion - + "]RE[]CA[UTF-8];B[ba])"; + + "]RE[];B[ba])"; String firstSave = SGFParser.saveToString(false); assertEquals(expected, firstSave, "root setup should be serialized only once on root."); String secondSave = SGFParser.saveToString(false);