package featurecat.lizzie.gui; import featurecat.lizzie.Lizzie; import featurecat.lizzie.util.WindowPosition; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.io.IOException; import java.util.ResourceBundle; import javax.swing.BorderFactory; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import javax.swing.text.ElementIterator; import javax.swing.text.StyleConstants; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.StyleSheet; import org.json.JSONArray; public class GtpConsolePane extends JDialog { private static final ResourceBundle resourceBundle = MainFrame.resourceBundle; // Display Comment private HTMLDocument htmlDoc; private LizziePane.HtmlKit htmlKit; private StyleSheet htmlStyle; private JScrollPane scrollPane; private JTextPane console; private String command; private boolean isAnalyzeCommand = false; private final JTextField txtCommand = new JTextField(); private JLabel lblCommand = new JLabel(); private JPanel pnlCommand = new JPanel(); private final int MAX_HTML_LENGTH = 10000; /** Creates a Gtp Console Window */ public GtpConsolePane(Window owner) { super(owner); setTitle("Gtp Console"); JSONArray pos = WindowPosition.gtpWindowPos(); if (pos != null) { this.setBounds(pos.getInt(0), pos.getInt(1), pos.getInt(2), pos.getInt(3)); } else { Insets oi = owner.getInsets(); setBounds( 0, owner.getY() - oi.top, Math.max(owner.getX() - oi.left, 400), Math.max(owner.getHeight() + oi.top + oi.bottom, 300)); } htmlKit = new LizziePane.HtmlKit(); htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument(); htmlStyle = htmlKit.getStyleSheet(); htmlStyle.addRule(Lizzie.config.gtpConsoleStyle); console = new JTextPane(); console.setBorder(BorderFactory.createEmptyBorder()); console.setEditable(false); console.setEditorKit(htmlKit); console.setDocument(htmlDoc); scrollPane = new JScrollPane(); scrollPane.setBorder(BorderFactory.createEmptyBorder()); txtCommand.setBackground(Color.DARK_GRAY); txtCommand.setForeground(Color.WHITE); lblCommand.setFont(new Font("Tahoma", Font.BOLD, 11)); lblCommand.setOpaque(true); lblCommand.setBackground(Color.DARK_GRAY); lblCommand.setForeground(Color.WHITE); lblCommand.setText(Lizzie.leelaz == null ? "GTP>" : Lizzie.leelaz.currentShortWeight() + ">"); pnlCommand.setLayout(new BorderLayout(0, 0)); pnlCommand.add(lblCommand, BorderLayout.WEST); pnlCommand.add(txtCommand); getContentPane().add(scrollPane, BorderLayout.CENTER); getContentPane().add(pnlCommand, BorderLayout.SOUTH); scrollPane.setViewportView(console); getRootPane().setBorder(BorderFactory.createEmptyBorder()); getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG); txtCommand.addActionListener(e -> postCommand(e)); } public void addCommand(String command, int commandNumber) { if (command == null || command.trim().length() == 0) { return; } lblCommand.setText(Lizzie.leelaz == null ? "GTP>" : Lizzie.leelaz.currentShortWeight() + ">"); this.command = command; this.isAnalyzeCommand = command.startsWith("lz-analyze") || command.startsWith("kata-analyze") || command.startsWith("lz-genmove_analyze"); addText(formatCommand(command, commandNumber)); } public void addLine(String line) { if (line == null || line.trim().length() == 0 || isAnalyzeCommand) { return; } addText(format(line)); } public void addLineForce(String line) { if (line == null || line.trim().length() == 0) { return; } addText(format(line)); } public void addZenCommand(String command, int commandNumber) { if (command == null || command.trim().length() == 0) { return; } addText(formatZenCommand(command, commandNumber)); } private void addText(String text) { try { htmlKit.insertHTML(htmlDoc, htmlDoc.getLength(), text, 0, 0, null); removeOldText(); console.setCaretPosition(htmlDoc.getLength()); } catch (BadLocationException | IOException e) { e.printStackTrace(); } } private void removeOldText() { Element body = htmlDoc.getElement( htmlDoc.getDefaultRootElement(), StyleConstants.NameAttribute, HTML.Tag.BODY); while (htmlDoc.getLength() > MAX_HTML_LENGTH) { ElementIterator it = new ElementIterator(body); it.first(); Element e = it.next(); if (e == null) { break; } htmlDoc.removeElement(e); } } public String formatZenCommand(String command, int commandNumber) { return String.format( "<span class=\"command\">" + ("YAZenGtp") + "> %d %s </span><br />", commandNumber, command); } public String formatCommand(String command, int commandNumber) { return String.format( "<span class=\"command\">" + (Lizzie.leelaz == null ? "GTP" : Lizzie.leelaz.currentShortWeight()) + "> %d %s </span><br />", commandNumber, command); } public String format(String text) { StringBuilder sb = new StringBuilder(); // TODO need better performance text = text.replaceAll("\\b([0-9]{1,3}\\.*[0-9]{0,2}%)", "<span class=\"winrate\">$1</span>") .replaceAll("\\b([A-HJ-Z][1-9][0-9]?)\\b", "<span class=\"coord\">$1</span>") .replaceAll(" (info move)", "<br />$1") .replaceAll("(\r\n)|(\n)", "<br />") .replaceAll(" ", " "); sb.append("<b> </b>").append(text); return sb.toString(); } private void postCommand(ActionEvent e) { if (txtCommand.getText() == null || txtCommand.getText().trim().isEmpty()) { return; } String command = txtCommand.getText().trim(); txtCommand.setText(""); if (Lizzie.leelaz != null) { if (command.startsWith("genmove") || command.startsWith("lz-genmove") || command.startsWith("play")) { String cmdParams[] = command.split(" "); if (cmdParams.length >= 2) { String param1 = cmdParams[1].toUpperCase(); boolean needPass = (Lizzie.board.getData().blackToPlay != "B".equals(param1)); if (needPass) { Lizzie.board.pass(); } if (command.startsWith("genmove") || command.startsWith("lz-genmove")) { if (!Lizzie.leelaz.isThinking) { Lizzie.leelaz.time_settings(); Lizzie.leelaz.isInputCommand = true; if (command.startsWith("genmove")) { Lizzie.leelaz.genmove(param1); } else { Lizzie.leelaz.genmove_analyze(param1); } } } else { if (cmdParams.length >= 3) { String param2 = cmdParams[2].toUpperCase(); Lizzie.board.place(param2); } } } } else if ("clear_board".equals(command)) { Lizzie.board.clear(); } else if ("undo".equals(command)) { Input.undo(); } else if (command.startsWith("boardsize")) { String cmdParams[] = command.split(" "); if (cmdParams.length >= 2) { int width = Integer.parseInt(cmdParams[1]); int height = width; if (cmdParams.length >= 3) { height = Integer.parseInt(cmdParams[2]); } Lizzie.board.reopen(width, height); } } else if (command.startsWith("komi")) { String cmdParams[] = command.split(" "); if (cmdParams.length >= 2) { try { double komi = Double.parseDouble(cmdParams[1]); Lizzie.leelaz.komi(komi); } catch (Exception ex) { } } } else { Lizzie.leelaz.sendCommand(command); } } } }