Skip to content

Commit

Permalink
Merge pull request #413 from zsalch/next_colornode
Browse files Browse the repository at this point in the history
next: Support use different color to indicate move blunder in variation
  • Loading branch information
featurecat authored Nov 8, 2018
2 parents 6a33d28 + c5aab62 commit 94c5a96
Show file tree
Hide file tree
Showing 8 changed files with 597 additions and 398 deletions.
774 changes: 397 additions & 377 deletions src/main/java/featurecat/lizzie/Config.java

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion src/main/java/featurecat/lizzie/gui/Input.java
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,15 @@ public void keyPressed(KeyEvent e) {
break;

case VK_T:
Lizzie.config.toggleShowComment();
if (controlIsPressed(e)) {
Lizzie.config.toggleShowCommentNodeColor();
} else {
Lizzie.config.toggleShowComment();
}
break;

case VK_Y:
Lizzie.config.toggleNodeColorMode();
break;

case VK_C:
Expand Down
57 changes: 56 additions & 1 deletion src/main/java/featurecat/lizzie/gui/LizzieFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import featurecat.lizzie.analysis.Leelaz;
import featurecat.lizzie.rules.Board;
import featurecat.lizzie.rules.BoardData;
import featurecat.lizzie.rules.BoardHistoryNode;
import featurecat.lizzie.rules.GIBParser;
import featurecat.lizzie.rules.SGFParser;
import java.awt.*;
Expand Down Expand Up @@ -72,8 +73,11 @@ public class LizzieFrame extends JFrame {
resourceBundle.getString("LizzieFrame.commands.keyF"),
resourceBundle.getString("LizzieFrame.commands.keyV"),
resourceBundle.getString("LizzieFrame.commands.keyW"),
resourceBundle.getString("LizzieFrame.commands.keyCtrlW"),
resourceBundle.getString("LizzieFrame.commands.keyG"),
resourceBundle.getString("LizzieFrame.commands.keyT"),
resourceBundle.getString("LizzieFrame.commands.keyCtrlT"),
resourceBundle.getString("LizzieFrame.commands.keyY"),
resourceBundle.getString("LizzieFrame.commands.keyHome"),
resourceBundle.getString("LizzieFrame.commands.keyEnd"),
resourceBundle.getString("LizzieFrame.commands.keyControl"),
Expand Down Expand Up @@ -873,7 +877,7 @@ void drawControls() {
Graphics2D g = cachedImage.createGraphics();

int maxSize = min(getWidth(), getHeight());
Font font = new Font(Lizzie.config.fontName, Font.PLAIN, (int) (maxSize * 0.034));
Font font = new Font(Lizzie.config.fontName, Font.PLAIN, (int) (maxSize * 0.03));
g.setFont(font);

FontMetrics metrics = g.getFontMetrics(font);
Expand Down Expand Up @@ -1391,4 +1395,55 @@ private void drawComment(Graphics2D g, int x, int y, int w, int h) {
null);
cachedComment = comment;
}

public double lastWinrateDiff(BoardHistoryNode node) {

// Last winrate
Optional<BoardData> lastNode = node.previous().flatMap(n -> Optional.of(n.getData()));
boolean validLastWinrate = lastNode.map(d -> d.playouts > 0).orElse(false);
double lastWR = validLastWinrate ? lastNode.get().winrate : 50;

// Current winrate
BoardData data = node.getData();
boolean validWinrate = false;
double curWR = 50;
if (data == Lizzie.board.getHistory().getData()) {
Leelaz.WinrateStats stats = Lizzie.leelaz.getWinrateStats();
curWR = stats.maxWinrate;
validWinrate = (stats.totalPlayouts > 0);
if (isPlayingAgainstLeelaz
&& playerIsBlack == !Lizzie.board.getHistory().getData().blackToPlay) {
validWinrate = false;
}
} else {
validWinrate = (data.playouts > 0);
curWR = validWinrate ? data.winrate : 100 - lastWR;
}

// Last move difference winrate
if (validLastWinrate && validWinrate) {
return 100 - lastWR - curWR;
} else {
return 0;
}
}

public Color getBlunderNodeColor(BoardHistoryNode node) {
if (Lizzie.config.nodeColorMode == 1 && node.getData().blackToPlay
|| Lizzie.config.nodeColorMode == 2 && !node.getData().blackToPlay) {
return Color.WHITE;
}
double diffWinrate = lastWinrateDiff(node);
Optional<Double> st =
diffWinrate >= 0
? Lizzie.config.blunderWinrateThresholds.flatMap(
l -> l.stream().filter(t -> (t > 0 && t <= diffWinrate)).reduce((f, s) -> s))
: Lizzie.config.blunderWinrateThresholds.flatMap(
l -> l.stream().filter(t -> (t < 0 && t >= diffWinrate)).reduce((f, s) -> f));
if (st.isPresent()) {
return Lizzie.config.blunderNodeColors.map(m -> m.get(st.get())).get();
} else {
return Color.WHITE;
}
}
}
87 changes: 68 additions & 19 deletions src/main/java/featurecat/lizzie/gui/VariationTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ public class VariationTree {
private int YSPACING;
private int XSPACING;
private int DOT_DIAM = 11; // Should be odd number
private int DOT_DIAM_S = 9; // For small node
private int CENTER_DIAM = 5;
private int RING_DIAM = 15;
private int diam = DOT_DIAM;

private ArrayList<Integer> laneUsageList;
private BoardHistoryNode curMove;
Expand Down Expand Up @@ -54,47 +58,68 @@ public void drawTree(
BoardHistoryNode cur = startNode;
int curposx = posx + lane * XSPACING;
int dotoffset = DOT_DIAM / 2;
if (Lizzie.config.nodeColorMode == 1 && cur.getData().blackToPlay
|| Lizzie.config.nodeColorMode == 2 && !cur.getData().blackToPlay) {
diam = DOT_DIAM_S;
} else {
diam = DOT_DIAM;
}
int dotoffsety = diam / 2;
int diff = (DOT_DIAM - diam) / 2;

// Draw line back to main branch
if (lane > 0) {

// Draw line back to main branch
if (lane - startLane > 0 || variationNumber > 1) {
// Need a horizontal and an angled line
drawLine(
g,
curposx + dotoffset,
posy + dotoffset,
posy + dotoffsety,
curposx + dotoffset - XSPACING,
posy + dotoffset - YSPACING,
posy + dotoffsety - YSPACING,
minposx);
drawLine(
g,
posx + (startLane - variationNumber) * XSPACING + 2 * dotoffset,
posy - YSPACING + dotoffset,
posy - YSPACING + dotoffsety,
curposx + dotoffset - XSPACING,
posy + dotoffset - YSPACING,
posy + dotoffsety - YSPACING,
minposx);
} else {
// Just an angled line
drawLine(
g,
curposx + dotoffset,
posy + dotoffset,
posy + dotoffsety,
curposx + 2 * dotoffset - XSPACING,
posy + 2 * dotoffset - YSPACING,
posy + 2 * dotoffsety - YSPACING,
minposx);
}
}

// Draw all the nodes and lines in this lane (not variations)
Color curcolor = g.getColor();
if (curposx > minposx && posy > 0) {
if (startNode == curMove) {
g.setColor(Color.green.brighter().brighter());
}
if (startNode.previous().isPresent()) {
g.fillOval(curposx, posy, DOT_DIAM, DOT_DIAM);
g.setColor(Color.BLACK);
g.drawOval(curposx, posy, DOT_DIAM, DOT_DIAM);
if (Lizzie.config.showCommentNodeColor && !cur.getData().comment.isEmpty()) {
g.setColor(Lizzie.config.commentNodeColor);
g.fillOval(
curposx + (DOT_DIAM + diff - RING_DIAM) / 2,
posy + (DOT_DIAM + diff - RING_DIAM) / 2,
RING_DIAM,
RING_DIAM);
}
g.setColor(Lizzie.frame.getBlunderNodeColor(cur));
g.fillOval(curposx + diff, posy + diff, diam, diam);
if (startNode == curMove) {
g.setColor(Color.BLACK);
g.fillOval(
curposx + (DOT_DIAM + diff - CENTER_DIAM) / 2,
posy + (DOT_DIAM + diff - CENTER_DIAM) / 2,
CENTER_DIAM,
CENTER_DIAM);
}
} else {
g.fillRect(curposx, posy, DOT_DIAM, DOT_DIAM);
g.setColor(Color.BLACK);
Expand All @@ -108,18 +133,42 @@ public void drawTree(
posy += YSPACING;
cur = cur.next().get();
if (curposx > minposx && posy > 0) {
if (Lizzie.config.nodeColorMode == 1 && cur.getData().blackToPlay
|| Lizzie.config.nodeColorMode == 2 && !cur.getData().blackToPlay) {
diam = DOT_DIAM_S;
} else {
diam = DOT_DIAM;
}
dotoffsety = diam / 2;
diff = (DOT_DIAM - diam) / 2;
if (Lizzie.config.showCommentNodeColor && !cur.getData().comment.isEmpty()) {
g.setColor(Lizzie.config.commentNodeColor);
g.fillOval(
curposx + (DOT_DIAM + diff - RING_DIAM) / 2,
posy + (DOT_DIAM + diff - RING_DIAM) / 2,
RING_DIAM,
RING_DIAM);
}
g.setColor(Lizzie.frame.getBlunderNodeColor(cur));
g.fillOval(curposx + diff, posy + diff, diam, diam);
if (cur == curMove) {
g.setColor(Color.green.brighter().brighter());
g.setColor(Color.BLACK);
g.fillOval(
curposx + (DOT_DIAM + diff - CENTER_DIAM) / 2,
posy + (DOT_DIAM + diff - CENTER_DIAM) / 2,
CENTER_DIAM,
CENTER_DIAM);
}
g.fillOval(curposx, posy, DOT_DIAM, DOT_DIAM);
g.setColor(Color.BLACK);
g.drawOval(curposx, posy, DOT_DIAM, DOT_DIAM);
g.setColor(curcolor);
g.drawLine(
curposx + dotoffset,
posy - 1,
posy - 1 + diff,
curposx + dotoffset,
posy - YSPACING + 2 * dotoffset + 2);
posy
- YSPACING
+ dotoffset
+ (diff > 0 ? dotoffset + 1 : dotoffsety)
+ (Lizzie.config.nodeColorMode == 0 ? 1 : 0));
}
}
// Now we have drawn all the nodes in this variation, and has reached the bottom of this
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/featurecat/lizzie/theme/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.IntStream;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import org.json.JSONArray;
Expand All @@ -26,6 +32,7 @@ public class Theme {
private String path = null;
private JSONObject config = new JSONObject();
private JSONObject uiConfig = null;
private Optional<List<Double>> blunderWinrateThresholds = Optional.empty();

public Theme(JSONObject uiConfig) {
this.uiConfig = uiConfig;
Expand Down Expand Up @@ -96,6 +103,12 @@ public boolean solidStoneIndicator() {
return config.optBoolean(key, uiConfig.optBoolean(key));
}

/** Show the node with the comment color */
public boolean showCommentNodeColor() {
String key = "show-comment-node-color";
return config.optBoolean(key, uiConfig.optBoolean(key, true));
}

/** The size of the shadow */
public int shadowSize() {
return getIntByKey("shadow-size", 100);
Expand All @@ -116,6 +129,11 @@ public int commentFontSize() {
return getIntByKey("comment-font-size", 3);
}

/** The size of the shadow */
public int nodeColorMode() {
return getIntByKey("node-color-mode", 0);
}

/**
* The background color of the comment panel
*
Expand All @@ -130,6 +148,11 @@ public Color commentFontColor() {
return getColorByKey("comment-font-color", Color.WHITE);
}

/** The color of the node with the comment */
public Color commentNodeColor() {
return getColorByKey("comment-node-color", Color.BLUE.brighter());
}

/** The color of the winrate line */
public Color winrateLineColor() {
return getColorByKey("winrate-line-color", Color.green);
Expand All @@ -145,6 +168,41 @@ public Color blunderBarColor() {
return getColorByKey("blunder-bar-color", new Color(255, 0, 0, 150));
}

/** The threshold list of the blunder winrate */
public Optional<List<Double>> blunderWinrateThresholds() {
String key = "blunder-winrate-thresholds";
Optional<JSONArray> array = Optional.ofNullable(config.optJSONArray(key));
if (!array.isPresent()) {
array = Optional.ofNullable(uiConfig.optJSONArray(key));
}
array.ifPresent(
m -> {
blunderWinrateThresholds = Optional.of(new ArrayList<Double>());
m.forEach(a -> blunderWinrateThresholds.get().add(new Double(a.toString())));
});
return blunderWinrateThresholds;
}

/** The color list of the blunder node */
public Optional<Map<Double, Color>> blunderNodeColors() {
Optional<Map<Double, Color>> map = Optional.of(new HashMap<Double, Color>());
String key = "blunder-node-colors";
Optional<JSONArray> array = Optional.ofNullable(config.optJSONArray(key));
if (!array.isPresent()) {
array = Optional.ofNullable(uiConfig.optJSONArray(key));
}
array.ifPresent(
a -> {
IntStream.range(0, a.length())
.forEach(
i -> {
Color color = array2Color((JSONArray) a.get(i), null);
blunderWinrateThresholds.map(l -> l.get(i)).map(t -> map.get().put(t, color));
});
});
return map;
}

private Color getColorByKey(String key, Color defaultColor) {
Color color = array2Color(config.optJSONArray(key), null);
if (color == null) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/l10n/DisplayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ LizzieFrame.commands.keyEnter=enter|force Leela Zero move
LizzieFrame.commands.keyF=f|toggle next move display
LizzieFrame.commands.keyG=g|toggle variation graph
LizzieFrame.commands.keyT=t|toggle comment display
LizzieFrame.commands.keyCtrlT=ctrl-t|toggle comment node color display
LizzieFrame.commands.keyHome=home|go to start
LizzieFrame.commands.keyI=i|edit game info
LizzieFrame.commands.keyA=a|run automatic analysis of game
Expand All @@ -38,6 +39,8 @@ LizzieFrame.commands.keySpace=space|toggle pondering
LizzieFrame.commands.keyUpArrow=up arrow|undo
LizzieFrame.commands.keyV=v|toggle variation display
LizzieFrame.commands.keyW=w|toggle winrate display
LizzieFrame.commands.keyCtrlW=ctrl-w|toggle large winrate graph
LizzieFrame.commands.keyY=y|toggle color node display
LizzieFrame.commands.keyPeriod=.|score game
LizzieFrame.commands.mouseWheelScroll=scrollwheel|undo/redo
LizzieFrame.commands.rightClick=right click|undo
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/l10n/DisplayStrings_RO.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ LizzieFrame.commands.keyEnter=enter|forțează mutarea lui Leela Zero
LizzieFrame.commands.keyF=f|afișează/ascunde următoarea mutare
LizzieFrame.commands.keyG=g|afișează/ascunde graficul cu variante
LizzieFrame.commands.keyT=t|afișează/ascunde comentariul
LizzieFrame.commands.keyCtrlT=ctrl-t|afișează/ascunde culoarea nodului comentariu
LizzieFrame.commands.keyHome=home|mergi la început
LizzieFrame.commands.keyI=i|editează informațiile jocului
LizzieFrame.commands.keyA=a|rulează analiza automată a jocului
Expand All @@ -37,6 +38,8 @@ LizzieFrame.commands.keySpace=spațiu|pornește/oprește analiza
LizzieFrame.commands.keyUpArrow=săgeată sus|înapoi
LizzieFrame.commands.keyV=v|afișează/ascunde variante
LizzieFrame.commands.keyW=w|afișează/ascunde probabilitate victorie
LizzieFrame.commands.keyCtrlW=ctrl-w|afiÈ™ează/ascunde graficul de câ\u0219tiguri mari
LizzieFrame.commands.keyY=y|comuta\u021Bi afi\u0219area nodului de culoare
LizzieFrame.commands.keyPeriod=.|scor
LizzieFrame.commands.mouseWheelScroll=rotiță mouse|înainte/înapoi
LizzieFrame.commands.rightClick=clic dreapta|înapoi
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/l10n/DisplayStrings_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ LizzieFrame.commands.keyEnter=enter|\u8BA9Leela Zero\u843D\u5B50
LizzieFrame.commands.keyF=f|\u663E\u793A/\u9690\u85CF\u4E0B\u4E00\u624B
LizzieFrame.commands.keyG=g|\u663E\u793A/\u9690\u85CF\u5206\u652F\u56FE
LizzieFrame.commands.keyT=t|\u663E\u793A/\u9690\u85CF\u8BC4\u8BBA
LizzieFrame.commands.keyCtrlT=ctrl-t|\u663E\u793A/\u9690\u85CF\u8BC4\u8BBA\u8282\u70B9\u989C\u8272
LizzieFrame.commands.keyHome=home|\u8DF3\u8F6C\u5230\u68CB\u8C31\u5F00\u5934
LizzieFrame.commands.keyI=i|\u7F16\u8F91\u68CB\u5C40\u4FE1\u606F
LizzieFrame.commands.keyA=a|\u8FD0\u884C\u7B80\u5355\u7684\u81EA\u52A8\u5168\u76D8\u5206\u6790
Expand All @@ -26,6 +27,8 @@ LizzieFrame.commands.keySpace=\u7A7A\u683C|\u542F\u52A8/\u6682\u505C\u540E\u53F0
LizzieFrame.commands.keyUpArrow=\u4E0A\u65B9\u5411\u952E|\u56DE\u9000\u4E00\u6B65
LizzieFrame.commands.keyV=v|\u663E\u793A/\u9690\u85CF\u53D8\u5316\u56FE
LizzieFrame.commands.keyW=w|\u663E\u793A/\u9690\u85CF\u80DC\u7387\u56FE
LizzieFrame.commands.keyCtrlW=ctrl-w|\u5207\u6362\u5927\u80DC\u7387\u56FE
LizzieFrame.commands.keyY=y|\u5207\u6362\u8282\u70B9\u989C\u8272\u663E\u793A
LizzieFrame.commands.keyPeriod=.(\u5C0F\u6570\u70B9)|\u70B9\u76EE
LizzieFrame.commands.mouseWheelScroll=\u9F20\u6807\u6EDA\u8F6E|\u5728\u68CB\u8C31\u4E2D\u5411\u524D/\u5411\u540E\u79FB\u52A8
LizzieFrame.commands.rightClick=\u9F20\u6807\u53F3\u952E|\u56DE\u4E0A\u4E00\u624B
Expand Down

0 comments on commit 94c5a96

Please sign in to comment.