Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next: Support Read/Write Sgf with Variation, AW/AB & Comment #364

Merged
merged 5 commits into from
Oct 1, 2018

Conversation

zsalch
Copy link
Contributor

@zsalch zsalch commented Sep 18, 2018

Closes #350

Support following features when Read/Write the SGF file:

  1. Variations tree
  2. AW/AB (Add White)/(Add Black) stone
  3. Comment (C tag)

@zsalch zsalch changed the title Support Read/Write Sgf with Variation, AW/AB & Comment next: Support Read/Write Sgf with Variation, AW/AB & Comment Sep 18, 2018

// close file
builder.append(')');
writer.append(builder.toString());
}

// Generate node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


// close file
builder.append(')');
writer.append(builder.toString());
}

// Generate node
private static String generateNode(Board board, Writer writer, BoardHistoryNode node) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need the writer argument here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Garbage code, deleted.

@@ -250,65 +285,92 @@ private static void saveToStream(Board board, Writer writer) throws IOException
builder.append(String.format("[%c%c]", x, y));
}
}
} else {
// Process the AW/AB stone
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand that else. Can you explain why this should be executed only when handicap == 0?

Copy link
Contributor Author

@zsalch zsalch Sep 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When has handicap, there is Black stones only, the original code already is processed.
The first time I modified the code for lizzie, I didn't want to destroy the original structure too much.
So just add a else.

if (isMultiGo) {
break PARSE_LOOP;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also remove the PARSE_LOOP label (outside the parsing loop)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

if (((int) b & 0x80) != 0) {
continue;
}
// Suppoert unicode charactors (UTF-8)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo Suppoert

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think you should remove that comment. After your changes the code supports unicode because it uses charAt instead of looking that bytes, so it will be hard to understand the comment out of context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

// Initialize the step count
subTreeStepMap.put(Integer.valueOf(subTreeDepth), Integer.valueOf(0));
} else {
if (i > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the i > 0 here? It seems that if we are inside a tag we always want to append that '('

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For skip first '(' that at the top of the Sgf file.

if (isMultiGo) {
break PARSE_LOOP;
// Restore to the variation node
for (int s = 0; s < subTreeStepMap.get(Integer.valueOf(subTreeDepth)).intValue(); s++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit suspicious to recompute subTreeStepMap.get(Integer.valueOf(subTreeDepth)).intValue() at every step of the loop. Any reason for doing that instead of computing that just outside of the for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -134,15 +152,26 @@ private static boolean parse(String value) {
if (move == null) {
Lizzie.board.pass(Stone.BLACK);
} else {
// Save the step count
subTreeStepMap.put(Integer.valueOf(subTreeDepth), Integer.valueOf(subTreeStepMap.get(Integer.valueOf(subTreeDepth)).intValue() + 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off here and a bit all over the PR... Could you configure your text editor to output spaces instead of tabs? The output should look nicer on GitHub and it would also be more consistent with the rest of the lizzie code base.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I have ignored this problem because with multiple editors.
Fixed it.

Lizzie.board.place(move[0], move[1], Stone.BLACK);
}
} else if (tag.equals("W")) {
int[] move = convertSgfPosToCoord(tagContent);
if (move == null) {
Lizzie.board.pass(Stone.WHITE);
} else {
// Save the step count
subTreeStepMap.put(Integer.valueOf(subTreeDepth), Integer.valueOf(subTreeStepMap.get(Integer.valueOf(subTreeDepth)).intValue() + 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line seams to be copy pasted. Is a way to avoid the duplication?

@@ -96,14 +101,27 @@ private static boolean parse(String value) {
case '(':
if (!inTag) {
subTreeDepth += 1;
// Initialize the step count
subTreeStepMap.put(Integer.valueOf(subTreeDepth), Integer.valueOf(0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in Java it's not required to explicitly convert between int and Integer, the java compiler will automatically box and unbox int and Integers to make things work. Concretely this line could be simplified to subTreeStepMap.put(subTreeDepth, 0);

This comment applies for the entirety of this PR, it would be nice if you could go over the diff and remove all the Integer.valueOf() and .intValue() calls that would be automatically inserted, I think the result would be simpler to read!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right.
The previous IDE compiler reported error, now there is no such problem.
Fixed.

@OlivierBlanvillain
Copy link
Contributor

@zsalch These are some really good additions! The only thing that worries be is the absence of tests. The code seams to be rather low level and fragile, and it very hard just by looking at the diff to make sure that you didn't break anything. Also, how is this code going to evolve in the future? In the absence of tests, it would very easy for someone to accidentally break the support for comments of variations without noticing.

My suggestion to move forward would be to add integration tests to this PR. I would like this parsing code to be accompanied with a set of sample games that demonstrate all the features handled by the parser, and a few tests to show that the parser doesn't crash on these games and produces the expected output.

You could maybe start from this commit efc8fe3 where I setup JUnit for the project, and write a simple test for the parser. If you need help with that I might also be able to contribute a test sample to kick start the effort.

Also I think I will wait for this PR to be ready to merge before looking at #365.

@zsalch
Copy link
Contributor Author

zsalch commented Sep 19, 2018

@OlivierBlanvillain

Thank you for your review, so the code is much clearer.

Introducing JUnit is a good idea and I will add some JUnit use cases.

For the test variations and comments, I think sgf e-book will be a good choice, of course, we have just added the AB / AW and C tag processing, for other tags have yet to be added.

I will upload some sgf for testing, but most of them are in Chinese. Maybe you can provide some English sgf files.

Regarding the test points, I think the first thing is the following:

    1. Whether AB/AW and C tag and variations are correctly stored in the NodeList;
    1. Is the AB/AW placed in the correct position;
    1. Whether the variations are displayed correctly;
    1. The comment for each step is displayed correctly;
    1. When saving, AB/AW and C tag and branches are saved correctly.

Since the structure of the Node and the NodeList is not modified, the general operation should be normal when variations are correctly displayed. But this also requires testing to verify.

Before do JUnit testing, you may be want to refer #356 . Here are some simple test cases.

@zsalch
Copy link
Contributor Author

zsalch commented Sep 22, 2018

@OlivierBlanvillain
I have added two simple test cases. Please check.

Copy link
Contributor

@OlivierBlanvillain OlivierBlanvillain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants