Moving to correct packages chess
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 24 Sep 2013 22:37:17 +0200
branchchess
changeset 513f1866fdb2a1
parent 50 49011b4a2689
child 52 6bb4070d2c20
Moving to correct packages
chess/pom.xml
chess/src/main/java/com/oracle/chess/client/htmljava/BoardModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/Color.java
chess/src/main/java/com/oracle/chess/client/htmljava/Communication.java
chess/src/main/java/com/oracle/chess/client/htmljava/GamesModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/LoadMain.java
chess/src/main/java/com/oracle/chess/client/htmljava/Main.java
chess/src/main/java/com/oracle/chess/client/htmljava/MsgType.java
chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java
chess/src/main/java/com/oracle/chess/client/htmljava/SettingsModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java
chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java
chess/src/main/java/org/apidesign/html/demo/chess/Color.java
chess/src/main/java/org/apidesign/html/demo/chess/Communication.java
chess/src/main/java/org/apidesign/html/demo/chess/GamesModel.java
chess/src/main/java/org/apidesign/html/demo/chess/LoadMain.java
chess/src/main/java/org/apidesign/html/demo/chess/Main.java
chess/src/main/java/org/apidesign/html/demo/chess/MsgType.java
chess/src/main/java/org/apidesign/html/demo/chess/Rules.java
chess/src/main/java/org/apidesign/html/demo/chess/SettingsModel.java
chess/src/main/java/org/apidesign/html/demo/chess/UIModel.java
chess/src/test/java/com/oracle/chess/client/htmljava/BoardModelTest.java
chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java
     1.1 --- a/chess/pom.xml	Tue Sep 24 22:28:31 2013 +0200
     1.2 +++ b/chess/pom.xml	Tue Sep 24 22:37:17 2013 +0200
     1.3 @@ -7,8 +7,8 @@
     1.4          <version>1.0-SNAPSHOT</version>
     1.5      </parent>
     1.6  
     1.7 -  <groupId>com.oracle.chess</groupId>
     1.8 -  <artifactId>ChessHTMLJavaClient</artifactId>
     1.9 +  <groupId>org.apidesign.html.demo</groupId>
    1.10 +  <artifactId>chessdemo</artifactId>
    1.11    <version>1.0-SNAPSHOT</version>
    1.12    <packaging>jar</packaging>
    1.13  
    1.14 @@ -58,7 +58,7 @@
    1.15                <configuration>
    1.16                    <archive>
    1.17                        <manifest>
    1.18 -                          <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
    1.19 +                          <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
    1.20                            <addClasspath>true</addClasspath>
    1.21                            <classpathPrefix>lib/</classpathPrefix>
    1.22                        </manifest>
    1.23 @@ -76,7 +76,7 @@
    1.24                            <value>${basedir}/src/main/webapp/</value>
    1.25                        </systemProperty>
    1.26                    </systemProperties>
    1.27 -                  <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
    1.28 +                  <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
    1.29                </configuration>
    1.30            </plugin>      
    1.31            <plugin>
     2.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/BoardModel.java	Tue Sep 24 22:28:31 2013 +0200
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,451 +0,0 @@
     2.4 -/**
     2.5 - * The MIT License (MIT)
     2.6 - *
     2.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.8 - *
     2.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.10 - * of this software and associated documentation files (the "Software"), to deal
    2.11 - * in the Software without restriction, including without limitation the rights
    2.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    2.13 - * copies of the Software, and to permit persons to whom the Software is
    2.14 - * furnished to do so, subject to the following conditions:
    2.15 - *
    2.16 - * The above copyright notice and this permission notice shall be included in
    2.17 - * all copies or substantial portions of the Software.
    2.18 - *
    2.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    2.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    2.25 - * THE SOFTWARE.
    2.26 - */
    2.27 -package com.oracle.chess.client.htmljava;
    2.28 -
    2.29 -import com.oracle.chess.client.htmljava.Communication.AlertType;
    2.30 -import java.util.Arrays;
    2.31 -import java.util.Collections;
    2.32 -import java.util.List;
    2.33 -import java.util.Timer;
    2.34 -import java.util.TimerTask;
    2.35 -import net.java.html.json.ComputedProperty;
    2.36 -import net.java.html.json.Function;
    2.37 -import net.java.html.json.Model;
    2.38 -import net.java.html.json.ModelOperation;
    2.39 -import net.java.html.json.OnPropertyChange;
    2.40 -import net.java.html.json.Property;
    2.41 -import net.java.html.sound.AudioClip;
    2.42 -
    2.43 -@Model(className="Board", properties={
    2.44 -    @Property(name = "player", type = String.class),
    2.45 -    @Property(name = "gameId", type = String.class),
    2.46 -    @Property(name = "whitePlayer", type = String.class),
    2.47 -    @Property(name = "blackPlayer", type = String.class),
    2.48 -    @Property(name = "alert", type = Alert.class),
    2.49 -    @Property(name = "alertMessage", type = String.class),
    2.50 -    @Property(name = "status", type = String.class),
    2.51 -    @Property(name = "rows", type = Row.class, array = true),
    2.52 -    @Property(name = "turn", type = Color.class),
    2.53 -    @Property(name = "moves", type = Move.class, array = true),
    2.54 -    @Property(name = "pendingMove", type = Move.class),
    2.55 -    @Property(name = "active", type = boolean.class),
    2.56 -})
    2.57 -public class BoardModel {
    2.58 -    @ComputedProperty static String title(String status, String gameId) {
    2.59 -        String t = status != null ? status : gameId;
    2.60 -        if (t != null && t.length() > 10) {
    2.61 -            return t.substring(0, 10);
    2.62 -        }
    2.63 -        return t;
    2.64 -    }
    2.65 -
    2.66 -    @ModelOperation static void updateSummary(Board b, String summary) {
    2.67 -        if (summary != null) {
    2.68 -            b.setStatus(summary);
    2.69 -        }
    2.70 -    }
    2.71 -    
    2.72 -    @ComputedProperty static boolean myTurn(String player, String whitePlayer, String blackPlayer, Color turn) {
    2.73 -        if (turn != null && player != null) switch (turn) {
    2.74 -            case B: return player.equals(blackPlayer);
    2.75 -            case W: return player.equals(whitePlayer);
    2.76 -        }
    2.77 -        return false;
    2.78 -    }
    2.79 -    
    2.80 -    @ComputedProperty static boolean justObserving(String player) {
    2.81 -        return player == null;
    2.82 -    }
    2.83 -    
    2.84 -    private static final AudioClip MOVE = AudioClip.create("sounds/move.mp3");
    2.85 -    @OnPropertyChange("moves") static void playMove() {
    2.86 -        MOVE.play();
    2.87 -    }
    2.88 -
    2.89 -    private static final AudioClip CHECK = AudioClip.create("sounds/check.mp3");
    2.90 -    private static final AudioClip CHECKMATE = AudioClip.create("sounds/checkmate.mp3");
    2.91 -    @OnPropertyChange("alert") static void warnCheckAndMate(Board b) {
    2.92 -        if (b.getAlert() == null) {
    2.93 -            return;
    2.94 -        }
    2.95 -        if (b.getAlert().getType() == AlertType.CHECK) {
    2.96 -            CHECK.play();
    2.97 -        }
    2.98 -        if (b.getAlert().getType() == AlertType.CHECKMATE) {
    2.99 -            CHECKMATE.play();
   2.100 -        }
   2.101 -    }
   2.102 -    
   2.103 -    @Function static void selected(Board b, Square data) {
   2.104 -        if (!b.isMyTurn()) {
   2.105 -            b.setAlertMessage("Not your turn!");
   2.106 -            return;
   2.107 -        }
   2.108 -        
   2.109 -        Square previoslySelected = findSelectedSquare(b);
   2.110 -        if (previoslySelected == null) {
   2.111 -            if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
   2.112 -                data.setSelected(true);
   2.113 -                Rules.computeAccessible(b, data);
   2.114 -            }
   2.115 -        } else {
   2.116 -            if (previoslySelected == data) {
   2.117 -                data.setSelected(false);
   2.118 -                Rules.computeAccessible(b, null);
   2.119 -                return;
   2.120 -            }
   2.121 -            if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
   2.122 -                previoslySelected.setSelected(false);
   2.123 -                data.setSelected(true);
   2.124 -                Rules.computeAccessible(b, data);
   2.125 -                return;
   2.126 -            }
   2.127 -            if (data.isAccessible()) {
   2.128 -                previoslySelected.setSelected(false);
   2.129 -
   2.130 -                Move newMove = new Move();
   2.131 -                newMove.setFrom(previoslySelected.getPosition());
   2.132 -                newMove.setTo(data.getPosition());
   2.133 -                newMove.setRound(b.getMoves().size() / 2 + 1);
   2.134 -                newMove.setPiece(previoslySelected.getPiece());
   2.135 -                newMove.setTurn(previoslySelected.getPieceColor());
   2.136 -                newMove.setTakes(data.getPiece() != null);
   2.137 -                b.getMoves().add(newMove);
   2.138 -                b.setPendingMove(newMove);
   2.139 -
   2.140 -                data.setPending(true);
   2.141 -                data.setPieceColor(previoslySelected.getPieceColor());
   2.142 -                data.setPiece(previoslySelected.getPiece());
   2.143 -                b.setTurn(null);
   2.144 -                previoslySelected.setPiece(null);
   2.145 -                previoslySelected.setPieceColor(null);
   2.146 -                Rules.computeAccessible(b, null);
   2.147 -
   2.148 -                Request sm = new Request();
   2.149 -                sm.setMsg(MsgType.SendMove);
   2.150 -                sm.setGameId(b.getGameId());
   2.151 -                sm.setFrom(newMove.getFrom().getLocation());
   2.152 -                sm.setTo(newMove.getTo().getLocation());
   2.153 -                sm.setColor(newMove.getTurn());
   2.154 -                final UI ui = UIModel.findUI(b);
   2.155 -                if (ui != null) {
   2.156 -                    ui.sendMsg(sm);
   2.157 -                }
   2.158 -            }
   2.159 -        }
   2.160 -    }
   2.161 -    
   2.162 -    static class NextMove extends TimerTask {
   2.163 -        private static final Timer T = new Timer("Animate moves");
   2.164 -        private final Board b;
   2.165 -        private final Move m;
   2.166 -
   2.167 -        public NextMove(Board b, Move m) {
   2.168 -            this.b = b;
   2.169 -            this.m = m;
   2.170 -            T.schedule(this, 1000);
   2.171 -        }
   2.172 -        
   2.173 -        
   2.174 -        @Override
   2.175 -        public void run() {
   2.176 -            b.showPosition(m);
   2.177 -        }
   2.178 -    }
   2.179 -    
   2.180 -    @ModelOperation @Function static void showPosition(Board b, Move data) {
   2.181 -        Rules.initBoard(b);
   2.182 -        boolean found = false;
   2.183 -        for (Move m : b.getMoves()) {
   2.184 -            if (found) {
   2.185 -                b.setTurn(null);
   2.186 -                new NextMove(b, m);
   2.187 -                return;
   2.188 -            }
   2.189 -            Square from = findSquare(b, (char)m.getFrom().getX(), m.getFrom().getY());
   2.190 -            Square to = findSquare(b, (char)m.getTo().getX(), m.getTo().getY());
   2.191 -            to.setPiece(from.getPiece());
   2.192 -            to.setPieceColor(from.getPieceColor());
   2.193 -            from.setPiece(null);
   2.194 -            from.setPieceColor(null);
   2.195 -            if (m == data) {
   2.196 -                found = true;
   2.197 -            }
   2.198 -        }
   2.199 -        b.setTurn(b.getMoves().size() % 2 == 0 ? Color.W : Color.B);
   2.200 -    }
   2.201 -    
   2.202 -    
   2.203 -
   2.204 -    @Function static void rotateBoard(Board b) {
   2.205 -        Collections.reverse(b.getRows());
   2.206 -        for (Row r : b.getRows()) {
   2.207 -            Collections.reverse(r.getColumns());
   2.208 -        }
   2.209 -        Square sq = findSelectedSquare(b);
   2.210 -        if (sq != null) {
   2.211 -            sq.setSelected(false);
   2.212 -            Rules.computeAccessible(b, null);
   2.213 -        }
   2.214 -    }
   2.215 -    
   2.216 -    @ComputedProperty static boolean whiteTurn(Color turn) {
   2.217 -        return turn == Color.W;
   2.218 -    }
   2.219 -
   2.220 -    @ComputedProperty static boolean blackTurn(Color turn) {
   2.221 -        return turn == Color.B;
   2.222 -    }
   2.223 -    
   2.224 -    @ComputedProperty static List<String> columnNames(List<Row> rows) {
   2.225 -        boolean whiteDown = rows.isEmpty() || rows.get(0).getY() == 8;
   2.226 -        String[] arr = new String[8];
   2.227 -        for (int i = 0; i < 8; i++) {
   2.228 -            String s;
   2.229 -            if (whiteDown) {
   2.230 -                s = "" + (char)('A' + i);
   2.231 -            } else {
   2.232 -                s = "" + (char)('H' - i);
   2.233 -            }
   2.234 -            arr[i] = s;
   2.235 -        }
   2.236 -        return Arrays.asList(arr);
   2.237 -    }
   2.238 -    
   2.239 -    static Square findSquare(Board b, char column, int row) {
   2.240 -        for (Row r : b.getRows()) {
   2.241 -            for (Square square : r.getColumns()) {
   2.242 -                if (square.getPosition().getX() == column && square.getPosition().getY() == row) {
   2.243 -                    return square;
   2.244 -                }
   2.245 -            }
   2.246 -        }
   2.247 -        return null;
   2.248 -    }
   2.249 -
   2.250 -    private static Square findSquare(Board b, Position to) {
   2.251 -        return findSquare(b, (char)to.getX(), to.getY());
   2.252 -    }
   2.253 -    
   2.254 -    static Square findSelectedSquare(Board b) {
   2.255 -        for (Row row : b.getRows()) {
   2.256 -            for (Square square : row.getColumns()) {
   2.257 -                if (square.isSelected()) {
   2.258 -                    return square;
   2.259 -                }
   2.260 -            }
   2.261 -        }
   2.262 -        return null;
   2.263 -    }
   2.264 -
   2.265 -    static void moveResponse(final Board b, final String errMsg, final List<String> whites, final List<String> blacks, final Color turn,
   2.266 -        Alert alert
   2.267 -    ) {
   2.268 -        if (errMsg != null) {
   2.269 -            b.getMoves().remove(b.getPendingMove());
   2.270 -            b.setPendingMove(null);
   2.271 -            b.setAlertMessage(errMsg);
   2.272 -        } else {
   2.273 -            b.setTurn(turn);
   2.274 -            b.setAlertMessage(null);
   2.275 -        }
   2.276 -        b.setAlert(alert);
   2.277 -        Rules.initBoard(b, whites, blacks, turn);
   2.278 -    }
   2.279 -
   2.280 -    static void moveUpdate(final Board b, final Move move, final List<String> whites, final List<String> blacks, final Color turn, Alert alert) {
   2.281 -        final Square from = BoardModel.findSquare(b, move.getFrom());
   2.282 -        final Square to = BoardModel.findSquare(b, move.getTo());
   2.283 -        move.setPiece(from.getPiece());
   2.284 -        move.setTurn(from.getPieceColor());
   2.285 -        if (to.getPiece() != null) {
   2.286 -            move.setTakes(true);
   2.287 -        }
   2.288 -        b.setAlert(alert);
   2.289 -        b.setAlertMessage(alert == null ? null : alert.getMessage());
   2.290 -        move.setRound(b.getMoves().size() / 2 + 1);
   2.291 -        b.getMoves().add(move);
   2.292 -        Rules.initBoard(b, whites, blacks, turn);
   2.293 -    }
   2.294 -
   2.295 -    @Model(className="Row", properties = {
   2.296 -        @Property(name = "columns", type = Square.class, array = true)
   2.297 -    })
   2.298 -    static class RowsImpl {
   2.299 -        @ComputedProperty static int y(List<Square> columns) {
   2.300 -            return columns.isEmpty() ? 0 : columns.get(0).getY();
   2.301 -        }
   2.302 -    }
   2.303 -    
   2.304 -    enum PieceType {
   2.305 -        PAWN(5), ROCK(2), KNIGHT(4), BISHOP(3), QUEEN(1), KING(0);
   2.306 -
   2.307 -        final int entityIndex;
   2.308 -        
   2.309 -        PieceType(int ei) {
   2.310 -            this.entityIndex = ei;
   2.311 -        }
   2.312 -
   2.313 -        static PieceType fromNotation(char notation) {
   2.314 -            switch (notation) {
   2.315 -                case 'R': return ROCK;
   2.316 -                case 'N': return KNIGHT;
   2.317 -                case 'B': return BISHOP;
   2.318 -                case 'Q': return QUEEN;
   2.319 -                case 'K': return KING;
   2.320 -                case 'P': return PAWN;
   2.321 -            }
   2.322 -            throw new IllegalStateException("Unexpected: " + notation);
   2.323 -        }
   2.324 -        
   2.325 -        String computeEntity(Color color) {
   2.326 -            if (color == null) {
   2.327 -                color = Color.W;
   2.328 -            }
   2.329 -            int base;
   2.330 -            switch (color) {
   2.331 -                case W: base = 12; break;
   2.332 -                case B: base = 18; break;
   2.333 -                default:
   2.334 -                    throw new AssertionError();
   2.335 -            }
   2.336 -            return "&#98" + String.valueOf(base + entityIndex) + ";";
   2.337 -        }
   2.338 -    }
   2.339 -    
   2.340 -    @Model(className="Position", properties = {
   2.341 -        @Property(name = "x", type = char.class),
   2.342 -        @Property(name = "y", type = int.class),
   2.343 -    })
   2.344 -    static class PositionImpl {
   2.345 -        @ComputedProperty static String location(int x, int y) {
   2.346 -            return "" + (char)(x - 'A' + 'a') + y;
   2.347 -        }
   2.348 -    }
   2.349 -    
   2.350 -    @Model(className="Square", properties = {
   2.351 -        @Property(name = "position", type = Position.class),
   2.352 -        @Property(name = "color", type = Color.class),
   2.353 -        @Property(name = "piece", type = PieceType.class),
   2.354 -        @Property(name = "pieceColor", type = Color.class),
   2.355 -        @Property(name = "selected", type = boolean.class),
   2.356 -        @Property(name = "accessible", type = boolean.class),
   2.357 -        @Property(name = "pending", type = boolean.class),
   2.358 -    })
   2.359 -    static class SquareModel {
   2.360 -        @ComputedProperty static String pieceEntity(
   2.361 -            PieceType piece, Color pieceColor
   2.362 -        ) {
   2.363 -            if (piece == null) {
   2.364 -                return "";
   2.365 -            }
   2.366 -            return piece.computeEntity(pieceColor);
   2.367 -        }
   2.368 -        
   2.369 -        @ComputedProperty static String squareColor(
   2.370 -            Color color, boolean selected, boolean accessible, boolean pending
   2.371 -        ) {
   2.372 -            if (selected) {
   2.373 -                return "selected";
   2.374 -            }
   2.375 -            if (accessible) {
   2.376 -                return "accessible";
   2.377 -            }
   2.378 -            if (pending) {
   2.379 -                return "pending";
   2.380 -            }
   2.381 -            
   2.382 -            if (color == null) {
   2.383 -                return "";
   2.384 -            } else {
   2.385 -                if (color == Color.W) {
   2.386 -                    return "white";
   2.387 -                } else {
   2.388 -                    return "black";
   2.389 -                }
   2.390 -            }
   2.391 -        }
   2.392 -        
   2.393 -        @ComputedProperty static char x(Position position) {
   2.394 -            return position == null ? 'A' : position.getX();
   2.395 -        }
   2.396 -
   2.397 -        @ComputedProperty static int y(Position position) {
   2.398 -            return position == null ? 1 : position.getY();
   2.399 -        }
   2.400 -    }
   2.401 -    
   2.402 -    @Model(className = "Move", properties = {
   2.403 -        @Property(name = "round", type = int.class),
   2.404 -        @Property(name = "turn", type = Color.class),
   2.405 -        @Property(name = "piece", type = PieceType.class),
   2.406 -        @Property(name = "from", type = Position.class),
   2.407 -        @Property(name = "to", type = Position.class),
   2.408 -        @Property(name = "promoted", type = PieceType.class),
   2.409 -        @Property(name = "takes", type = boolean.class),
   2.410 -        @Property(name = "check", type = boolean.class),
   2.411 -    })
   2.412 -    static class MoveImpl {
   2.413 -        @ComputedProperty static boolean whiteMove(Color turn) {
   2.414 -            return turn == Color.W;
   2.415 -        }
   2.416 -        
   2.417 -        @ComputedProperty static String html(
   2.418 -            Position from, Position to, boolean takes, PieceType piece, Color turn
   2.419 -        ) {
   2.420 -            if (from == null || to == null) {
   2.421 -                return "";
   2.422 -            }
   2.423 -            StringBuilder sb = new StringBuilder();
   2.424 -            if (piece != null && piece != PieceType.PAWN) {
   2.425 -                sb.append(piece.computeEntity(turn));
   2.426 -            }
   2.427 -            
   2.428 -            sb.append(from.getLocation());
   2.429 -            if (takes) {
   2.430 -                sb.append("x");
   2.431 -            }
   2.432 -            sb.append(to.getLocation());
   2.433 -            return sb.toString();
   2.434 -        }
   2.435 -
   2.436 -        static Move valueOf(String move) {
   2.437 -            move = move.toUpperCase();
   2.438 -            Move m = new Move();
   2.439 -            {
   2.440 -                Position p = new Position();
   2.441 -                p.setX(move.charAt(0));
   2.442 -                p.setY(move.charAt(1) - '0');
   2.443 -                m.setFrom(p);
   2.444 -            }
   2.445 -            {
   2.446 -                Position p = new Position();
   2.447 -                p.setX(move.charAt(2));
   2.448 -                p.setY(move.charAt(3) - '0');
   2.449 -                m.setTo(p);
   2.450 -            }
   2.451 -            return m;
   2.452 -        }
   2.453 -    }
   2.454 -}
     3.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Color.java	Tue Sep 24 22:28:31 2013 +0200
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,32 +0,0 @@
     3.4 -/**
     3.5 - * The MIT License (MIT)
     3.6 - *
     3.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.8 - *
     3.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    3.10 - * of this software and associated documentation files (the "Software"), to deal
    3.11 - * in the Software without restriction, including without limitation the rights
    3.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    3.13 - * copies of the Software, and to permit persons to whom the Software is
    3.14 - * furnished to do so, subject to the following conditions:
    3.15 - *
    3.16 - * The above copyright notice and this permission notice shall be included in
    3.17 - * all copies or substantial portions of the Software.
    3.18 - *
    3.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    3.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    3.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    3.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    3.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    3.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    3.25 - * THE SOFTWARE.
    3.26 - */
    3.27 -package com.oracle.chess.client.htmljava;
    3.28 -
    3.29 -/**
    3.30 - *
    3.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.32 - */
    3.33 -public enum Color {
    3.34 -    W, B;
    3.35 -}
     4.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Communication.java	Tue Sep 24 22:28:31 2013 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,110 +0,0 @@
     4.4 -/**
     4.5 - * The MIT License (MIT)
     4.6 - *
     4.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.8 - *
     4.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    4.10 - * of this software and associated documentation files (the "Software"), to deal
    4.11 - * in the Software without restriction, including without limitation the rights
    4.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    4.13 - * copies of the Software, and to permit persons to whom the Software is
    4.14 - * furnished to do so, subject to the following conditions:
    4.15 - *
    4.16 - * The above copyright notice and this permission notice shall be included in
    4.17 - * all copies or substantial portions of the Software.
    4.18 - *
    4.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    4.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    4.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    4.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    4.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    4.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    4.25 - * THE SOFTWARE.
    4.26 - */
    4.27 -package com.oracle.chess.client.htmljava;
    4.28 -
    4.29 -import net.java.html.json.ComputedProperty;
    4.30 -import net.java.html.json.Model;
    4.31 -import net.java.html.json.Property;
    4.32 -
    4.33 -
    4.34 -/** Communication protocols to talk to the server.
    4.35 - *
    4.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.37 - */
    4.38 -final class Communication {
    4.39 -    @Model(className = "Request", properties = {
    4.40 -        @Property(name = "msg", type = MsgType.class),
    4.41 -        @Property(name = "username", type = String.class),
    4.42 -        @Property(name = "password", type = String.class),
    4.43 -        @Property(name = "gameId", type = String.class),
    4.44 -        @Property(name = "color", type = Color.class),
    4.45 -        @Property(name = "from", type = String.class),
    4.46 -        @Property(name = "to", type = String.class),
    4.47 -        @Property(name = "observer", type = boolean.class),
    4.48 -    })
    4.49 -    static class RequestModel {
    4.50 -    }
    4.51 -
    4.52 -    @Model(className = "BoardRep", properties = {
    4.53 -        @Property(name = "whites", type = String.class, array = true),
    4.54 -        @Property(name = "blacks", type = String.class, array = true),
    4.55 -    })
    4.56 -    static class BoardRepModel {
    4.57 -    }
    4.58 -
    4.59 -    @Model(className = "Response", properties = {
    4.60 -        @Property(name = "msg", type = String.class),
    4.61 -        @Property(name = "games", array = true, type = Game.class),
    4.62 -        @Property(name = "board", type = BoardRep.class),
    4.63 -        @Property(name = "turn", type = Color.class),
    4.64 -        @Property(name = "color", type = Color.class),
    4.65 -        @Property(name = "gameId", type = String.class),
    4.66 -        @Property(name = "error", type = Err.class),
    4.67 -        @Property(name = "alert", type = Alert.class),
    4.68 -        @Property(name = "status", type = String.class),
    4.69 -        @Property(name = "summary", type = String.class),
    4.70 -        @Property(name = "moves", type = String.class, array = true),
    4.71 -        @Property(name = "from", type = String.class),
    4.72 -        @Property(name = "to", type = String.class),
    4.73 -        @Property(name = "check", type = CheckResult.class),
    4.74 -        @Property(name = "whitePlayer", type = String.class),
    4.75 -        @Property(name = "blackPlayer", type = String.class),
    4.76 -    })
    4.77 -    static class ResponseModel {
    4.78 -        @ComputedProperty static Color nextTurn(Color turn, Alert alert) {
    4.79 -            if (alert == null || !alert.getType().isTerminal()) {
    4.80 -                return turn;
    4.81 -            } else {
    4.82 -                return null;
    4.83 -            }
    4.84 -        }
    4.85 -    }
    4.86 -
    4.87 -    static enum CheckResult {
    4.88 -        VALID, INVALID, NOT_REGISTERED
    4.89 -    };
    4.90 -    
    4.91 -    @Model(className = "Err", properties = {
    4.92 -        @Property(name = "code", type = int.class),
    4.93 -        @Property(name = "message", type = String.class),
    4.94 -    })
    4.95 -    static class ErrorModel {
    4.96 -    }
    4.97 -
    4.98 -    @Model(className = "Alert", properties = {
    4.99 -        @Property(name = "type", type = AlertType.class),
   4.100 -        @Property(name = "message", type = String.class),
   4.101 -    })
   4.102 -    static class AlertModel {
   4.103 -    }
   4.104 -
   4.105 -    static enum AlertType {
   4.106 -        CHECKMATE, CHECK, DRAW;
   4.107 -
   4.108 -        public boolean isTerminal() {
   4.109 -            return this == CHECKMATE || this == DRAW;
   4.110 -        }
   4.111 -    };
   4.112 -    
   4.113 -}
     5.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/GamesModel.java	Tue Sep 24 22:28:31 2013 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,86 +0,0 @@
     5.4 -/**
     5.5 - * The MIT License (MIT)
     5.6 - *
     5.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.8 - *
     5.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    5.10 - * of this software and associated documentation files (the "Software"), to deal
    5.11 - * in the Software without restriction, including without limitation the rights
    5.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    5.13 - * copies of the Software, and to permit persons to whom the Software is
    5.14 - * furnished to do so, subject to the following conditions:
    5.15 - *
    5.16 - * The above copyright notice and this permission notice shall be included in
    5.17 - * all copies or substantial portions of the Software.
    5.18 - *
    5.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    5.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    5.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    5.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    5.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    5.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    5.25 - * THE SOFTWARE.
    5.26 - */
    5.27 -package com.oracle.chess.client.htmljava;
    5.28 -
    5.29 -import java.util.List;
    5.30 -import net.java.html.json.ComputedProperty;
    5.31 -import net.java.html.json.Model;
    5.32 -import net.java.html.json.ModelOperation;
    5.33 -import net.java.html.json.Property;
    5.34 -
    5.35 -/**
    5.36 - *
    5.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.38 - */
    5.39 -@Model(className = "Games", properties = {
    5.40 -    @Property(name = "own", array = true, type = Game.class),
    5.41 -    @Property(name = "other", array = true, type = Game.class),
    5.42 -    @Property(name = "selectedColor", type = String.class),
    5.43 -})
    5.44 -class GamesModel {
    5.45 -    @Model(className = "Game", properties = {
    5.46 -        @Property(name = "gameId", type=String.class),
    5.47 -        @Property(name = "summary", type=String.class),
    5.48 -        @Property(name = "open", type=boolean.class),
    5.49 -        @Property(name = "whitePlayer", type=String.class),
    5.50 -        @Property(name = "blackPlayer", type=String.class)
    5.51 -    })
    5.52 -    static class GameImpl {
    5.53 -        @ComputedProperty static String description(String gameId, String summary) {
    5.54 -            return summary != null ? summary : gameId;
    5.55 -        }
    5.56 -        
    5.57 -        @ComputedProperty static boolean pendingPlayer(String whitePlayer, String blackPlayer) {
    5.58 -            return whitePlayer == null || blackPlayer == null;
    5.59 -        }
    5.60 -    }
    5.61 -    
    5.62 -    
    5.63 -    @ComputedProperty static boolean anyOwnGame(List<Game> own) {
    5.64 -        return !own.isEmpty();
    5.65 -    }
    5.66 -
    5.67 -    @ComputedProperty static boolean anyOtherGame(List<Game> other) {
    5.68 -        return !other.isEmpty();
    5.69 -    }
    5.70 -    
    5.71 -    @ModelOperation static void listGames(Games g, List<Game> games, String username) {
    5.72 -        g.getOwn().clear();
    5.73 -        g.getOther().clear();
    5.74 -        int cnt = 0;
    5.75 -        final int maxGames = 30;
    5.76 -        for (Game game : games) {
    5.77 -            if (
    5.78 -                username.equals(game.getWhitePlayer()) || 
    5.79 -                username.equals(game.getBlackPlayer())
    5.80 -            ) {
    5.81 -                g.getOwn().add(game);
    5.82 -            } else {
    5.83 -                if (cnt++ < maxGames) {
    5.84 -                    g.getOther().add(game);
    5.85 -                }
    5.86 -            }
    5.87 -        }
    5.88 -    }
    5.89 -}
     6.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/LoadMain.java	Tue Sep 24 22:28:31 2013 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,41 +0,0 @@
     6.4 -/**
     6.5 - * The MIT License (MIT)
     6.6 - *
     6.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.8 - *
     6.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    6.10 - * of this software and associated documentation files (the "Software"), to deal
    6.11 - * in the Software without restriction, including without limitation the rights
    6.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    6.13 - * copies of the Software, and to permit persons to whom the Software is
    6.14 - * furnished to do so, subject to the following conditions:
    6.15 - *
    6.16 - * The above copyright notice and this permission notice shall be included in
    6.17 - * all copies or substantial portions of the Software.
    6.18 - *
    6.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    6.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    6.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    6.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    6.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    6.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    6.25 - * THE SOFTWARE.
    6.26 - */
    6.27 -package com.oracle.chess.client.htmljava;
    6.28 -
    6.29 -
    6.30 -public final class LoadMain {
    6.31 -    private LoadMain() {
    6.32 -    }
    6.33 -    
    6.34 -    /**
    6.35 -     * Called when the page is ready.
    6.36 -     */
    6.37 -    static {
    6.38 -        try {
    6.39 -            UIModel.initialize();
    6.40 -        } catch (Throwable ex) {
    6.41 -            ex.printStackTrace();
    6.42 -        }
    6.43 -    }
    6.44 -}
     7.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Main.java	Tue Sep 24 22:28:31 2013 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,42 +0,0 @@
     7.4 -/**
     7.5 - * The MIT License (MIT)
     7.6 - *
     7.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.8 - *
     7.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    7.10 - * of this software and associated documentation files (the "Software"), to deal
    7.11 - * in the Software without restriction, including without limitation the rights
    7.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    7.13 - * copies of the Software, and to permit persons to whom the Software is
    7.14 - * furnished to do so, subject to the following conditions:
    7.15 - *
    7.16 - * The above copyright notice and this permission notice shall be included in
    7.17 - * all copies or substantial portions of the Software.
    7.18 - *
    7.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    7.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    7.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    7.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    7.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    7.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    7.25 - * THE SOFTWARE.
    7.26 - */
    7.27 -package com.oracle.chess.client.htmljava;
    7.28 -
    7.29 -import net.java.html.boot.BrowserBuilder;
    7.30 -import org.apidesign.bck2brwsr.core.JavaScriptOnly;
    7.31 -
    7.32 -public final class Main {
    7.33 -    private Main() {
    7.34 -    }
    7.35 -
    7.36 -    @JavaScriptOnly(name = "main", value = "null")
    7.37 -    public static void main(String... args) throws Exception {
    7.38 -        BrowserBuilder.newBrowser().
    7.39 -            loadPage("pages/index.html").
    7.40 -            loadClass(UIModel.class).
    7.41 -            invoke("initialize", args).
    7.42 -            showAndWait();
    7.43 -        System.exit(0);
    7.44 -    }
    7.45 -}
     8.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/MsgType.java	Tue Sep 24 22:28:31 2013 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,40 +0,0 @@
     8.4 -/**
     8.5 - * The MIT License (MIT)
     8.6 - *
     8.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.8 - *
     8.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.10 - * of this software and associated documentation files (the "Software"), to deal
    8.11 - * in the Software without restriction, including without limitation the rights
    8.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    8.13 - * copies of the Software, and to permit persons to whom the Software is
    8.14 - * furnished to do so, subject to the following conditions:
    8.15 - *
    8.16 - * The above copyright notice and this permission notice shall be included in
    8.17 - * all copies or substantial portions of the Software.
    8.18 - *
    8.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    8.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    8.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    8.25 - * THE SOFTWARE.
    8.26 - */
    8.27 -package com.oracle.chess.client.htmljava;
    8.28 -
    8.29 -/**
    8.30 - *
    8.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.32 - */
    8.33 - enum MsgType {
    8.34 -    CreateGame, QueryGames, SendMove, JoinGame, UpdateGame, CheckCredentials;
    8.35 -
    8.36 -    static MsgType forResponse(String msg) {
    8.37 -        if (msg.endsWith("Rsp")) {
    8.38 -            msg = msg.substring(0, msg.length() - 3);
    8.39 -        }
    8.40 -        return MsgType.valueOf(msg);
    8.41 -    }
    8.42 -    
    8.43 -}
     9.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java	Tue Sep 24 22:28:31 2013 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,314 +0,0 @@
     9.4 -/**
     9.5 - * The MIT License (MIT)
     9.6 - *
     9.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.8 - *
     9.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    9.10 - * of this software and associated documentation files (the "Software"), to deal
    9.11 - * in the Software without restriction, including without limitation the rights
    9.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9.13 - * copies of the Software, and to permit persons to whom the Software is
    9.14 - * furnished to do so, subject to the following conditions:
    9.15 - *
    9.16 - * The above copyright notice and this permission notice shall be included in
    9.17 - * all copies or substantial portions of the Software.
    9.18 - *
    9.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    9.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    9.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    9.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    9.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    9.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    9.25 - * THE SOFTWARE.
    9.26 - */
    9.27 -package com.oracle.chess.client.htmljava;
    9.28 -
    9.29 -import java.util.ArrayList;
    9.30 -import java.util.List;
    9.31 -
    9.32 -/** Common chess rules.
    9.33 - *
    9.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.35 - */
    9.36 -class Rules {
    9.37 -    static void computeAccessible(Board b, Square s) {
    9.38 -        for (Row r : b.getRows()) {
    9.39 -            for (Square ts : r.getColumns()) {
    9.40 -                ts.setAccessible(false);
    9.41 -            }
    9.42 -        }
    9.43 -        if (s == null) {
    9.44 -            return;
    9.45 -        }
    9.46 -        
    9.47 -        switch (s.getPiece()) {
    9.48 -            case BISHOP: 
    9.49 -                moveBishop(b, s);
    9.50 -                break;
    9.51 -            case KING:
    9.52 -                computeAccessible(b, s, 1, 1, 1);
    9.53 -                computeAccessible(b, s, 1, -1, 1);
    9.54 -                computeAccessible(b, s, -1, -1, 1);
    9.55 -                computeAccessible(b, s, -1, 1, 1);
    9.56 -                computeAccessible(b, s, 1, 0, 1);
    9.57 -                computeAccessible(b, s, 0, -1, 1);
    9.58 -                computeAccessible(b, s, 0, 1, 1);
    9.59 -                computeAccessible(b, s, -1, 0, 1);
    9.60 -                checkRochade(b, s);
    9.61 -                break;
    9.62 -            case ROCK:
    9.63 -                moveRock(b, s);
    9.64 -                break;
    9.65 -            case QUEEN:
    9.66 -                moveRock(b, s);
    9.67 -                moveBishop(b, s);
    9.68 -                break;
    9.69 -            case KNIGHT:
    9.70 -                computeAccessible(b, s, 2, 1, 1);
    9.71 -                computeAccessible(b, s, 2, -1, 1);
    9.72 -                computeAccessible(b, s, -2, -1, 1);
    9.73 -                computeAccessible(b, s, -2, 1, 1);
    9.74 -                computeAccessible(b, s, 1, 2, 1);
    9.75 -                computeAccessible(b, s, -1, 2, 1);
    9.76 -                computeAccessible(b, s, -1, -2, 1);
    9.77 -                computeAccessible(b, s, 1, -2, 1);
    9.78 -                break;
    9.79 -            case PAWN:
    9.80 -                pawns(b, s);
    9.81 -                break;
    9.82 -        }
    9.83 -    }
    9.84 -
    9.85 -    private static void moveRock(Board b, Square s) {
    9.86 -        computeAccessible(b, s, 1, 0, 8);
    9.87 -        computeAccessible(b, s, 0, -1, 8);
    9.88 -        computeAccessible(b, s, -1, 0, 8);
    9.89 -        computeAccessible(b, s, 0, 1, 8);
    9.90 -    }
    9.91 -
    9.92 -    private static void moveBishop(Board b, Square s) {
    9.93 -        computeAccessible(b, s, 1, 1, 8);
    9.94 -        computeAccessible(b, s, 1, -1, 8);
    9.95 -        computeAccessible(b, s, -1, -1, 8);
    9.96 -        computeAccessible(b, s, -1, 1, 8);
    9.97 -    }
    9.98 -    
    9.99 -    private static void computeAccessible(
   9.100 -        Board b, Square s, int dx, int dy,
   9.101 -        int limit
   9.102 -    ) {
   9.103 -        int x = s.getX();
   9.104 -        int y = s.getY();
   9.105 -        
   9.106 -        while (limit-- > 0) {
   9.107 -            x += dx;
   9.108 -            y += dy;
   9.109 -            Square next = BoardModel.findSquare(b, (char)x, y);
   9.110 -            if (next == null) {
   9.111 -                break;
   9.112 -            }
   9.113 -            if (next.getPieceColor() == s.getPieceColor()) {
   9.114 -                break;
   9.115 -            }
   9.116 -            next.setAccessible(true);
   9.117 -            if (next.getPieceColor() != null) {
   9.118 -                break;
   9.119 -            }
   9.120 -        }
   9.121 -    }
   9.122 -    
   9.123 -    private static void pawns(Board b, Square s) {
   9.124 -        final boolean white = s.getPieceColor() == Color.W;
   9.125 -        int dy = white ? 1 : -1;
   9.126 -        Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
   9.127 -        if (step != null && step.getPiece() == null) {
   9.128 -            step.setAccessible(true);
   9.129 -            if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
   9.130 -                Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
   9.131 -                if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
   9.132 -                    nextSTep.setAccessible(true);
   9.133 -                }
   9.134 -            }
   9.135 -        }
   9.136 -        Color opposite = white ? Color.B : Color.W;
   9.137 -        Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
   9.138 -        if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
   9.139 -            takeLeft.setAccessible(true);
   9.140 -        }
   9.141 -        Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
   9.142 -        if (takeRight != null && takeRight.getPieceColor() == opposite) {
   9.143 -            takeRight.setAccessible(true);
   9.144 -        }
   9.145 -        if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
   9.146 -            int enPassantFrom = white ? 7 : 2;
   9.147 -            int enPassantTo = white ? 5 : 4;
   9.148 -            if (!b.getMoves().isEmpty()) {
   9.149 -                Move last = b.getMoves().get(b.getMoves().size() - 1);
   9.150 -                if (
   9.151 -                    last.getPiece() == BoardModel.PieceType.PAWN &&
   9.152 -                    last.getFrom().getY() == enPassantFrom &&
   9.153 -                    last.getTo().getY() == enPassantTo
   9.154 -                ) {
   9.155 -                    if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
   9.156 -                        takeLeft.setAccessible(true);
   9.157 -                    }
   9.158 -                    if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
   9.159 -                        takeRight.setAccessible(true);
   9.160 -                    }
   9.161 -                }
   9.162 -            }
   9.163 -        }
   9.164 -    }
   9.165 -
   9.166 -    static Board createBoard() {
   9.167 -        Board b = new Board();
   9.168 -        initBoardField(b);
   9.169 -        initBoard(b);
   9.170 -        return b;
   9.171 -    }
   9.172 -
   9.173 -    private static void initBoardField(Board b) {
   9.174 -        List<Row> addRows = new ArrayList<>(8);
   9.175 -        for (int i = 8; i > 0; i--) {
   9.176 -            Square[] arr = new Square[8];
   9.177 -            for (char j = 'A'; j <= 'H'; j++) {
   9.178 -                arr[j - 'A'] = new Square(
   9.179 -                    new Position(j, i),
   9.180 -                    (i + j) % 2 == 1 ? Color.W : Color.B,
   9.181 -                    null, null, // figure
   9.182 -                    false, false, false
   9.183 -                );
   9.184 -            }
   9.185 -            addRows.add(new Row(arr));
   9.186 -        }
   9.187 -        b.getRows().addAll(addRows);
   9.188 -    }
   9.189 -    
   9.190 -    static void initBoard(Board b) {
   9.191 -        initBoard(b, true);
   9.192 -    }
   9.193 -    private static void initBoard(Board b, boolean init) {
   9.194 -        if (init) {
   9.195 -            b.setTurn(Color.W);
   9.196 -        }
   9.197 -        if (b.getRows().isEmpty()) {
   9.198 -            for (int i = 8; i > 0; i--) {
   9.199 -                Row r = b.getRows().get(8 - i);
   9.200 -                for (char j = 'A'; j <= 'H'; j++) {
   9.201 -                    Square s = r.getColumns().get(j - 'A');
   9.202 -                    s.setAccessible(false);
   9.203 -                    s.setPending(false);
   9.204 -                    r.getColumns().set(j - 'A', s);
   9.205 -                    initialPosition(s, init);
   9.206 -                }
   9.207 -            }
   9.208 -        } else {
   9.209 -            for (Row r : b.getRows()) {
   9.210 -                for (Square square : r.getColumns()) {
   9.211 -                    square.setAccessible(false);
   9.212 -                    square.setPending(false);
   9.213 -                    square.setPiece(null);
   9.214 -                    square.setPieceColor(null);
   9.215 -                    square.setSelected(false);
   9.216 -                    initialPosition(square, init);
   9.217 -                }
   9.218 -            }
   9.219 -        }
   9.220 -        b.setPendingMove(null);
   9.221 -    }
   9.222 -
   9.223 -    private static void initialPosition(Square s, boolean init) {
   9.224 -        int row = s.getPosition().getY();
   9.225 -        char column = s.getPosition().getX();
   9.226 -        s.setPiece(null);
   9.227 -        s.setPieceColor(null);
   9.228 -        if (init) {
   9.229 -            if (row == 2) {
   9.230 -                s.setPiece(BoardModel.PieceType.PAWN);
   9.231 -                s.setPieceColor(Color.W);
   9.232 -            } else if (row == 7) {
   9.233 -                s.setPiece(BoardModel.PieceType.PAWN);
   9.234 -                s.setPieceColor(Color.B);
   9.235 -            } else if (row == 8 || row == 1) {
   9.236 -                s.setPieceColor(row == 1 ? Color.W : Color.B);
   9.237 -                BoardModel.PieceType t;
   9.238 -                switch (column) {
   9.239 -                    case 'A':
   9.240 -                    case 'H':
   9.241 -                        t = BoardModel.PieceType.ROCK;
   9.242 -                        break;
   9.243 -                    case 'B':
   9.244 -                    case 'G':
   9.245 -                        t = BoardModel.PieceType.KNIGHT;
   9.246 -                        break;
   9.247 -                    case 'C':
   9.248 -                    case 'F':
   9.249 -                        t = BoardModel.PieceType.BISHOP;
   9.250 -                        break;
   9.251 -                    case 'D':
   9.252 -                        t = BoardModel.PieceType.QUEEN;
   9.253 -                        break;
   9.254 -                    default:
   9.255 -                        t = BoardModel.PieceType.KING;
   9.256 -                        break;
   9.257 -                }
   9.258 -                s.setPiece(t);
   9.259 -            }
   9.260 -        }
   9.261 -    }
   9.262 -
   9.263 -    static void initBoard(
   9.264 -        Board board, List<String> whites, List<String> blacks, Color turn
   9.265 -    ) {
   9.266 -        initBoard(board, false);
   9.267 -        for (String w : whites) {
   9.268 -            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   9.269 -            w = w.toUpperCase();
   9.270 -            char column = w.charAt(1);
   9.271 -            int row = (w.charAt(2) - '0');
   9.272 -            
   9.273 -            Square s = BoardModel.findSquare(board, column, row);
   9.274 -            s.setPieceColor(Color.W);
   9.275 -            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   9.276 -        }
   9.277 -        for (String w : blacks) {
   9.278 -            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
   9.279 -            w = w.toUpperCase();
   9.280 -            char column = w.charAt(1);
   9.281 -            int row = (w.charAt(2) - '0');
   9.282 -            
   9.283 -            Square s = BoardModel.findSquare(board, column, row);
   9.284 -            s.setPieceColor(Color.B);
   9.285 -            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
   9.286 -        }
   9.287 -        board.setTurn(turn);
   9.288 -    }
   9.289 -
   9.290 -    private static void checkRochade(Board b, Square s) {
   9.291 -        if (s.getPosition().getX() == 'E') {
   9.292 -            int y = s.getPosition().getY();
   9.293 -            final Square gRow = BoardModel.findSquare(b, 'G', y);
   9.294 -            if (
   9.295 -                BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK 
   9.296 -                &&
   9.297 -                BoardModel.findSquare(b, 'F', y).getPiece() == null
   9.298 -                &&
   9.299 -                gRow.getPiece() == null
   9.300 -            ) {
   9.301 -                gRow.setAccessible(true);
   9.302 -            }
   9.303 -            final Square cRow = BoardModel.findSquare(b, 'C', y);
   9.304 -            if (
   9.305 -                BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK 
   9.306 -                &&
   9.307 -                BoardModel.findSquare(b, 'B', y).getPiece() == null
   9.308 -                &&
   9.309 -                BoardModel.findSquare(b, 'D', y).getPiece() == null
   9.310 -                &&
   9.311 -                cRow.getPiece() == null
   9.312 -            ) {
   9.313 -                cRow.setAccessible(true);
   9.314 -            }
   9.315 -        }
   9.316 -    }
   9.317 -}
    10.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/SettingsModel.java	Tue Sep 24 22:28:31 2013 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,82 +0,0 @@
    10.4 -/**
    10.5 - * The MIT License (MIT)
    10.6 - *
    10.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.8 - *
    10.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
   10.10 - * of this software and associated documentation files (the "Software"), to deal
   10.11 - * in the Software without restriction, including without limitation the rights
   10.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10.13 - * copies of the Software, and to permit persons to whom the Software is
   10.14 - * furnished to do so, subject to the following conditions:
   10.15 - *
   10.16 - * The above copyright notice and this permission notice shall be included in
   10.17 - * all copies or substantial portions of the Software.
   10.18 - *
   10.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   10.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   10.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   10.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   10.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   10.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   10.25 - * THE SOFTWARE.
   10.26 - */
   10.27 -package com.oracle.chess.client.htmljava;
   10.28 -
   10.29 -import java.io.File;
   10.30 -import java.io.FileInputStream;
   10.31 -import java.io.FileOutputStream;
   10.32 -import java.io.IOException;
   10.33 -import java.util.Properties;
   10.34 -import net.java.html.json.ComputedProperty;
   10.35 -import net.java.html.json.Model;
   10.36 -import net.java.html.json.ModelOperation;
   10.37 -import net.java.html.json.Property;
   10.38 -
   10.39 -/**
   10.40 - *
   10.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.42 - */
   10.43 -@Model(className = "Settings", properties = {
   10.44 -    @Property(name = "username", type = String.class),
   10.45 -    @Property(name = "password", type = String.class),
   10.46 -    @Property(name = "url", type = String.class),
   10.47 -})
   10.48 -class SettingsModel {
   10.49 -    private static final String SETTINGS = ".j1chess/html.properties";
   10.50 -    private static final String DEFAULT_URL = "ws://localhost:8080/chess/chessserver";
   10.51 -    
   10.52 -    @ComputedProperty static boolean validCredentials(String username, String password) {
   10.53 -        return username != null && password != null && !username.isEmpty() && !password.isEmpty();
   10.54 -    }
   10.55 -    
   10.56 -    @ModelOperation static void read(Settings s) {
   10.57 -        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   10.58 -        try (FileInputStream is = new FileInputStream(prefs)) {
   10.59 -            Properties p = new Properties();
   10.60 -            p.load(is);
   10.61 -            
   10.62 -            s.setUsername(p.getProperty("username", ""));
   10.63 -            s.setPassword(p.getProperty("password", ""));
   10.64 -            s.setUrl(p.getProperty("url", DEFAULT_URL));
   10.65 -        } catch (Throwable ex) {
   10.66 -            s.setUsername("");
   10.67 -            s.setPassword("");
   10.68 -            s.setUrl(DEFAULT_URL);
   10.69 -        }
   10.70 -    }
   10.71 -    
   10.72 -    @ModelOperation static void write(Settings s, UI ui) {
   10.73 -        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   10.74 -        prefs.getParentFile().mkdirs();
   10.75 -        try (FileOutputStream os = new FileOutputStream(prefs)) {
   10.76 -            Properties p = new Properties();
   10.77 -            p.setProperty("username", s.getUsername());
   10.78 -            p.setProperty("password", s.getPassword());
   10.79 -            p.setProperty("url", s.getUrl());
   10.80 -            p.store(os, "Java One Chess Preferences for HTML/Java Client");
   10.81 -        } catch (Throwable ex) {
   10.82 -            ui.setStatus("Cannot save preferences: " + ex.getMessage());
   10.83 -        }
   10.84 -    }
   10.85 -}
    11.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java	Tue Sep 24 22:28:31 2013 +0200
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,315 +0,0 @@
    11.4 -/**
    11.5 - * The MIT License (MIT)
    11.6 - *
    11.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    11.8 - *
    11.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
   11.10 - * of this software and associated documentation files (the "Software"), to deal
   11.11 - * in the Software without restriction, including without limitation the rights
   11.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   11.13 - * copies of the Software, and to permit persons to whom the Software is
   11.14 - * furnished to do so, subject to the following conditions:
   11.15 - *
   11.16 - * The above copyright notice and this permission notice shall be included in
   11.17 - * all copies or substantial portions of the Software.
   11.18 - *
   11.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   11.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   11.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   11.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   11.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   11.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   11.25 - * THE SOFTWARE.
   11.26 - */
   11.27 -package com.oracle.chess.client.htmljava;
   11.28 -
   11.29 -import java.io.IOException;
   11.30 -import java.net.URISyntaxException;
   11.31 -import java.util.HashSet;
   11.32 -import java.util.List;
   11.33 -import java.util.Set;
   11.34 -import java.util.logging.Level;
   11.35 -import java.util.logging.Logger;
   11.36 -import net.java.html.json.ComputedProperty;
   11.37 -import net.java.html.json.Function;
   11.38 -import net.java.html.json.Model;
   11.39 -import net.java.html.json.ModelOperation;
   11.40 -import net.java.html.json.OnPropertyChange;
   11.41 -import net.java.html.json.OnReceive;
   11.42 -import net.java.html.json.Property;
   11.43 -
   11.44 -/**
   11.45 - *
   11.46 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.47 - */
   11.48 -@Model(className = "UI", properties = {
   11.49 -    @Property(name = "status", type = String.class),
   11.50 -    @Property(name = "selectedGameId", type = String.class),
   11.51 -    @Property(name = "boards", type = Board.class, array = true),
   11.52 -    @Property(name = "viewGames", type = Games.class),
   11.53 -    @Property(name = "settings", type = Settings.class),
   11.54 -    @Property(name = "connected", type = boolean.class),
   11.55 -    @Property(name = "disconnected", type = boolean.class),
   11.56 -})
   11.57 -public class UIModel {
   11.58 -    private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
   11.59 -    
   11.60 -    @ComputedProperty static boolean settingsActive(String selectedGameId) {
   11.61 -        return selectedGameId == null;
   11.62 -    }
   11.63 -    
   11.64 -    @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
   11.65 -        return selectedGameId == null && connected;
   11.66 -    }
   11.67 -    
   11.68 -    @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
   11.69 -        Board active = null;
   11.70 -        for (Board b : boards) {
   11.71 -            b.setActive(false);
   11.72 -            if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
   11.73 -                b.setActive(true);
   11.74 -                active = b;
   11.75 -            }
   11.76 -        }
   11.77 -        return active;
   11.78 -    }
   11.79 -    
   11.80 -    @Function static void activateGame(UI m, Board data) {
   11.81 -        m.setSelectedGameId(data.getGameId());
   11.82 -    }
   11.83 -
   11.84 -    @Function static void activateSettings(UI m) {
   11.85 -        m.setSelectedGameId(null);
   11.86 -        refreshGames(m);
   11.87 -    }
   11.88 -    
   11.89 -    @Function static void createGame(UI u) {
   11.90 -        u.setStatus("Creating new game...");
   11.91 -        Request r = new Request();
   11.92 -        r.setMsg(MsgType.CreateGame);
   11.93 -        r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
   11.94 -        u.sendMsg(r);
   11.95 -    }
   11.96 -
   11.97 -    @ModelOperation @Function static void refreshGames(UI u) {
   11.98 -        u.setStatus("Refreshing games...");
   11.99 -        Request r = new Request();
  11.100 -        r.setMsg(MsgType.QueryGames);
  11.101 -        u.sendMsg(r);
  11.102 -    }
  11.103 -    
  11.104 -    @ModelOperation static void sendMsg(UI ui, Request r) {
  11.105 -        final Settings sttngs = ui.getSettings();
  11.106 -        
  11.107 -        String url = sttngs.getUrl();
  11.108 -        r.setUsername(sttngs.getUsername());
  11.109 -        r.setPassword(sttngs.getPassword());
  11.110 -        
  11.111 -        LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
  11.112 -        ui.queryServer(url, r);
  11.113 -    }
  11.114 -    
  11.115 -    
  11.116 -    @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError") 
  11.117 -    static void queryServer(UI ui, Response r) {
  11.118 -        LOG.log(Level.INFO, "Received {0}", r);
  11.119 -        if (r == null) {
  11.120 -            ui.setDisconnected(false);
  11.121 -            verifyLogin(ui);
  11.122 -            return;
  11.123 -        }
  11.124 -        SWITCH: switch (MsgType.forResponse(r.getMsg())) {
  11.125 -            case CheckCredentials: {
  11.126 -                switch (r.getCheck()) {
  11.127 -                    case NOT_REGISTERED:
  11.128 -                    case VALID:
  11.129 -                        ui.setConnected(true);
  11.130 -                        ui.refreshGames();
  11.131 -                        ui.setStatus("Connected.");
  11.132 -                        return;
  11.133 -                    case INVALID:
  11.134 -                        ui.setStatus("Password is invalid");
  11.135 -                        break;
  11.136 -                }
  11.137 -                disconnect(ui);
  11.138 -            }
  11.139 -                
  11.140 -            case QueryGames:
  11.141 -                ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
  11.142 -                ui.setStatus("");
  11.143 -                break;
  11.144 -            case CreateGame: {
  11.145 -                ui.setStatus("Game " + r + " created");
  11.146 -                final Board b = Rules.createBoard();
  11.147 -                Rules.initBoard(
  11.148 -                    b, r.getBoard().getWhites(),
  11.149 -                    r.getBoard().getBlacks(),
  11.150 -                    r.getTurn()
  11.151 -                );
  11.152 -                b.setGameId(r.getGameId());
  11.153 -                b.setWhitePlayer(r.getWhitePlayer());
  11.154 -                b.setBlackPlayer(r.getBlackPlayer());
  11.155 -                b.setPlayer(ui.getSettings().getUsername());
  11.156 -                b.updateSummary(r.getSummary());
  11.157 -                ui.getBoards().add(b);
  11.158 -                ui.setSelectedGameId(r.getGameId());
  11.159 -                UIModel.refreshGames(ui);
  11.160 -                break;
  11.161 -            }
  11.162 -            case SendMove: {
  11.163 -                if (r.getBoard() == null) {
  11.164 -                    throw new NullPointerException("No board in " + r);
  11.165 -                }
  11.166 -                final Board b = findBoard(ui, r.getGameId());
  11.167 -                if (b == null) {
  11.168 -                    break;
  11.169 -                }
  11.170 -                b.updateSummary(r.getSummary());
  11.171 -                final String errMsg = r.getError() == null ? null : r.getError().getMessage();
  11.172 -                final List<String> whites = r.getBoard().getWhites();
  11.173 -                final List<String> blacks = r.getBoard().getBlacks();
  11.174 -                final Color turn = r.getNextTurn();
  11.175 -                BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
  11.176 -                break;
  11.177 -            }
  11.178 -            case JoinGame: {
  11.179 -                Board b;
  11.180 -                if ((b = findBoard(ui, r.getGameId())) != null) {
  11.181 -                    b.setWhitePlayer(r.getWhitePlayer());
  11.182 -                    b.setBlackPlayer(r.getBlackPlayer());
  11.183 -                    b.setPlayer(ui.getSettings().getUsername());
  11.184 -                    b.updateSummary(r.getSummary());
  11.185 -                    ui.setSelectedGameId(r.getGameId());
  11.186 -                    break SWITCH;
  11.187 -                }
  11.188 -                ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
  11.189 -                b = Rules.createBoard();
  11.190 -                Rules.initBoard(
  11.191 -                    b, r.getBoard().getWhites(),
  11.192 -                    r.getBoard().getBlacks(),
  11.193 -                    r.getTurn()
  11.194 -                );
  11.195 -                b.setGameId(r.getGameId());
  11.196 -                b.setWhitePlayer(r.getWhitePlayer());
  11.197 -                b.setBlackPlayer(r.getBlackPlayer());
  11.198 -                b.setPlayer(ui.getSettings().getUsername());
  11.199 -                b.updateSummary(r.getSummary());
  11.200 -                if (r.getColor() == Color.B) {
  11.201 -                    BoardModel.rotateBoard(b);
  11.202 -                }
  11.203 -                if (r.getMoves() != null) {
  11.204 -                    for (String move : r.getMoves()) {
  11.205 -                        Move m = BoardModel.MoveImpl.valueOf(move);
  11.206 -                        b.getMoves().add(m);
  11.207 -                    }
  11.208 -                } else {
  11.209 -                    b.getMoves().clear();
  11.210 -                }
  11.211 -                ui.setSelectedGameId(b.getGameId());
  11.212 -                ui.getBoards().add(b);
  11.213 -                break;
  11.214 -            }
  11.215 -            case UpdateGame: {
  11.216 -                final Board b = findBoard(ui, r.getGameId());
  11.217 -                if (b == null) {
  11.218 -                    break;
  11.219 -                }
  11.220 -                b.updateSummary(r.getSummary());
  11.221 -                final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
  11.222 -                final List<String> whites = r.getBoard().getWhites();
  11.223 -                final List<String> blacks = r.getBoard().getBlacks();
  11.224 -                final Color turn = r.getNextTurn();
  11.225 -                BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
  11.226 -            }
  11.227 -        }
  11.228 -    }
  11.229 -
  11.230 -
  11.231 -    private static Board findBoard(UI ui, String gameId) {
  11.232 -        for (Board tmp : ui.getBoards()) {
  11.233 -            if (tmp.getGameId().equals(gameId)) {
  11.234 -                return tmp;
  11.235 -            }
  11.236 -        }
  11.237 -        return null;
  11.238 -    }
  11.239 -    
  11.240 -    
  11.241 -    static void wasAnError(UI ui, Exception t) {
  11.242 -        if (t == null) {
  11.243 -            ui.setConnected(false);
  11.244 -            ui.setDisconnected(true);
  11.245 -            ui.setStatus("Disconnected.");
  11.246 -        } else {
  11.247 -            ui.setStatus("Error: " + t.getLocalizedMessage());
  11.248 -        }
  11.249 -    }
  11.250 -    
  11.251 -    @Function static void joinGame(UI u, Game data) {
  11.252 -        Request r = new Request();
  11.253 -        r.setMsg(MsgType.JoinGame);
  11.254 -        r.setObserver(false);
  11.255 -        r.setGameId(data.getGameId());
  11.256 -        u.sendMsg(r);
  11.257 -    }
  11.258 -
  11.259 -    @Function static void observeGame(UI u, Game data) {
  11.260 -        Request r = new Request();
  11.261 -        r.setMsg(MsgType.JoinGame);
  11.262 -        r.setObserver(true);
  11.263 -        r.setGameId(data.getGameId());
  11.264 -        u.sendMsg(r);
  11.265 -    }
  11.266 -
  11.267 -    private static final Set<UI> ACTIVE = new HashSet<>();
  11.268 -    @OnPropertyChange("connected") static void clearGames(UI m) {
  11.269 -        if (m.isDisconnected()) {
  11.270 -            m.getBoards().clear();
  11.271 -            ACTIVE.remove(m);
  11.272 -        } else {
  11.273 -            ACTIVE.add(m);
  11.274 -        }
  11.275 -    }
  11.276 -    
  11.277 -    static UI findUI(Board b) {
  11.278 -        for (UI ui : ACTIVE) {
  11.279 -            if (ui.getBoards().contains(b)) {
  11.280 -                return ui;
  11.281 -            }
  11.282 -        }
  11.283 -        return null;
  11.284 -    }
  11.285 -    
  11.286 -    @Function static void leave(UI ui, Board data) {
  11.287 -        ui.getBoards().remove(data);
  11.288 -        ui.setSelectedGameId(null);
  11.289 -    }
  11.290 -    
  11.291 -    @Function static void disconnect(UI ui) {
  11.292 -        ui.queryServer(ui.getSettings().getUrl(), null);
  11.293 -        ui.setStatus("Disconnecting...");
  11.294 -    }
  11.295 -
  11.296 -    private static void verifyLogin(UI ui) {
  11.297 -        ui.setStatus("Verifying user credentials...");
  11.298 -        Request r = new Request();
  11.299 -        r.setMsg(MsgType.CheckCredentials);
  11.300 -        ui.sendMsg(r);
  11.301 -    }
  11.302 -    
  11.303 -    @Function static void reconnect(UI ui) {
  11.304 -        final Settings s = ui.getSettings();
  11.305 -        ui.setStatus("Connecting to the server...");
  11.306 -        ui.queryServer(s.getUrl(), null);
  11.307 -        s.write(ui);
  11.308 -    }
  11.309 -    
  11.310 -    public static void initialize(String... args) throws URISyntaxException, IOException {
  11.311 -        UI ui = new UI();
  11.312 -        ui.getSettings().read();
  11.313 -        ui.setStatus("Ready.");
  11.314 -        ui.setDisconnected(true);
  11.315 -        ui.applyBindings();
  11.316 -    }
  11.317 -
  11.318 -}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java	Tue Sep 24 22:37:17 2013 +0200
    12.3 @@ -0,0 +1,451 @@
    12.4 +/**
    12.5 + * The MIT License (MIT)
    12.6 + *
    12.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    12.8 + *
    12.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   12.10 + * of this software and associated documentation files (the "Software"), to deal
   12.11 + * in the Software without restriction, including without limitation the rights
   12.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   12.13 + * copies of the Software, and to permit persons to whom the Software is
   12.14 + * furnished to do so, subject to the following conditions:
   12.15 + *
   12.16 + * The above copyright notice and this permission notice shall be included in
   12.17 + * all copies or substantial portions of the Software.
   12.18 + *
   12.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   12.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   12.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   12.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   12.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   12.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   12.25 + * THE SOFTWARE.
   12.26 + */
   12.27 +package org.apidesign.html.demo.chess;
   12.28 +
   12.29 +import java.util.Arrays;
   12.30 +import java.util.Collections;
   12.31 +import java.util.List;
   12.32 +import java.util.Timer;
   12.33 +import java.util.TimerTask;
   12.34 +import net.java.html.json.ComputedProperty;
   12.35 +import net.java.html.json.Function;
   12.36 +import net.java.html.json.Model;
   12.37 +import net.java.html.json.ModelOperation;
   12.38 +import net.java.html.json.OnPropertyChange;
   12.39 +import net.java.html.json.Property;
   12.40 +import net.java.html.sound.AudioClip;
   12.41 +import org.apidesign.html.demo.chess.Communication.AlertType;
   12.42 +
   12.43 +@Model(className="Board", properties={
   12.44 +    @Property(name = "player", type = String.class),
   12.45 +    @Property(name = "gameId", type = String.class),
   12.46 +    @Property(name = "whitePlayer", type = String.class),
   12.47 +    @Property(name = "blackPlayer", type = String.class),
   12.48 +    @Property(name = "alert", type = Alert.class),
   12.49 +    @Property(name = "alertMessage", type = String.class),
   12.50 +    @Property(name = "status", type = String.class),
   12.51 +    @Property(name = "rows", type = Row.class, array = true),
   12.52 +    @Property(name = "turn", type = Color.class),
   12.53 +    @Property(name = "moves", type = Move.class, array = true),
   12.54 +    @Property(name = "pendingMove", type = Move.class),
   12.55 +    @Property(name = "active", type = boolean.class),
   12.56 +})
   12.57 +public class BoardModel {
   12.58 +    @ComputedProperty static String title(String status, String gameId) {
   12.59 +        String t = status != null ? status : gameId;
   12.60 +        if (t != null && t.length() > 10) {
   12.61 +            return t.substring(0, 10);
   12.62 +        }
   12.63 +        return t;
   12.64 +    }
   12.65 +
   12.66 +    @ModelOperation static void updateSummary(Board b, String summary) {
   12.67 +        if (summary != null) {
   12.68 +            b.setStatus(summary);
   12.69 +        }
   12.70 +    }
   12.71 +    
   12.72 +    @ComputedProperty static boolean myTurn(String player, String whitePlayer, String blackPlayer, Color turn) {
   12.73 +        if (turn != null && player != null) switch (turn) {
   12.74 +            case B: return player.equals(blackPlayer);
   12.75 +            case W: return player.equals(whitePlayer);
   12.76 +        }
   12.77 +        return false;
   12.78 +    }
   12.79 +    
   12.80 +    @ComputedProperty static boolean justObserving(String player) {
   12.81 +        return player == null;
   12.82 +    }
   12.83 +    
   12.84 +    private static final AudioClip MOVE = AudioClip.create("sounds/move.mp3");
   12.85 +    @OnPropertyChange("moves") static void playMove() {
   12.86 +        MOVE.play();
   12.87 +    }
   12.88 +
   12.89 +    private static final AudioClip CHECK = AudioClip.create("sounds/check.mp3");
   12.90 +    private static final AudioClip CHECKMATE = AudioClip.create("sounds/checkmate.mp3");
   12.91 +    @OnPropertyChange("alert") static void warnCheckAndMate(Board b) {
   12.92 +        if (b.getAlert() == null) {
   12.93 +            return;
   12.94 +        }
   12.95 +        if (b.getAlert().getType() == AlertType.CHECK) {
   12.96 +            CHECK.play();
   12.97 +        }
   12.98 +        if (b.getAlert().getType() == AlertType.CHECKMATE) {
   12.99 +            CHECKMATE.play();
  12.100 +        }
  12.101 +    }
  12.102 +    
  12.103 +    @Function static void selected(Board b, Square data) {
  12.104 +        if (!b.isMyTurn()) {
  12.105 +            b.setAlertMessage("Not your turn!");
  12.106 +            return;
  12.107 +        }
  12.108 +        
  12.109 +        Square previoslySelected = findSelectedSquare(b);
  12.110 +        if (previoslySelected == null) {
  12.111 +            if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
  12.112 +                data.setSelected(true);
  12.113 +                Rules.computeAccessible(b, data);
  12.114 +            }
  12.115 +        } else {
  12.116 +            if (previoslySelected == data) {
  12.117 +                data.setSelected(false);
  12.118 +                Rules.computeAccessible(b, null);
  12.119 +                return;
  12.120 +            }
  12.121 +            if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
  12.122 +                previoslySelected.setSelected(false);
  12.123 +                data.setSelected(true);
  12.124 +                Rules.computeAccessible(b, data);
  12.125 +                return;
  12.126 +            }
  12.127 +            if (data.isAccessible()) {
  12.128 +                previoslySelected.setSelected(false);
  12.129 +
  12.130 +                Move newMove = new Move();
  12.131 +                newMove.setFrom(previoslySelected.getPosition());
  12.132 +                newMove.setTo(data.getPosition());
  12.133 +                newMove.setRound(b.getMoves().size() / 2 + 1);
  12.134 +                newMove.setPiece(previoslySelected.getPiece());
  12.135 +                newMove.setTurn(previoslySelected.getPieceColor());
  12.136 +                newMove.setTakes(data.getPiece() != null);
  12.137 +                b.getMoves().add(newMove);
  12.138 +                b.setPendingMove(newMove);
  12.139 +
  12.140 +                data.setPending(true);
  12.141 +                data.setPieceColor(previoslySelected.getPieceColor());
  12.142 +                data.setPiece(previoslySelected.getPiece());
  12.143 +                b.setTurn(null);
  12.144 +                previoslySelected.setPiece(null);
  12.145 +                previoslySelected.setPieceColor(null);
  12.146 +                Rules.computeAccessible(b, null);
  12.147 +
  12.148 +                Request sm = new Request();
  12.149 +                sm.setMsg(MsgType.SendMove);
  12.150 +                sm.setGameId(b.getGameId());
  12.151 +                sm.setFrom(newMove.getFrom().getLocation());
  12.152 +                sm.setTo(newMove.getTo().getLocation());
  12.153 +                sm.setColor(newMove.getTurn());
  12.154 +                final UI ui = UIModel.findUI(b);
  12.155 +                if (ui != null) {
  12.156 +                    ui.sendMsg(sm);
  12.157 +                }
  12.158 +            }
  12.159 +        }
  12.160 +    }
  12.161 +    
  12.162 +    static class NextMove extends TimerTask {
  12.163 +        private static final Timer T = new Timer("Animate moves");
  12.164 +        private final Board b;
  12.165 +        private final Move m;
  12.166 +
  12.167 +        public NextMove(Board b, Move m) {
  12.168 +            this.b = b;
  12.169 +            this.m = m;
  12.170 +            T.schedule(this, 1000);
  12.171 +        }
  12.172 +        
  12.173 +        
  12.174 +        @Override
  12.175 +        public void run() {
  12.176 +            b.showPosition(m);
  12.177 +        }
  12.178 +    }
  12.179 +    
  12.180 +    @ModelOperation @Function static void showPosition(Board b, Move data) {
  12.181 +        Rules.initBoard(b);
  12.182 +        boolean found = false;
  12.183 +        for (Move m : b.getMoves()) {
  12.184 +            if (found) {
  12.185 +                b.setTurn(null);
  12.186 +                new NextMove(b, m);
  12.187 +                return;
  12.188 +            }
  12.189 +            Square from = findSquare(b, (char)m.getFrom().getX(), m.getFrom().getY());
  12.190 +            Square to = findSquare(b, (char)m.getTo().getX(), m.getTo().getY());
  12.191 +            to.setPiece(from.getPiece());
  12.192 +            to.setPieceColor(from.getPieceColor());
  12.193 +            from.setPiece(null);
  12.194 +            from.setPieceColor(null);
  12.195 +            if (m == data) {
  12.196 +                found = true;
  12.197 +            }
  12.198 +        }
  12.199 +        b.setTurn(b.getMoves().size() % 2 == 0 ? Color.W : Color.B);
  12.200 +    }
  12.201 +    
  12.202 +    
  12.203 +
  12.204 +    @Function static void rotateBoard(Board b) {
  12.205 +        Collections.reverse(b.getRows());
  12.206 +        for (Row r : b.getRows()) {
  12.207 +            Collections.reverse(r.getColumns());
  12.208 +        }
  12.209 +        Square sq = findSelectedSquare(b);
  12.210 +        if (sq != null) {
  12.211 +            sq.setSelected(false);
  12.212 +            Rules.computeAccessible(b, null);
  12.213 +        }
  12.214 +    }
  12.215 +    
  12.216 +    @ComputedProperty static boolean whiteTurn(Color turn) {
  12.217 +        return turn == Color.W;
  12.218 +    }
  12.219 +
  12.220 +    @ComputedProperty static boolean blackTurn(Color turn) {
  12.221 +        return turn == Color.B;
  12.222 +    }
  12.223 +    
  12.224 +    @ComputedProperty static List<String> columnNames(List<Row> rows) {
  12.225 +        boolean whiteDown = rows.isEmpty() || rows.get(0).getY() == 8;
  12.226 +        String[] arr = new String[8];
  12.227 +        for (int i = 0; i < 8; i++) {
  12.228 +            String s;
  12.229 +            if (whiteDown) {
  12.230 +                s = "" + (char)('A' + i);
  12.231 +            } else {
  12.232 +                s = "" + (char)('H' - i);
  12.233 +            }
  12.234 +            arr[i] = s;
  12.235 +        }
  12.236 +        return Arrays.asList(arr);
  12.237 +    }
  12.238 +    
  12.239 +    static Square findSquare(Board b, char column, int row) {
  12.240 +        for (Row r : b.getRows()) {
  12.241 +            for (Square square : r.getColumns()) {
  12.242 +                if (square.getPosition().getX() == column && square.getPosition().getY() == row) {
  12.243 +                    return square;
  12.244 +                }
  12.245 +            }
  12.246 +        }
  12.247 +        return null;
  12.248 +    }
  12.249 +
  12.250 +    private static Square findSquare(Board b, Position to) {
  12.251 +        return findSquare(b, (char)to.getX(), to.getY());
  12.252 +    }
  12.253 +    
  12.254 +    static Square findSelectedSquare(Board b) {
  12.255 +        for (Row row : b.getRows()) {
  12.256 +            for (Square square : row.getColumns()) {
  12.257 +                if (square.isSelected()) {
  12.258 +                    return square;
  12.259 +                }
  12.260 +            }
  12.261 +        }
  12.262 +        return null;
  12.263 +    }
  12.264 +
  12.265 +    static void moveResponse(final Board b, final String errMsg, final List<String> whites, final List<String> blacks, final Color turn,
  12.266 +        Alert alert
  12.267 +    ) {
  12.268 +        if (errMsg != null) {
  12.269 +            b.getMoves().remove(b.getPendingMove());
  12.270 +            b.setPendingMove(null);
  12.271 +            b.setAlertMessage(errMsg);
  12.272 +        } else {
  12.273 +            b.setTurn(turn);
  12.274 +            b.setAlertMessage(null);
  12.275 +        }
  12.276 +        b.setAlert(alert);
  12.277 +        Rules.initBoard(b, whites, blacks, turn);
  12.278 +    }
  12.279 +
  12.280 +    static void moveUpdate(final Board b, final Move move, final List<String> whites, final List<String> blacks, final Color turn, Alert alert) {
  12.281 +        final Square from = BoardModel.findSquare(b, move.getFrom());
  12.282 +        final Square to = BoardModel.findSquare(b, move.getTo());
  12.283 +        move.setPiece(from.getPiece());
  12.284 +        move.setTurn(from.getPieceColor());
  12.285 +        if (to.getPiece() != null) {
  12.286 +            move.setTakes(true);
  12.287 +        }
  12.288 +        b.setAlert(alert);
  12.289 +        b.setAlertMessage(alert == null ? null : alert.getMessage());
  12.290 +        move.setRound(b.getMoves().size() / 2 + 1);
  12.291 +        b.getMoves().add(move);
  12.292 +        Rules.initBoard(b, whites, blacks, turn);
  12.293 +    }
  12.294 +
  12.295 +    @Model(className="Row", properties = {
  12.296 +        @Property(name = "columns", type = Square.class, array = true)
  12.297 +    })
  12.298 +    static class RowsImpl {
  12.299 +        @ComputedProperty static int y(List<Square> columns) {
  12.300 +            return columns.isEmpty() ? 0 : columns.get(0).getY();
  12.301 +        }
  12.302 +    }
  12.303 +    
  12.304 +    enum PieceType {
  12.305 +        PAWN(5), ROCK(2), KNIGHT(4), BISHOP(3), QUEEN(1), KING(0);
  12.306 +
  12.307 +        final int entityIndex;
  12.308 +        
  12.309 +        PieceType(int ei) {
  12.310 +            this.entityIndex = ei;
  12.311 +        }
  12.312 +
  12.313 +        static PieceType fromNotation(char notation) {
  12.314 +            switch (notation) {
  12.315 +                case 'R': return ROCK;
  12.316 +                case 'N': return KNIGHT;
  12.317 +                case 'B': return BISHOP;
  12.318 +                case 'Q': return QUEEN;
  12.319 +                case 'K': return KING;
  12.320 +                case 'P': return PAWN;
  12.321 +            }
  12.322 +            throw new IllegalStateException("Unexpected: " + notation);
  12.323 +        }
  12.324 +        
  12.325 +        String computeEntity(Color color) {
  12.326 +            if (color == null) {
  12.327 +                color = Color.W;
  12.328 +            }
  12.329 +            int base;
  12.330 +            switch (color) {
  12.331 +                case W: base = 12; break;
  12.332 +                case B: base = 18; break;
  12.333 +                default:
  12.334 +                    throw new AssertionError();
  12.335 +            }
  12.336 +            return "&#98" + String.valueOf(base + entityIndex) + ";";
  12.337 +        }
  12.338 +    }
  12.339 +    
  12.340 +    @Model(className="Position", properties = {
  12.341 +        @Property(name = "x", type = char.class),
  12.342 +        @Property(name = "y", type = int.class),
  12.343 +    })
  12.344 +    static class PositionImpl {
  12.345 +        @ComputedProperty static String location(int x, int y) {
  12.346 +            return "" + (char)(x - 'A' + 'a') + y;
  12.347 +        }
  12.348 +    }
  12.349 +    
  12.350 +    @Model(className="Square", properties = {
  12.351 +        @Property(name = "position", type = Position.class),
  12.352 +        @Property(name = "color", type = Color.class),
  12.353 +        @Property(name = "piece", type = PieceType.class),
  12.354 +        @Property(name = "pieceColor", type = Color.class),
  12.355 +        @Property(name = "selected", type = boolean.class),
  12.356 +        @Property(name = "accessible", type = boolean.class),
  12.357 +        @Property(name = "pending", type = boolean.class),
  12.358 +    })
  12.359 +    static class SquareModel {
  12.360 +        @ComputedProperty static String pieceEntity(
  12.361 +            PieceType piece, Color pieceColor
  12.362 +        ) {
  12.363 +            if (piece == null) {
  12.364 +                return "";
  12.365 +            }
  12.366 +            return piece.computeEntity(pieceColor);
  12.367 +        }
  12.368 +        
  12.369 +        @ComputedProperty static String squareColor(
  12.370 +            Color color, boolean selected, boolean accessible, boolean pending
  12.371 +        ) {
  12.372 +            if (selected) {
  12.373 +                return "selected";
  12.374 +            }
  12.375 +            if (accessible) {
  12.376 +                return "accessible";
  12.377 +            }
  12.378 +            if (pending) {
  12.379 +                return "pending";
  12.380 +            }
  12.381 +            
  12.382 +            if (color == null) {
  12.383 +                return "";
  12.384 +            } else {
  12.385 +                if (color == Color.W) {
  12.386 +                    return "white";
  12.387 +                } else {
  12.388 +                    return "black";
  12.389 +                }
  12.390 +            }
  12.391 +        }
  12.392 +        
  12.393 +        @ComputedProperty static char x(Position position) {
  12.394 +            return position == null ? 'A' : position.getX();
  12.395 +        }
  12.396 +
  12.397 +        @ComputedProperty static int y(Position position) {
  12.398 +            return position == null ? 1 : position.getY();
  12.399 +        }
  12.400 +    }
  12.401 +    
  12.402 +    @Model(className = "Move", properties = {
  12.403 +        @Property(name = "round", type = int.class),
  12.404 +        @Property(name = "turn", type = Color.class),
  12.405 +        @Property(name = "piece", type = PieceType.class),
  12.406 +        @Property(name = "from", type = Position.class),
  12.407 +        @Property(name = "to", type = Position.class),
  12.408 +        @Property(name = "promoted", type = PieceType.class),
  12.409 +        @Property(name = "takes", type = boolean.class),
  12.410 +        @Property(name = "check", type = boolean.class),
  12.411 +    })
  12.412 +    static class MoveImpl {
  12.413 +        @ComputedProperty static boolean whiteMove(Color turn) {
  12.414 +            return turn == Color.W;
  12.415 +        }
  12.416 +        
  12.417 +        @ComputedProperty static String html(
  12.418 +            Position from, Position to, boolean takes, PieceType piece, Color turn
  12.419 +        ) {
  12.420 +            if (from == null || to == null) {
  12.421 +                return "";
  12.422 +            }
  12.423 +            StringBuilder sb = new StringBuilder();
  12.424 +            if (piece != null && piece != PieceType.PAWN) {
  12.425 +                sb.append(piece.computeEntity(turn));
  12.426 +            }
  12.427 +            
  12.428 +            sb.append(from.getLocation());
  12.429 +            if (takes) {
  12.430 +                sb.append("x");
  12.431 +            }
  12.432 +            sb.append(to.getLocation());
  12.433 +            return sb.toString();
  12.434 +        }
  12.435 +
  12.436 +        static Move valueOf(String move) {
  12.437 +            move = move.toUpperCase();
  12.438 +            Move m = new Move();
  12.439 +            {
  12.440 +                Position p = new Position();
  12.441 +                p.setX(move.charAt(0));
  12.442 +                p.setY(move.charAt(1) - '0');
  12.443 +                m.setFrom(p);
  12.444 +            }
  12.445 +            {
  12.446 +                Position p = new Position();
  12.447 +                p.setX(move.charAt(2));
  12.448 +                p.setY(move.charAt(3) - '0');
  12.449 +                m.setTo(p);
  12.450 +            }
  12.451 +            return m;
  12.452 +        }
  12.453 +    }
  12.454 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Color.java	Tue Sep 24 22:37:17 2013 +0200
    13.3 @@ -0,0 +1,32 @@
    13.4 +/**
    13.5 + * The MIT License (MIT)
    13.6 + *
    13.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    13.8 + *
    13.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   13.10 + * of this software and associated documentation files (the "Software"), to deal
   13.11 + * in the Software without restriction, including without limitation the rights
   13.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   13.13 + * copies of the Software, and to permit persons to whom the Software is
   13.14 + * furnished to do so, subject to the following conditions:
   13.15 + *
   13.16 + * The above copyright notice and this permission notice shall be included in
   13.17 + * all copies or substantial portions of the Software.
   13.18 + *
   13.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   13.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   13.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   13.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   13.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   13.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   13.25 + * THE SOFTWARE.
   13.26 + */
   13.27 +package org.apidesign.html.demo.chess;
   13.28 +
   13.29 +/**
   13.30 + *
   13.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   13.32 + */
   13.33 +public enum Color {
   13.34 +    W, B;
   13.35 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Communication.java	Tue Sep 24 22:37:17 2013 +0200
    14.3 @@ -0,0 +1,110 @@
    14.4 +/**
    14.5 + * The MIT License (MIT)
    14.6 + *
    14.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    14.8 + *
    14.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   14.10 + * of this software and associated documentation files (the "Software"), to deal
   14.11 + * in the Software without restriction, including without limitation the rights
   14.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   14.13 + * copies of the Software, and to permit persons to whom the Software is
   14.14 + * furnished to do so, subject to the following conditions:
   14.15 + *
   14.16 + * The above copyright notice and this permission notice shall be included in
   14.17 + * all copies or substantial portions of the Software.
   14.18 + *
   14.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   14.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   14.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   14.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   14.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   14.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   14.25 + * THE SOFTWARE.
   14.26 + */
   14.27 +package org.apidesign.html.demo.chess;
   14.28 +
   14.29 +import net.java.html.json.ComputedProperty;
   14.30 +import net.java.html.json.Model;
   14.31 +import net.java.html.json.Property;
   14.32 +
   14.33 +
   14.34 +/** Communication protocols to talk to the server.
   14.35 + *
   14.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   14.37 + */
   14.38 +final class Communication {
   14.39 +    @Model(className = "Request", properties = {
   14.40 +        @Property(name = "msg", type = MsgType.class),
   14.41 +        @Property(name = "username", type = String.class),
   14.42 +        @Property(name = "password", type = String.class),
   14.43 +        @Property(name = "gameId", type = String.class),
   14.44 +        @Property(name = "color", type = Color.class),
   14.45 +        @Property(name = "from", type = String.class),
   14.46 +        @Property(name = "to", type = String.class),
   14.47 +        @Property(name = "observer", type = boolean.class),
   14.48 +    })
   14.49 +    static class RequestModel {
   14.50 +    }
   14.51 +
   14.52 +    @Model(className = "BoardRep", properties = {
   14.53 +        @Property(name = "whites", type = String.class, array = true),
   14.54 +        @Property(name = "blacks", type = String.class, array = true),
   14.55 +    })
   14.56 +    static class BoardRepModel {
   14.57 +    }
   14.58 +
   14.59 +    @Model(className = "Response", properties = {
   14.60 +        @Property(name = "msg", type = String.class),
   14.61 +        @Property(name = "games", array = true, type = Game.class),
   14.62 +        @Property(name = "board", type = BoardRep.class),
   14.63 +        @Property(name = "turn", type = Color.class),
   14.64 +        @Property(name = "color", type = Color.class),
   14.65 +        @Property(name = "gameId", type = String.class),
   14.66 +        @Property(name = "error", type = Err.class),
   14.67 +        @Property(name = "alert", type = Alert.class),
   14.68 +        @Property(name = "status", type = String.class),
   14.69 +        @Property(name = "summary", type = String.class),
   14.70 +        @Property(name = "moves", type = String.class, array = true),
   14.71 +        @Property(name = "from", type = String.class),
   14.72 +        @Property(name = "to", type = String.class),
   14.73 +        @Property(name = "check", type = CheckResult.class),
   14.74 +        @Property(name = "whitePlayer", type = String.class),
   14.75 +        @Property(name = "blackPlayer", type = String.class),
   14.76 +    })
   14.77 +    static class ResponseModel {
   14.78 +        @ComputedProperty static Color nextTurn(Color turn, Alert alert) {
   14.79 +            if (alert == null || !alert.getType().isTerminal()) {
   14.80 +                return turn;
   14.81 +            } else {
   14.82 +                return null;
   14.83 +            }
   14.84 +        }
   14.85 +    }
   14.86 +
   14.87 +    static enum CheckResult {
   14.88 +        VALID, INVALID, NOT_REGISTERED
   14.89 +    };
   14.90 +    
   14.91 +    @Model(className = "Err", properties = {
   14.92 +        @Property(name = "code", type = int.class),
   14.93 +        @Property(name = "message", type = String.class),
   14.94 +    })
   14.95 +    static class ErrorModel {
   14.96 +    }
   14.97 +
   14.98 +    @Model(className = "Alert", properties = {
   14.99 +        @Property(name = "type", type = AlertType.class),
  14.100 +        @Property(name = "message", type = String.class),
  14.101 +    })
  14.102 +    static class AlertModel {
  14.103 +    }
  14.104 +
  14.105 +    static enum AlertType {
  14.106 +        CHECKMATE, CHECK, DRAW;
  14.107 +
  14.108 +        public boolean isTerminal() {
  14.109 +            return this == CHECKMATE || this == DRAW;
  14.110 +        }
  14.111 +    };
  14.112 +    
  14.113 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/GamesModel.java	Tue Sep 24 22:37:17 2013 +0200
    15.3 @@ -0,0 +1,86 @@
    15.4 +/**
    15.5 + * The MIT License (MIT)
    15.6 + *
    15.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    15.8 + *
    15.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   15.10 + * of this software and associated documentation files (the "Software"), to deal
   15.11 + * in the Software without restriction, including without limitation the rights
   15.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   15.13 + * copies of the Software, and to permit persons to whom the Software is
   15.14 + * furnished to do so, subject to the following conditions:
   15.15 + *
   15.16 + * The above copyright notice and this permission notice shall be included in
   15.17 + * all copies or substantial portions of the Software.
   15.18 + *
   15.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   15.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   15.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   15.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   15.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   15.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   15.25 + * THE SOFTWARE.
   15.26 + */
   15.27 +package org.apidesign.html.demo.chess;
   15.28 +
   15.29 +import java.util.List;
   15.30 +import net.java.html.json.ComputedProperty;
   15.31 +import net.java.html.json.Model;
   15.32 +import net.java.html.json.ModelOperation;
   15.33 +import net.java.html.json.Property;
   15.34 +
   15.35 +/**
   15.36 + *
   15.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   15.38 + */
   15.39 +@Model(className = "Games", properties = {
   15.40 +    @Property(name = "own", array = true, type = Game.class),
   15.41 +    @Property(name = "other", array = true, type = Game.class),
   15.42 +    @Property(name = "selectedColor", type = String.class),
   15.43 +})
   15.44 +class GamesModel {
   15.45 +    @Model(className = "Game", properties = {
   15.46 +        @Property(name = "gameId", type=String.class),
   15.47 +        @Property(name = "summary", type=String.class),
   15.48 +        @Property(name = "open", type=boolean.class),
   15.49 +        @Property(name = "whitePlayer", type=String.class),
   15.50 +        @Property(name = "blackPlayer", type=String.class)
   15.51 +    })
   15.52 +    static class GameImpl {
   15.53 +        @ComputedProperty static String description(String gameId, String summary) {
   15.54 +            return summary != null ? summary : gameId;
   15.55 +        }
   15.56 +        
   15.57 +        @ComputedProperty static boolean pendingPlayer(String whitePlayer, String blackPlayer) {
   15.58 +            return whitePlayer == null || blackPlayer == null;
   15.59 +        }
   15.60 +    }
   15.61 +    
   15.62 +    
   15.63 +    @ComputedProperty static boolean anyOwnGame(List<Game> own) {
   15.64 +        return !own.isEmpty();
   15.65 +    }
   15.66 +
   15.67 +    @ComputedProperty static boolean anyOtherGame(List<Game> other) {
   15.68 +        return !other.isEmpty();
   15.69 +    }
   15.70 +    
   15.71 +    @ModelOperation static void listGames(Games g, List<Game> games, String username) {
   15.72 +        g.getOwn().clear();
   15.73 +        g.getOther().clear();
   15.74 +        int cnt = 0;
   15.75 +        final int maxGames = 30;
   15.76 +        for (Game game : games) {
   15.77 +            if (
   15.78 +                username.equals(game.getWhitePlayer()) || 
   15.79 +                username.equals(game.getBlackPlayer())
   15.80 +            ) {
   15.81 +                g.getOwn().add(game);
   15.82 +            } else {
   15.83 +                if (cnt++ < maxGames) {
   15.84 +                    g.getOther().add(game);
   15.85 +                }
   15.86 +            }
   15.87 +        }
   15.88 +    }
   15.89 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/LoadMain.java	Tue Sep 24 22:37:17 2013 +0200
    16.3 @@ -0,0 +1,41 @@
    16.4 +/**
    16.5 + * The MIT License (MIT)
    16.6 + *
    16.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    16.8 + *
    16.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   16.10 + * of this software and associated documentation files (the "Software"), to deal
   16.11 + * in the Software without restriction, including without limitation the rights
   16.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   16.13 + * copies of the Software, and to permit persons to whom the Software is
   16.14 + * furnished to do so, subject to the following conditions:
   16.15 + *
   16.16 + * The above copyright notice and this permission notice shall be included in
   16.17 + * all copies or substantial portions of the Software.
   16.18 + *
   16.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   16.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   16.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   16.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   16.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   16.25 + * THE SOFTWARE.
   16.26 + */
   16.27 +package org.apidesign.html.demo.chess;
   16.28 +
   16.29 +
   16.30 +public final class LoadMain {
   16.31 +    private LoadMain() {
   16.32 +    }
   16.33 +    
   16.34 +    /**
   16.35 +     * Called when the page is ready.
   16.36 +     */
   16.37 +    static {
   16.38 +        try {
   16.39 +            UIModel.initialize();
   16.40 +        } catch (Throwable ex) {
   16.41 +            ex.printStackTrace();
   16.42 +        }
   16.43 +    }
   16.44 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Main.java	Tue Sep 24 22:37:17 2013 +0200
    17.3 @@ -0,0 +1,42 @@
    17.4 +/**
    17.5 + * The MIT License (MIT)
    17.6 + *
    17.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    17.8 + *
    17.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   17.10 + * of this software and associated documentation files (the "Software"), to deal
   17.11 + * in the Software without restriction, including without limitation the rights
   17.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   17.13 + * copies of the Software, and to permit persons to whom the Software is
   17.14 + * furnished to do so, subject to the following conditions:
   17.15 + *
   17.16 + * The above copyright notice and this permission notice shall be included in
   17.17 + * all copies or substantial portions of the Software.
   17.18 + *
   17.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   17.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   17.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   17.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   17.25 + * THE SOFTWARE.
   17.26 + */
   17.27 +package org.apidesign.html.demo.chess;
   17.28 +
   17.29 +import net.java.html.boot.BrowserBuilder;
   17.30 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
   17.31 +
   17.32 +public final class Main {
   17.33 +    private Main() {
   17.34 +    }
   17.35 +
   17.36 +    @JavaScriptOnly(name = "main", value = "null")
   17.37 +    public static void main(String... args) throws Exception {
   17.38 +        BrowserBuilder.newBrowser().
   17.39 +            loadPage("pages/index.html").
   17.40 +            loadClass(UIModel.class).
   17.41 +            invoke("initialize", args).
   17.42 +            showAndWait();
   17.43 +        System.exit(0);
   17.44 +    }
   17.45 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/MsgType.java	Tue Sep 24 22:37:17 2013 +0200
    18.3 @@ -0,0 +1,40 @@
    18.4 +/**
    18.5 + * The MIT License (MIT)
    18.6 + *
    18.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    18.8 + *
    18.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   18.10 + * of this software and associated documentation files (the "Software"), to deal
   18.11 + * in the Software without restriction, including without limitation the rights
   18.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   18.13 + * copies of the Software, and to permit persons to whom the Software is
   18.14 + * furnished to do so, subject to the following conditions:
   18.15 + *
   18.16 + * The above copyright notice and this permission notice shall be included in
   18.17 + * all copies or substantial portions of the Software.
   18.18 + *
   18.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   18.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   18.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   18.25 + * THE SOFTWARE.
   18.26 + */
   18.27 +package org.apidesign.html.demo.chess;
   18.28 +
   18.29 +/**
   18.30 + *
   18.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   18.32 + */
   18.33 + enum MsgType {
   18.34 +    CreateGame, QueryGames, SendMove, JoinGame, UpdateGame, CheckCredentials;
   18.35 +
   18.36 +    static MsgType forResponse(String msg) {
   18.37 +        if (msg.endsWith("Rsp")) {
   18.38 +            msg = msg.substring(0, msg.length() - 3);
   18.39 +        }
   18.40 +        return MsgType.valueOf(msg);
   18.41 +    }
   18.42 +    
   18.43 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Rules.java	Tue Sep 24 22:37:17 2013 +0200
    19.3 @@ -0,0 +1,314 @@
    19.4 +/**
    19.5 + * The MIT License (MIT)
    19.6 + *
    19.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    19.8 + *
    19.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   19.10 + * of this software and associated documentation files (the "Software"), to deal
   19.11 + * in the Software without restriction, including without limitation the rights
   19.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   19.13 + * copies of the Software, and to permit persons to whom the Software is
   19.14 + * furnished to do so, subject to the following conditions:
   19.15 + *
   19.16 + * The above copyright notice and this permission notice shall be included in
   19.17 + * all copies or substantial portions of the Software.
   19.18 + *
   19.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   19.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   19.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   19.25 + * THE SOFTWARE.
   19.26 + */
   19.27 +package org.apidesign.html.demo.chess;
   19.28 +
   19.29 +import java.util.ArrayList;
   19.30 +import java.util.List;
   19.31 +
   19.32 +/** Common chess rules.
   19.33 + *
   19.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   19.35 + */
   19.36 +class Rules {
   19.37 +    static void computeAccessible(Board b, Square s) {
   19.38 +        for (Row r : b.getRows()) {
   19.39 +            for (Square ts : r.getColumns()) {
   19.40 +                ts.setAccessible(false);
   19.41 +            }
   19.42 +        }
   19.43 +        if (s == null) {
   19.44 +            return;
   19.45 +        }
   19.46 +        
   19.47 +        switch (s.getPiece()) {
   19.48 +            case BISHOP: 
   19.49 +                moveBishop(b, s);
   19.50 +                break;
   19.51 +            case KING:
   19.52 +                computeAccessible(b, s, 1, 1, 1);
   19.53 +                computeAccessible(b, s, 1, -1, 1);
   19.54 +                computeAccessible(b, s, -1, -1, 1);
   19.55 +                computeAccessible(b, s, -1, 1, 1);
   19.56 +                computeAccessible(b, s, 1, 0, 1);
   19.57 +                computeAccessible(b, s, 0, -1, 1);
   19.58 +                computeAccessible(b, s, 0, 1, 1);
   19.59 +                computeAccessible(b, s, -1, 0, 1);
   19.60 +                checkRochade(b, s);
   19.61 +                break;
   19.62 +            case ROCK:
   19.63 +                moveRock(b, s);
   19.64 +                break;
   19.65 +            case QUEEN:
   19.66 +                moveRock(b, s);
   19.67 +                moveBishop(b, s);
   19.68 +                break;
   19.69 +            case KNIGHT:
   19.70 +                computeAccessible(b, s, 2, 1, 1);
   19.71 +                computeAccessible(b, s, 2, -1, 1);
   19.72 +                computeAccessible(b, s, -2, -1, 1);
   19.73 +                computeAccessible(b, s, -2, 1, 1);
   19.74 +                computeAccessible(b, s, 1, 2, 1);
   19.75 +                computeAccessible(b, s, -1, 2, 1);
   19.76 +                computeAccessible(b, s, -1, -2, 1);
   19.77 +                computeAccessible(b, s, 1, -2, 1);
   19.78 +                break;
   19.79 +            case PAWN:
   19.80 +                pawns(b, s);
   19.81 +                break;
   19.82 +        }
   19.83 +    }
   19.84 +
   19.85 +    private static void moveRock(Board b, Square s) {
   19.86 +        computeAccessible(b, s, 1, 0, 8);
   19.87 +        computeAccessible(b, s, 0, -1, 8);
   19.88 +        computeAccessible(b, s, -1, 0, 8);
   19.89 +        computeAccessible(b, s, 0, 1, 8);
   19.90 +    }
   19.91 +
   19.92 +    private static void moveBishop(Board b, Square s) {
   19.93 +        computeAccessible(b, s, 1, 1, 8);
   19.94 +        computeAccessible(b, s, 1, -1, 8);
   19.95 +        computeAccessible(b, s, -1, -1, 8);
   19.96 +        computeAccessible(b, s, -1, 1, 8);
   19.97 +    }
   19.98 +    
   19.99 +    private static void computeAccessible(
  19.100 +        Board b, Square s, int dx, int dy,
  19.101 +        int limit
  19.102 +    ) {
  19.103 +        int x = s.getX();
  19.104 +        int y = s.getY();
  19.105 +        
  19.106 +        while (limit-- > 0) {
  19.107 +            x += dx;
  19.108 +            y += dy;
  19.109 +            Square next = BoardModel.findSquare(b, (char)x, y);
  19.110 +            if (next == null) {
  19.111 +                break;
  19.112 +            }
  19.113 +            if (next.getPieceColor() == s.getPieceColor()) {
  19.114 +                break;
  19.115 +            }
  19.116 +            next.setAccessible(true);
  19.117 +            if (next.getPieceColor() != null) {
  19.118 +                break;
  19.119 +            }
  19.120 +        }
  19.121 +    }
  19.122 +    
  19.123 +    private static void pawns(Board b, Square s) {
  19.124 +        final boolean white = s.getPieceColor() == Color.W;
  19.125 +        int dy = white ? 1 : -1;
  19.126 +        Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
  19.127 +        if (step != null && step.getPiece() == null) {
  19.128 +            step.setAccessible(true);
  19.129 +            if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
  19.130 +                Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
  19.131 +                if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
  19.132 +                    nextSTep.setAccessible(true);
  19.133 +                }
  19.134 +            }
  19.135 +        }
  19.136 +        Color opposite = white ? Color.B : Color.W;
  19.137 +        Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
  19.138 +        if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
  19.139 +            takeLeft.setAccessible(true);
  19.140 +        }
  19.141 +        Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
  19.142 +        if (takeRight != null && takeRight.getPieceColor() == opposite) {
  19.143 +            takeRight.setAccessible(true);
  19.144 +        }
  19.145 +        if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
  19.146 +            int enPassantFrom = white ? 7 : 2;
  19.147 +            int enPassantTo = white ? 5 : 4;
  19.148 +            if (!b.getMoves().isEmpty()) {
  19.149 +                Move last = b.getMoves().get(b.getMoves().size() - 1);
  19.150 +                if (
  19.151 +                    last.getPiece() == BoardModel.PieceType.PAWN &&
  19.152 +                    last.getFrom().getY() == enPassantFrom &&
  19.153 +                    last.getTo().getY() == enPassantTo
  19.154 +                ) {
  19.155 +                    if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
  19.156 +                        takeLeft.setAccessible(true);
  19.157 +                    }
  19.158 +                    if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
  19.159 +                        takeRight.setAccessible(true);
  19.160 +                    }
  19.161 +                }
  19.162 +            }
  19.163 +        }
  19.164 +    }
  19.165 +
  19.166 +    static Board createBoard() {
  19.167 +        Board b = new Board();
  19.168 +        initBoardField(b);
  19.169 +        initBoard(b);
  19.170 +        return b;
  19.171 +    }
  19.172 +
  19.173 +    private static void initBoardField(Board b) {
  19.174 +        List<Row> addRows = new ArrayList<>(8);
  19.175 +        for (int i = 8; i > 0; i--) {
  19.176 +            Square[] arr = new Square[8];
  19.177 +            for (char j = 'A'; j <= 'H'; j++) {
  19.178 +                arr[j - 'A'] = new Square(
  19.179 +                    new Position(j, i),
  19.180 +                    (i + j) % 2 == 1 ? Color.W : Color.B,
  19.181 +                    null, null, // figure
  19.182 +                    false, false, false
  19.183 +                );
  19.184 +            }
  19.185 +            addRows.add(new Row(arr));
  19.186 +        }
  19.187 +        b.getRows().addAll(addRows);
  19.188 +    }
  19.189 +    
  19.190 +    static void initBoard(Board b) {
  19.191 +        initBoard(b, true);
  19.192 +    }
  19.193 +    private static void initBoard(Board b, boolean init) {
  19.194 +        if (init) {
  19.195 +            b.setTurn(Color.W);
  19.196 +        }
  19.197 +        if (b.getRows().isEmpty()) {
  19.198 +            for (int i = 8; i > 0; i--) {
  19.199 +                Row r = b.getRows().get(8 - i);
  19.200 +                for (char j = 'A'; j <= 'H'; j++) {
  19.201 +                    Square s = r.getColumns().get(j - 'A');
  19.202 +                    s.setAccessible(false);
  19.203 +                    s.setPending(false);
  19.204 +                    r.getColumns().set(j - 'A', s);
  19.205 +                    initialPosition(s, init);
  19.206 +                }
  19.207 +            }
  19.208 +        } else {
  19.209 +            for (Row r : b.getRows()) {
  19.210 +                for (Square square : r.getColumns()) {
  19.211 +                    square.setAccessible(false);
  19.212 +                    square.setPending(false);
  19.213 +                    square.setPiece(null);
  19.214 +                    square.setPieceColor(null);
  19.215 +                    square.setSelected(false);
  19.216 +                    initialPosition(square, init);
  19.217 +                }
  19.218 +            }
  19.219 +        }
  19.220 +        b.setPendingMove(null);
  19.221 +    }
  19.222 +
  19.223 +    private static void initialPosition(Square s, boolean init) {
  19.224 +        int row = s.getPosition().getY();
  19.225 +        char column = s.getPosition().getX();
  19.226 +        s.setPiece(null);
  19.227 +        s.setPieceColor(null);
  19.228 +        if (init) {
  19.229 +            if (row == 2) {
  19.230 +                s.setPiece(BoardModel.PieceType.PAWN);
  19.231 +                s.setPieceColor(Color.W);
  19.232 +            } else if (row == 7) {
  19.233 +                s.setPiece(BoardModel.PieceType.PAWN);
  19.234 +                s.setPieceColor(Color.B);
  19.235 +            } else if (row == 8 || row == 1) {
  19.236 +                s.setPieceColor(row == 1 ? Color.W : Color.B);
  19.237 +                BoardModel.PieceType t;
  19.238 +                switch (column) {
  19.239 +                    case 'A':
  19.240 +                    case 'H':
  19.241 +                        t = BoardModel.PieceType.ROCK;
  19.242 +                        break;
  19.243 +                    case 'B':
  19.244 +                    case 'G':
  19.245 +                        t = BoardModel.PieceType.KNIGHT;
  19.246 +                        break;
  19.247 +                    case 'C':
  19.248 +                    case 'F':
  19.249 +                        t = BoardModel.PieceType.BISHOP;
  19.250 +                        break;
  19.251 +                    case 'D':
  19.252 +                        t = BoardModel.PieceType.QUEEN;
  19.253 +                        break;
  19.254 +                    default:
  19.255 +                        t = BoardModel.PieceType.KING;
  19.256 +                        break;
  19.257 +                }
  19.258 +                s.setPiece(t);
  19.259 +            }
  19.260 +        }
  19.261 +    }
  19.262 +
  19.263 +    static void initBoard(
  19.264 +        Board board, List<String> whites, List<String> blacks, Color turn
  19.265 +    ) {
  19.266 +        initBoard(board, false);
  19.267 +        for (String w : whites) {
  19.268 +            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
  19.269 +            w = w.toUpperCase();
  19.270 +            char column = w.charAt(1);
  19.271 +            int row = (w.charAt(2) - '0');
  19.272 +            
  19.273 +            Square s = BoardModel.findSquare(board, column, row);
  19.274 +            s.setPieceColor(Color.W);
  19.275 +            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
  19.276 +        }
  19.277 +        for (String w : blacks) {
  19.278 +            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
  19.279 +            w = w.toUpperCase();
  19.280 +            char column = w.charAt(1);
  19.281 +            int row = (w.charAt(2) - '0');
  19.282 +            
  19.283 +            Square s = BoardModel.findSquare(board, column, row);
  19.284 +            s.setPieceColor(Color.B);
  19.285 +            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
  19.286 +        }
  19.287 +        board.setTurn(turn);
  19.288 +    }
  19.289 +
  19.290 +    private static void checkRochade(Board b, Square s) {
  19.291 +        if (s.getPosition().getX() == 'E') {
  19.292 +            int y = s.getPosition().getY();
  19.293 +            final Square gRow = BoardModel.findSquare(b, 'G', y);
  19.294 +            if (
  19.295 +                BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK 
  19.296 +                &&
  19.297 +                BoardModel.findSquare(b, 'F', y).getPiece() == null
  19.298 +                &&
  19.299 +                gRow.getPiece() == null
  19.300 +            ) {
  19.301 +                gRow.setAccessible(true);
  19.302 +            }
  19.303 +            final Square cRow = BoardModel.findSquare(b, 'C', y);
  19.304 +            if (
  19.305 +                BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK 
  19.306 +                &&
  19.307 +                BoardModel.findSquare(b, 'B', y).getPiece() == null
  19.308 +                &&
  19.309 +                BoardModel.findSquare(b, 'D', y).getPiece() == null
  19.310 +                &&
  19.311 +                cRow.getPiece() == null
  19.312 +            ) {
  19.313 +                cRow.setAccessible(true);
  19.314 +            }
  19.315 +        }
  19.316 +    }
  19.317 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/SettingsModel.java	Tue Sep 24 22:37:17 2013 +0200
    20.3 @@ -0,0 +1,82 @@
    20.4 +/**
    20.5 + * The MIT License (MIT)
    20.6 + *
    20.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    20.8 + *
    20.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   20.10 + * of this software and associated documentation files (the "Software"), to deal
   20.11 + * in the Software without restriction, including without limitation the rights
   20.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   20.13 + * copies of the Software, and to permit persons to whom the Software is
   20.14 + * furnished to do so, subject to the following conditions:
   20.15 + *
   20.16 + * The above copyright notice and this permission notice shall be included in
   20.17 + * all copies or substantial portions of the Software.
   20.18 + *
   20.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   20.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   20.25 + * THE SOFTWARE.
   20.26 + */
   20.27 +package org.apidesign.html.demo.chess;
   20.28 +
   20.29 +import java.io.File;
   20.30 +import java.io.FileInputStream;
   20.31 +import java.io.FileOutputStream;
   20.32 +import java.io.IOException;
   20.33 +import java.util.Properties;
   20.34 +import net.java.html.json.ComputedProperty;
   20.35 +import net.java.html.json.Model;
   20.36 +import net.java.html.json.ModelOperation;
   20.37 +import net.java.html.json.Property;
   20.38 +
   20.39 +/**
   20.40 + *
   20.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   20.42 + */
   20.43 +@Model(className = "Settings", properties = {
   20.44 +    @Property(name = "username", type = String.class),
   20.45 +    @Property(name = "password", type = String.class),
   20.46 +    @Property(name = "url", type = String.class),
   20.47 +})
   20.48 +class SettingsModel {
   20.49 +    private static final String SETTINGS = ".j1chess/html.properties";
   20.50 +    private static final String DEFAULT_URL = "ws://localhost:8080/chess/chessserver";
   20.51 +    
   20.52 +    @ComputedProperty static boolean validCredentials(String username, String password) {
   20.53 +        return username != null && password != null && !username.isEmpty() && !password.isEmpty();
   20.54 +    }
   20.55 +    
   20.56 +    @ModelOperation static void read(Settings s) {
   20.57 +        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   20.58 +        try (FileInputStream is = new FileInputStream(prefs)) {
   20.59 +            Properties p = new Properties();
   20.60 +            p.load(is);
   20.61 +            
   20.62 +            s.setUsername(p.getProperty("username", ""));
   20.63 +            s.setPassword(p.getProperty("password", ""));
   20.64 +            s.setUrl(p.getProperty("url", DEFAULT_URL));
   20.65 +        } catch (Throwable ex) {
   20.66 +            s.setUsername("");
   20.67 +            s.setPassword("");
   20.68 +            s.setUrl(DEFAULT_URL);
   20.69 +        }
   20.70 +    }
   20.71 +    
   20.72 +    @ModelOperation static void write(Settings s, UI ui) {
   20.73 +        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   20.74 +        prefs.getParentFile().mkdirs();
   20.75 +        try (FileOutputStream os = new FileOutputStream(prefs)) {
   20.76 +            Properties p = new Properties();
   20.77 +            p.setProperty("username", s.getUsername());
   20.78 +            p.setProperty("password", s.getPassword());
   20.79 +            p.setProperty("url", s.getUrl());
   20.80 +            p.store(os, "Java One Chess Preferences for HTML/Java Client");
   20.81 +        } catch (Throwable ex) {
   20.82 +            ui.setStatus("Cannot save preferences: " + ex.getMessage());
   20.83 +        }
   20.84 +    }
   20.85 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/UIModel.java	Tue Sep 24 22:37:17 2013 +0200
    21.3 @@ -0,0 +1,315 @@
    21.4 +/**
    21.5 + * The MIT License (MIT)
    21.6 + *
    21.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    21.8 + *
    21.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   21.10 + * of this software and associated documentation files (the "Software"), to deal
   21.11 + * in the Software without restriction, including without limitation the rights
   21.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   21.13 + * copies of the Software, and to permit persons to whom the Software is
   21.14 + * furnished to do so, subject to the following conditions:
   21.15 + *
   21.16 + * The above copyright notice and this permission notice shall be included in
   21.17 + * all copies or substantial portions of the Software.
   21.18 + *
   21.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   21.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   21.25 + * THE SOFTWARE.
   21.26 + */
   21.27 +package org.apidesign.html.demo.chess;
   21.28 +
   21.29 +import java.io.IOException;
   21.30 +import java.net.URISyntaxException;
   21.31 +import java.util.HashSet;
   21.32 +import java.util.List;
   21.33 +import java.util.Set;
   21.34 +import java.util.logging.Level;
   21.35 +import java.util.logging.Logger;
   21.36 +import net.java.html.json.ComputedProperty;
   21.37 +import net.java.html.json.Function;
   21.38 +import net.java.html.json.Model;
   21.39 +import net.java.html.json.ModelOperation;
   21.40 +import net.java.html.json.OnPropertyChange;
   21.41 +import net.java.html.json.OnReceive;
   21.42 +import net.java.html.json.Property;
   21.43 +
   21.44 +/**
   21.45 + *
   21.46 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.47 + */
   21.48 +@Model(className = "UI", properties = {
   21.49 +    @Property(name = "status", type = String.class),
   21.50 +    @Property(name = "selectedGameId", type = String.class),
   21.51 +    @Property(name = "boards", type = Board.class, array = true),
   21.52 +    @Property(name = "viewGames", type = Games.class),
   21.53 +    @Property(name = "settings", type = Settings.class),
   21.54 +    @Property(name = "connected", type = boolean.class),
   21.55 +    @Property(name = "disconnected", type = boolean.class),
   21.56 +})
   21.57 +public class UIModel {
   21.58 +    private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
   21.59 +    
   21.60 +    @ComputedProperty static boolean settingsActive(String selectedGameId) {
   21.61 +        return selectedGameId == null;
   21.62 +    }
   21.63 +    
   21.64 +    @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
   21.65 +        return selectedGameId == null && connected;
   21.66 +    }
   21.67 +    
   21.68 +    @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
   21.69 +        Board active = null;
   21.70 +        for (Board b : boards) {
   21.71 +            b.setActive(false);
   21.72 +            if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
   21.73 +                b.setActive(true);
   21.74 +                active = b;
   21.75 +            }
   21.76 +        }
   21.77 +        return active;
   21.78 +    }
   21.79 +    
   21.80 +    @Function static void activateGame(UI m, Board data) {
   21.81 +        m.setSelectedGameId(data.getGameId());
   21.82 +    }
   21.83 +
   21.84 +    @Function static void activateSettings(UI m) {
   21.85 +        m.setSelectedGameId(null);
   21.86 +        refreshGames(m);
   21.87 +    }
   21.88 +    
   21.89 +    @Function static void createGame(UI u) {
   21.90 +        u.setStatus("Creating new game...");
   21.91 +        Request r = new Request();
   21.92 +        r.setMsg(MsgType.CreateGame);
   21.93 +        r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
   21.94 +        u.sendMsg(r);
   21.95 +    }
   21.96 +
   21.97 +    @ModelOperation @Function static void refreshGames(UI u) {
   21.98 +        u.setStatus("Refreshing games...");
   21.99 +        Request r = new Request();
  21.100 +        r.setMsg(MsgType.QueryGames);
  21.101 +        u.sendMsg(r);
  21.102 +    }
  21.103 +    
  21.104 +    @ModelOperation static void sendMsg(UI ui, Request r) {
  21.105 +        final Settings sttngs = ui.getSettings();
  21.106 +        
  21.107 +        String url = sttngs.getUrl();
  21.108 +        r.setUsername(sttngs.getUsername());
  21.109 +        r.setPassword(sttngs.getPassword());
  21.110 +        
  21.111 +        LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
  21.112 +        ui.queryServer(url, r);
  21.113 +    }
  21.114 +    
  21.115 +    
  21.116 +    @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError") 
  21.117 +    static void queryServer(UI ui, Response r) {
  21.118 +        LOG.log(Level.INFO, "Received {0}", r);
  21.119 +        if (r == null) {
  21.120 +            ui.setDisconnected(false);
  21.121 +            verifyLogin(ui);
  21.122 +            return;
  21.123 +        }
  21.124 +        SWITCH: switch (MsgType.forResponse(r.getMsg())) {
  21.125 +            case CheckCredentials: {
  21.126 +                switch (r.getCheck()) {
  21.127 +                    case NOT_REGISTERED:
  21.128 +                    case VALID:
  21.129 +                        ui.setConnected(true);
  21.130 +                        ui.refreshGames();
  21.131 +                        ui.setStatus("Connected.");
  21.132 +                        return;
  21.133 +                    case INVALID:
  21.134 +                        ui.setStatus("Password is invalid");
  21.135 +                        break;
  21.136 +                }
  21.137 +                disconnect(ui);
  21.138 +            }
  21.139 +                
  21.140 +            case QueryGames:
  21.141 +                ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
  21.142 +                ui.setStatus("");
  21.143 +                break;
  21.144 +            case CreateGame: {
  21.145 +                ui.setStatus("Game " + r + " created");
  21.146 +                final Board b = Rules.createBoard();
  21.147 +                Rules.initBoard(
  21.148 +                    b, r.getBoard().getWhites(),
  21.149 +                    r.getBoard().getBlacks(),
  21.150 +                    r.getTurn()
  21.151 +                );
  21.152 +                b.setGameId(r.getGameId());
  21.153 +                b.setWhitePlayer(r.getWhitePlayer());
  21.154 +                b.setBlackPlayer(r.getBlackPlayer());
  21.155 +                b.setPlayer(ui.getSettings().getUsername());
  21.156 +                b.updateSummary(r.getSummary());
  21.157 +                ui.getBoards().add(b);
  21.158 +                ui.setSelectedGameId(r.getGameId());
  21.159 +                UIModel.refreshGames(ui);
  21.160 +                break;
  21.161 +            }
  21.162 +            case SendMove: {
  21.163 +                if (r.getBoard() == null) {
  21.164 +                    throw new NullPointerException("No board in " + r);
  21.165 +                }
  21.166 +                final Board b = findBoard(ui, r.getGameId());
  21.167 +                if (b == null) {
  21.168 +                    break;
  21.169 +                }
  21.170 +                b.updateSummary(r.getSummary());
  21.171 +                final String errMsg = r.getError() == null ? null : r.getError().getMessage();
  21.172 +                final List<String> whites = r.getBoard().getWhites();
  21.173 +                final List<String> blacks = r.getBoard().getBlacks();
  21.174 +                final Color turn = r.getNextTurn();
  21.175 +                BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
  21.176 +                break;
  21.177 +            }
  21.178 +            case JoinGame: {
  21.179 +                Board b;
  21.180 +                if ((b = findBoard(ui, r.getGameId())) != null) {
  21.181 +                    b.setWhitePlayer(r.getWhitePlayer());
  21.182 +                    b.setBlackPlayer(r.getBlackPlayer());
  21.183 +                    b.setPlayer(ui.getSettings().getUsername());
  21.184 +                    b.updateSummary(r.getSummary());
  21.185 +                    ui.setSelectedGameId(r.getGameId());
  21.186 +                    break SWITCH;
  21.187 +                }
  21.188 +                ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
  21.189 +                b = Rules.createBoard();
  21.190 +                Rules.initBoard(
  21.191 +                    b, r.getBoard().getWhites(),
  21.192 +                    r.getBoard().getBlacks(),
  21.193 +                    r.getTurn()
  21.194 +                );
  21.195 +                b.setGameId(r.getGameId());
  21.196 +                b.setWhitePlayer(r.getWhitePlayer());
  21.197 +                b.setBlackPlayer(r.getBlackPlayer());
  21.198 +                b.setPlayer(ui.getSettings().getUsername());
  21.199 +                b.updateSummary(r.getSummary());
  21.200 +                if (r.getColor() == Color.B) {
  21.201 +                    BoardModel.rotateBoard(b);
  21.202 +                }
  21.203 +                if (r.getMoves() != null) {
  21.204 +                    for (String move : r.getMoves()) {
  21.205 +                        Move m = BoardModel.MoveImpl.valueOf(move);
  21.206 +                        b.getMoves().add(m);
  21.207 +                    }
  21.208 +                } else {
  21.209 +                    b.getMoves().clear();
  21.210 +                }
  21.211 +                ui.setSelectedGameId(b.getGameId());
  21.212 +                ui.getBoards().add(b);
  21.213 +                break;
  21.214 +            }
  21.215 +            case UpdateGame: {
  21.216 +                final Board b = findBoard(ui, r.getGameId());
  21.217 +                if (b == null) {
  21.218 +                    break;
  21.219 +                }
  21.220 +                b.updateSummary(r.getSummary());
  21.221 +                final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
  21.222 +                final List<String> whites = r.getBoard().getWhites();
  21.223 +                final List<String> blacks = r.getBoard().getBlacks();
  21.224 +                final Color turn = r.getNextTurn();
  21.225 +                BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
  21.226 +            }
  21.227 +        }
  21.228 +    }
  21.229 +
  21.230 +
  21.231 +    private static Board findBoard(UI ui, String gameId) {
  21.232 +        for (Board tmp : ui.getBoards()) {
  21.233 +            if (tmp.getGameId().equals(gameId)) {
  21.234 +                return tmp;
  21.235 +            }
  21.236 +        }
  21.237 +        return null;
  21.238 +    }
  21.239 +    
  21.240 +    
  21.241 +    static void wasAnError(UI ui, Exception t) {
  21.242 +        if (t == null) {
  21.243 +            ui.setConnected(false);
  21.244 +            ui.setDisconnected(true);
  21.245 +            ui.setStatus("Disconnected.");
  21.246 +        } else {
  21.247 +            ui.setStatus("Error: " + t.getLocalizedMessage());
  21.248 +        }
  21.249 +    }
  21.250 +    
  21.251 +    @Function static void joinGame(UI u, Game data) {
  21.252 +        Request r = new Request();
  21.253 +        r.setMsg(MsgType.JoinGame);
  21.254 +        r.setObserver(false);
  21.255 +        r.setGameId(data.getGameId());
  21.256 +        u.sendMsg(r);
  21.257 +    }
  21.258 +
  21.259 +    @Function static void observeGame(UI u, Game data) {
  21.260 +        Request r = new Request();
  21.261 +        r.setMsg(MsgType.JoinGame);
  21.262 +        r.setObserver(true);
  21.263 +        r.setGameId(data.getGameId());
  21.264 +        u.sendMsg(r);
  21.265 +    }
  21.266 +
  21.267 +    private static final Set<UI> ACTIVE = new HashSet<>();
  21.268 +    @OnPropertyChange("connected") static void clearGames(UI m) {
  21.269 +        if (m.isDisconnected()) {
  21.270 +            m.getBoards().clear();
  21.271 +            ACTIVE.remove(m);
  21.272 +        } else {
  21.273 +            ACTIVE.add(m);
  21.274 +        }
  21.275 +    }
  21.276 +    
  21.277 +    static UI findUI(Board b) {
  21.278 +        for (UI ui : ACTIVE) {
  21.279 +            if (ui.getBoards().contains(b)) {
  21.280 +                return ui;
  21.281 +            }
  21.282 +        }
  21.283 +        return null;
  21.284 +    }
  21.285 +    
  21.286 +    @Function static void leave(UI ui, Board data) {
  21.287 +        ui.getBoards().remove(data);
  21.288 +        ui.setSelectedGameId(null);
  21.289 +    }
  21.290 +    
  21.291 +    @Function static void disconnect(UI ui) {
  21.292 +        ui.queryServer(ui.getSettings().getUrl(), null);
  21.293 +        ui.setStatus("Disconnecting...");
  21.294 +    }
  21.295 +
  21.296 +    private static void verifyLogin(UI ui) {
  21.297 +        ui.setStatus("Verifying user credentials...");
  21.298 +        Request r = new Request();
  21.299 +        r.setMsg(MsgType.CheckCredentials);
  21.300 +        ui.sendMsg(r);
  21.301 +    }
  21.302 +    
  21.303 +    @Function static void reconnect(UI ui) {
  21.304 +        final Settings s = ui.getSettings();
  21.305 +        ui.setStatus("Connecting to the server...");
  21.306 +        ui.queryServer(s.getUrl(), null);
  21.307 +        s.write(ui);
  21.308 +    }
  21.309 +    
  21.310 +    public static void initialize(String... args) throws URISyntaxException, IOException {
  21.311 +        UI ui = new UI();
  21.312 +        ui.getSettings().read();
  21.313 +        ui.setStatus("Ready.");
  21.314 +        ui.setDisconnected(true);
  21.315 +        ui.applyBindings();
  21.316 +    }
  21.317 +
  21.318 +}
    22.1 --- a/chess/src/test/java/com/oracle/chess/client/htmljava/BoardModelTest.java	Tue Sep 24 22:28:31 2013 +0200
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,537 +0,0 @@
    22.4 -/**
    22.5 - * The MIT License (MIT)
    22.6 - *
    22.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    22.8 - *
    22.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
   22.10 - * of this software and associated documentation files (the "Software"), to deal
   22.11 - * in the Software without restriction, including without limitation the rights
   22.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   22.13 - * copies of the Software, and to permit persons to whom the Software is
   22.14 - * furnished to do so, subject to the following conditions:
   22.15 - *
   22.16 - * The above copyright notice and this permission notice shall be included in
   22.17 - * all copies or substantial portions of the Software.
   22.18 - *
   22.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   22.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   22.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   22.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   22.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   22.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22.25 - * THE SOFTWARE.
   22.26 - */
   22.27 -package com.oracle.chess.client.htmljava;
   22.28 -
   22.29 -import com.oracle.chess.client.htmljava.BoardModel.PieceType;
   22.30 -import java.util.Arrays;
   22.31 -import java.util.Collections;
   22.32 -import java.util.List;
   22.33 -import static org.testng.Assert.*;
   22.34 -import org.testng.annotations.Test;
   22.35 -
   22.36 -/**
   22.37 - *
   22.38 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   22.39 - */
   22.40 -public class BoardModelTest {
   22.41 -    
   22.42 -    public BoardModelTest() {
   22.43 -    }
   22.44 -    
   22.45 -    @Test public void whiteRockLeftBottom() {
   22.46 -        Board b = Rules.createBoard();
   22.47 -        Row bottom = b.getRows().get(7);
   22.48 -        Square left = bottom.getColumns().get(0);
   22.49 -        assertEquals(left.getPiece(), PieceType.ROCK, "Rock is on bottom left square");
   22.50 -        assertEquals(left.getPieceColor(), Color.W, "It is white");
   22.51 -        assertEquals(left.getColor(), Color.B, "Square is black");
   22.52 -    }
   22.53 -
   22.54 -    @Test public void e2e4e7e6() {
   22.55 -        Board b = Rules.createBoard();
   22.56 -        b.setGameId("myId");
   22.57 -        setPlayer(b, Color.W);
   22.58 -        assertEquals(b.getTurn(), Color.W);
   22.59 -        
   22.60 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
   22.61 -        assertNotNull(e2);
   22.62 -        BoardModel.selected(b, e2);
   22.63 -        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
   22.64 -        
   22.65 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
   22.66 -        assertNotNull(e4);
   22.67 -        
   22.68 -        BoardModel.selected(b, e4);
   22.69 -        
   22.70 -        assertTrue(e4.isPending(), "e4 marked as pending move");
   22.71 -        assertNull(e2.getPiece(), "No pawn at e2");
   22.72 -
   22.73 -        // ignore all other figures than the two pawns
   22.74 -        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
   22.75 -            Collections.singletonList("Pe7"), Color.B, null
   22.76 -        );
   22.77 -
   22.78 -        assertFalse(e4.isPending(), "e4 now the move is real");
   22.79 -        assertNull(e2.getPiece(), "No pawn at e2");
   22.80 -        assertEquals(e4.getPiece(), BoardModel.PieceType.PAWN, "Pawn moved successfully");
   22.81 -        assertNull(BoardModel.findSelectedSquare(b), "No square selected");
   22.82 -        
   22.83 -        BoardModel.selected(b, e4);
   22.84 -        assertNull(BoardModel.findSelectedSquare(b), "No square selected, it is blacks turn");
   22.85 -
   22.86 -        List<Move> mvs1 = b.getMoves();
   22.87 -        assertEquals(1, mvs1.size(), "First move was made: " + mvs1);
   22.88 -        Move firstMove = mvs1.get(0);
   22.89 -        assertEquals(firstMove.getPiece(), PieceType.PAWN, "Moving with pawn");
   22.90 -        assertEquals(firstMove.getRound(), 1, "First round of moves");
   22.91 -        assertEquals(firstMove.getTurn(), Color.W, "Moved by white");
   22.92 -        assertTrue(firstMove.isWhiteMove(), "Really moved by white");
   22.93 -        
   22.94 -        assertTrue(b.isBlackTurn(), "black's turn");
   22.95 -        
   22.96 -        
   22.97 -        Square e7 = BoardModel.findSquare(b, 'E', 7);
   22.98 -        BoardModel.selected(b, e7);
   22.99 -        assertNull(BoardModel.findSelectedSquare(b), "Can't select anything when I am white player");
  22.100 -        
  22.101 -        Move blackMv = BoardModel.MoveImpl.valueOf("E7E6");
  22.102 -        BoardModel.moveUpdate(b, blackMv, 
  22.103 -            Collections.singletonList("PE4"), 
  22.104 -            Collections.singletonList("PE6"), 
  22.105 -            Color.W, null
  22.106 -        );
  22.107 -        
  22.108 -        assertNull(e7.getPiece(), "Piece has been moved");
  22.109 -        
  22.110 -        List<Move> mvs = b.getMoves();
  22.111 -        assertEquals(2, mvs.size(), "There are two moves now: " + mvs);
  22.112 -        Move secondMove = mvs.get(1);
  22.113 -        assertEquals(secondMove.getPiece(), PieceType.PAWN, "Moving with pawn");
  22.114 -        assertEquals(secondMove.getRound(), 1, "Still 1st round of moves");
  22.115 -        assertEquals(secondMove.getTurn(), Color.B, "Moved by black");
  22.116 -        assertFalse(secondMove.isWhiteMove(), "Really moved by black");
  22.117 -    }
  22.118 -
  22.119 -    @Test public void unselect() {
  22.120 -        Board b = Rules.createBoard();
  22.121 -        b.setGameId("myId");
  22.122 -        setPlayer(b, Color.W);
  22.123 -        assertEquals(b.getTurn(), Color.W);
  22.124 -        
  22.125 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.126 -        assertNotNull(e2);
  22.127 -        BoardModel.selected(b, e2);
  22.128 -        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  22.129 -        
  22.130 -        BoardModel.selected(b, e2);
  22.131 -        assertNull(BoardModel.findSelectedSquare(b), "E2 is unselected");
  22.132 -        
  22.133 -        for (Row row : b.getRows()) {
  22.134 -            for (Square s : row.getColumns()) {
  22.135 -                assertFalse(s.isAccessible(), "No square is accessible anymore: " + s);
  22.136 -            }
  22.137 -        }
  22.138 -    }
  22.139 -    
  22.140 -    @Test public void discaredMove() {
  22.141 -        Board b = Rules.createBoard();
  22.142 -        b.setGameId("myId");
  22.143 -        setPlayer(b, Color.W);
  22.144 -        assertEquals(b.getTurn(), Color.W);
  22.145 -        
  22.146 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.147 -        assertNotNull(e2);
  22.148 -        BoardModel.selected(b, e2);
  22.149 -        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  22.150 -        
  22.151 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
  22.152 -        assertNotNull(e4);
  22.153 -        
  22.154 -        BoardModel.selected(b, e4);
  22.155 -        
  22.156 -        assertTrue(e4.isPending(), "e4 marked as pending move");
  22.157 -        assertNull(e2.getPiece(), "No pawn at e2");
  22.158 -        
  22.159 -        assertEquals(b.getMoves().size(), 1, "One move recorded");
  22.160 -        assertEquals(b.getMoves().get(0), b.getPendingMove(), "Pending move is waiting");
  22.161 -
  22.162 -        // ignore all other figures than the two pawns
  22.163 -        BoardModel.moveResponse(b, "No way, can't play like this", Collections.singletonList("PE2"), 
  22.164 -            Collections.singletonList("Pe7"), Color.W, null
  22.165 -        );
  22.166 -        
  22.167 -        assertEquals(b.getAlertMessage(), "No way, can't play like this");
  22.168 -        assertNull(e4.getPiece(), "No piece on e4");
  22.169 -        assertEquals(e2.getPiece(), PieceType.PAWN, "Pawn is back");
  22.170 -        
  22.171 -        assertEquals(b.getMoves().size(), 0, "Move was discarded");
  22.172 -        assertNull(b.getPendingMove(), "No pending moves");
  22.173 -    }
  22.174 -    
  22.175 -    @Test public void cantSelectEmptySquare() {
  22.176 -        Board b = Rules.createBoard();
  22.177 -        Square e3 = BoardModel.findSquare(b, 'E', 3);
  22.178 -        assertNotNull(e3);
  22.179 -        BoardModel.selected(b, e3);
  22.180 -        assertNull(BoardModel.findSelectedSquare(b), "No square is selected");
  22.181 -    }
  22.182 -
  22.183 -    @Test public void cantTakeOwnPiece() {
  22.184 -        Board b = Rules.createBoard();
  22.185 -        setPlayer(b, Color.W);
  22.186 -        Square e1 = BoardModel.findSquare(b, 'E', 1);
  22.187 -        assertNotNull(e1);
  22.188 -        BoardModel.selected(b, e1);
  22.189 -        assertEquals(BoardModel.findSelectedSquare(b), e1, "E1 is selected");
  22.190 -        
  22.191 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.192 -        assertNotNull(e2);
  22.193 -        
  22.194 -        BoardModel.selected(b, e2);
  22.195 -        
  22.196 -        assertNotNull(e1.getPiece(), "King remains at e1");
  22.197 -        assertEquals(e2.getPiece(), BoardModel.PieceType.PAWN, "Pawn remains");
  22.198 -        assertEquals(BoardModel.findSelectedSquare(b), e2, "e2 now selected");
  22.199 -        
  22.200 -    }
  22.201 -    
  22.202 -    @Test public void knightMustMoveToF3() {
  22.203 -        Board b = Rules.createBoard();
  22.204 -        setPlayer(b, Color.W);
  22.205 -        Square g1 = BoardModel.findSquare(b, 'G', 1);
  22.206 -        BoardModel.selected(b, g1);
  22.207 -        
  22.208 -        Square f3 = BoardModel.findSquare(b, 'F', 3);
  22.209 -        assertTrue(f3.isAccessible(), "This is a field where knight can move");
  22.210 -
  22.211 -        Square g3 = BoardModel.findSquare(b, 'G', 3);
  22.212 -        assertFalse(g3.isAccessible(), "Not a place for knight");
  22.213 -
  22.214 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.215 -        assertFalse(e2.isAccessible(), "Not a place either, occupied");
  22.216 -
  22.217 -        BoardModel.selected(b, g3);
  22.218 -        
  22.219 -        assertNull(g3.getPiece(), "No figure was moved");
  22.220 -        assertTrue(g1.isSelected(), "Original square still selected");
  22.221 -        
  22.222 -        BoardModel.selected(b, f3);
  22.223 -        
  22.224 -        assertEquals(f3.getPiece(), PieceType.KNIGHT, "Moved");
  22.225 -        assertFalse(g3.isSelected(), "No longer selected");
  22.226 -    }
  22.227 -    
  22.228 -    @Test public void pawnCanTakeToSide() {
  22.229 -        Board b = Rules.createBoard();
  22.230 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.231 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
  22.232 -        Square d7 = BoardModel.findSquare(b, 'D', 7);
  22.233 -        Square d5 = BoardModel.findSquare(b, 'D', 5);
  22.234 -        
  22.235 -        BoardModel.selected(b, e2);
  22.236 -        BoardModel.selected(b, e4);
  22.237 -        
  22.238 -        // ignore all other figures than the two pawns
  22.239 -        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  22.240 -            Collections.singletonList("PD7"), Color.B, null
  22.241 -        );
  22.242 -        
  22.243 -        setPlayer(b, Color.B);
  22.244 -        
  22.245 -        BoardModel.selected(b, d7);
  22.246 -        BoardModel.selected(b, d5);
  22.247 -        
  22.248 -        // ignore all other figures than the two pawns
  22.249 -        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  22.250 -            Collections.singletonList("PD5"), Color.W, null
  22.251 -        );
  22.252 -        
  22.253 -        setPlayer(b, Color.W);
  22.254 -        
  22.255 -        BoardModel.selected(b, e4);
  22.256 -        assertTrue(d5.isAccessible(), "Can take on d5");
  22.257 -        BoardModel.selected(b, d5);
  22.258 -        assertNull(e4.getPiece(), "No pawn on e4");
  22.259 -        assertEquals(d5.getPieceColor(), Color.W, "White Pawn on d5");
  22.260 -    }
  22.261 -    
  22.262 -    @Test public void pawnCanJumpOnAnother() {
  22.263 -        Board b = Rules.createBoard();
  22.264 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.265 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
  22.266 -        Square d7 = BoardModel.findSquare(b, 'D', 7);
  22.267 -        Square d5 = BoardModel.findSquare(b, 'D', 5);
  22.268 -        Square e7 = BoardModel.findSquare(b, 'E', 7);
  22.269 -        Square e6 = BoardModel.findSquare(b, 'E', 6);
  22.270 -        Square e5 = BoardModel.findSquare(b, 'E', 5);
  22.271 -        
  22.272 -        BoardModel.selected(b, e2);
  22.273 -        BoardModel.selected(b, e4);
  22.274 -        
  22.275 -        // ignore all other figures than the three pawns
  22.276 -        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  22.277 -            Arrays.asList("PD7", "PE7"), Color.B, null
  22.278 -        );
  22.279 -        
  22.280 -        setPlayer(b, Color.B);
  22.281 -        
  22.282 -        BoardModel.selected(b, d7);
  22.283 -        BoardModel.selected(b, d5);
  22.284 -        
  22.285 -        // ignore all other figures than the three pawns
  22.286 -        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  22.287 -            Arrays.asList("PD5", "PE7"), Color.W, null
  22.288 -        );
  22.289 -        
  22.290 -        setPlayer(b, Color.W);
  22.291 -        
  22.292 -        BoardModel.selected(b, e4);
  22.293 -        BoardModel.selected(b, e5);
  22.294 -        
  22.295 -        // ignore all other figures than the three pawns
  22.296 -        BoardModel.moveResponse(b, null, Collections.singletonList("PE5"), 
  22.297 -            Arrays.asList("PD5", "PE7"), Color.B, null
  22.298 -        );
  22.299 -        
  22.300 -        setPlayer(b, Color.B);
  22.301 -        
  22.302 -        BoardModel.selected(b, e7);
  22.303 -        assertTrue(e6.isAccessible(), "Can move by one piece");
  22.304 -        assertFalse(e5.isAccessible(), "Can't move where other pawn is");
  22.305 -    }
  22.306 -    
  22.307 -    @Test public void showFirstMove() {
  22.308 -        Board b = Rules.createBoard();
  22.309 -        setPlayer(b, Color.W);
  22.310 -        Square e2 = BoardModel.findSquare(b, 'E', 2);
  22.311 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
  22.312 -        Square d7 = BoardModel.findSquare(b, 'D', 7);
  22.313 -        Square d5 = BoardModel.findSquare(b, 'D', 5);
  22.314 -        
  22.315 -        BoardModel.selected(b, e2);
  22.316 -        BoardModel.selected(b, e4);
  22.317 -        
  22.318 -        // ignore all other figures than the two pawns
  22.319 -        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
  22.320 -            Collections.singletonList("PD7"), Color.B, null
  22.321 -        );
  22.322 -        
  22.323 -        Move blackMv = BoardModel.MoveImpl.valueOf("D7D5");
  22.324 -        BoardModel.moveUpdate(b, blackMv, 
  22.325 -            Collections.singletonList("PE4"), 
  22.326 -            Collections.singletonList("PD5"), 
  22.327 -            Color.W, null
  22.328 -        );
  22.329 -        
  22.330 -
  22.331 -        assertEquals(b.getMoves().size(), 2, "Two moves");
  22.332 -        BoardModel.showPosition(b, b.getMoves().get(0));
  22.333 -        
  22.334 -        assertEquals(b.getRows().size(), 8, "Still eight rows");
  22.335 -        assertEquals(b.getRows().get(0).getColumns().size(), 8, "Eight columns");
  22.336 -        
  22.337 -        assertNull(e2.getPiece(), "e2 is empty");
  22.338 -        assertEquals(e4.getPiece(), PieceType.PAWN, "e4 has pawn");
  22.339 -        assertEquals(d7.getPiece(), PieceType.PAWN, "d7 has pawn");
  22.340 -        assertNull(d5.getPiece(), "Second move is not made");
  22.341 -        assertNull(b.getTurn(), "Nobody to make a move");
  22.342 -    }
  22.343 -    
  22.344 -    @Test public void initialPositionReadFromAServer() {
  22.345 -        List<String> blacks = Arrays.asList(
  22.346 -            "Pa7",
  22.347 -            "Pb7",
  22.348 -            "Pc7",
  22.349 -            "Pd7",
  22.350 -            "Pe7",
  22.351 -            "Pf7",
  22.352 -            "Pg7",
  22.353 -            "Ph7",
  22.354 -            "Ra8",
  22.355 -            "Nb8",
  22.356 -            "Bc8",
  22.357 -            "Qd8",
  22.358 -            "Ke8",
  22.359 -            "Bf8",
  22.360 -            "Ng8",
  22.361 -            "Rh8"
  22.362 -        );
  22.363 -        List<String> whites = Arrays.asList(
  22.364 -            "Ra1",
  22.365 -            "Nb1",
  22.366 -            "Bc1",
  22.367 -            "Qd1",
  22.368 -            "Ke1",
  22.369 -            "Bf1",
  22.370 -            "Ng1",
  22.371 -            "Rh1",
  22.372 -            "Pa2",
  22.373 -            "Pb2",
  22.374 -            "Pc2",
  22.375 -            "Pd2",
  22.376 -            "Pe2",
  22.377 -            "Pf2",
  22.378 -            "Pg2",
  22.379 -            "Ph2"
  22.380 -        );
  22.381 -        
  22.382 -        Board b = Rules.createBoard();
  22.383 -        Rules.initBoard(b, whites, blacks, Color.W);
  22.384 -        
  22.385 -        Board b2 = Rules.createBoard();
  22.386 -        Rules.initBoard(b2);
  22.387 -        
  22.388 -        for (int i = 0; i < 7; i++) {
  22.389 -            for (int j = 0; j < 7; j++) {
  22.390 -                Square s = b.getRows().get(i).getColumns().get(j);
  22.391 -                Square s2 = b2.getRows().get(i).getColumns().get(j);
  22.392 -                
  22.393 -                assertEquals(s.getPiece(), s2.getPiece(), "Same piece at " + i + "/" + j);
  22.394 -                assertEquals(s.getPieceColor(), s2.getPieceColor(), "Same piece color at " + i + "/" + j);
  22.395 -            }
  22.396 -        }
  22.397 -    }
  22.398 -    
  22.399 -    @Test public void allowSmallRochade() {
  22.400 -        Board b = Rules.createBoard();
  22.401 -        setPlayer(b, Color.W);
  22.402 -        Square f1 = BoardModel.findSquare(b, 'F', 1);
  22.403 -        f1.setPiece(null);
  22.404 -        f1.setPieceColor(null);
  22.405 -        Square g1 = BoardModel.findSquare(b, 'G', 1);
  22.406 -        g1.setPiece(null);
  22.407 -        g1.setPieceColor(null);
  22.408 -        Square e1 = BoardModel.findSquare(b, 'E', 1);
  22.409 -        
  22.410 -        BoardModel.selected(b, e1);
  22.411 -        assertTrue(g1.isAccessible(), "Can do 0-0");
  22.412 -    }
  22.413 -    
  22.414 -    @Test public void allowSmallRochadeForBlack() {
  22.415 -        Board b = Rules.createBoard();
  22.416 -        setPlayer(b, Color.B);
  22.417 -        b.setTurn(Color.B);
  22.418 -        Square f8 = BoardModel.findSquare(b, 'F', 8);
  22.419 -        f8.setPiece(null);
  22.420 -        f8.setPieceColor(null);
  22.421 -        Square g8 = BoardModel.findSquare(b, 'G', 8);
  22.422 -        g8.setPiece(null);
  22.423 -        g8.setPieceColor(null);
  22.424 -        Square e8 = BoardModel.findSquare(b, 'E', 8);
  22.425 -        
  22.426 -        BoardModel.selected(b, e8);
  22.427 -        assertTrue(g8.isAccessible(), "Can do 0-0");
  22.428 -    }
  22.429 -    
  22.430 -    @Test public void disallowSmallRochadeWhenNoRock() {
  22.431 -        Board b = Rules.createBoard();
  22.432 -        setPlayer(b, Color.W);
  22.433 -        Square f1 = BoardModel.findSquare(b, 'F', 1);
  22.434 -        f1.setPiece(null);
  22.435 -        f1.setPieceColor(null);
  22.436 -        Square g1 = BoardModel.findSquare(b, 'G', 1);
  22.437 -        g1.setPiece(null);
  22.438 -        g1.setPieceColor(null);
  22.439 -        Square h1 = BoardModel.findSquare(b, 'H', 1);
  22.440 -        h1.setPiece(null);
  22.441 -        h1.setPieceColor(null);
  22.442 -        Square e1 = BoardModel.findSquare(b, 'E', 1);
  22.443 -        
  22.444 -        BoardModel.selected(b, e1);
  22.445 -        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is no rock");
  22.446 -    }
  22.447 -    
  22.448 -    @Test public void disallowSmallRochadeWhenBishop() {
  22.449 -        Board b = Rules.createBoard();
  22.450 -        setPlayer(b, Color.W);
  22.451 -        Square g1 = BoardModel.findSquare(b, 'G', 1);
  22.452 -        g1.setPiece(null);
  22.453 -        Square e1 = BoardModel.findSquare(b, 'E', 1);
  22.454 -        
  22.455 -        BoardModel.selected(b, e1);
  22.456 -        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is bishop");
  22.457 -    }
  22.458 -
  22.459 -    @Test public void disallowSmallRochadeWhenKnight() {
  22.460 -        Board b = Rules.createBoard();
  22.461 -        setPlayer(b, Color.W);
  22.462 -        Square f1 = BoardModel.findSquare(b, 'F', 1);
  22.463 -        f1.setPiece(null);
  22.464 -        Square e1 = BoardModel.findSquare(b, 'E', 1);
  22.465 -        
  22.466 -        BoardModel.selected(b, e1);
  22.467 -        assertFalse(f1.isAccessible(), "Cannot do 0-0 when there is knight");
  22.468 -    }
  22.469 -    
  22.470 -    @Test public void allowBigRochadeForBlack() {
  22.471 -        Board b = Rules.createBoard();
  22.472 -        setPlayer(b, Color.B);
  22.473 -        b.setTurn(Color.B);
  22.474 -        Square b8 = BoardModel.findSquare(b, 'B', 8);
  22.475 -        b8.setPiece(null);
  22.476 -        b8.setPieceColor(null);
  22.477 -        Square c8 = BoardModel.findSquare(b, 'C', 8);
  22.478 -        c8.setPiece(null);
  22.479 -        c8.setPieceColor(null);
  22.480 -        Square d8 = BoardModel.findSquare(b, 'D', 8);
  22.481 -        d8.setPiece(null);
  22.482 -        d8.setPieceColor(null);
  22.483 -        Square e8 = BoardModel.findSquare(b, 'E', 8);
  22.484 -        
  22.485 -        BoardModel.selected(b, e8);
  22.486 -        assertTrue(c8.isAccessible(), "Can do 0-0-0");
  22.487 -    }
  22.488 -    
  22.489 -    @Test public void enPassant() {
  22.490 -        Board b = Rules.createBoard();
  22.491 -        setPlayer(b, Color.B);
  22.492 -        b.setTurn(Color.B);
  22.493 -
  22.494 -        Square e7 = BoardModel.findSquare(b, 'E', 7);
  22.495 -        Square e4 = BoardModel.findSquare(b, 'E', 4);
  22.496 -        movePiece(e7, e4);
  22.497 -        
  22.498 -        Move move = new Move();
  22.499 -        move.setFrom(position('D', 2));
  22.500 -        move.setTo(position('D', 4));
  22.501 -        move.setPiece(PieceType.PAWN);
  22.502 -        b.getMoves().add(move);
  22.503 -        
  22.504 -        Square d2 = BoardModel.findSquare(b, 'D', 2);
  22.505 -        Square d4 = BoardModel.findSquare(b, 'D', 4);
  22.506 -        movePiece(d2, d4);
  22.507 -        
  22.508 -        BoardModel.selected(b, e4);
  22.509 -        
  22.510 -        Square e3 = BoardModel.findSquare(b, 'E', 3);
  22.511 -        assertTrue(e3.isAccessible(), "Obviously can move to e3");
  22.512 -        
  22.513 -        Square d3 = BoardModel.findSquare(b, 'D', 3);
  22.514 -        assertTrue(d3.isAccessible(), "Can also take on d3");
  22.515 -    }
  22.516 -
  22.517 -    private void movePiece(Square from, Square to) {
  22.518 -        to.setPiece(from.getPiece());
  22.519 -        to.setPieceColor(from.getPieceColor());
  22.520 -        from.setPiece(null);
  22.521 -        from.setPieceColor(null);
  22.522 -    }
  22.523 -
  22.524 -    private Position position(char c, int i) {
  22.525 -        Position p = new Position();
  22.526 -        p.setX(c);
  22.527 -        p.setY(i);
  22.528 -        return p;
  22.529 -    }
  22.530 -    
  22.531 -    private static void setPlayer(Board b, Color c) {
  22.532 -        b.setWhitePlayer("x");
  22.533 -        b.setBlackPlayer("y");
  22.534 -        if (c == Color.B) {
  22.535 -            b.setPlayer("y");
  22.536 -        } else {
  22.537 -            b.setPlayer("x");
  22.538 -        }
  22.539 -    }
  22.540 -}
    23.1 --- a/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java	Tue Sep 24 22:28:31 2013 +0200
    23.2 +++ b/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java	Tue Sep 24 22:37:17 2013 +0200
    23.3 @@ -23,8 +23,13 @@
    23.4   */
    23.5  package org.apidesign.html.demo.chess;
    23.6  
    23.7 -import org.apidesign.html.demo.chess.BoardModel.ColorType;
    23.8 +import org.apidesign.html.demo.chess.Color;
    23.9 +import org.apidesign.html.demo.chess.Rules;
   23.10 +import org.apidesign.html.demo.chess.BoardModel;
   23.11  import org.apidesign.html.demo.chess.BoardModel.PieceType;
   23.12 +import java.util.Arrays;
   23.13 +import java.util.Collections;
   23.14 +import java.util.List;
   23.15  import static org.testng.Assert.*;
   23.16  import org.testng.annotations.Test;
   23.17  
   23.18 @@ -36,11 +41,21 @@
   23.19      
   23.20      public BoardModelTest() {
   23.21      }
   23.22 -
   23.23 +    
   23.24 +    @Test public void whiteRockLeftBottom() {
   23.25 +        Board b = Rules.createBoard();
   23.26 +        Row bottom = b.getRows().get(7);
   23.27 +        Square left = bottom.getColumns().get(0);
   23.28 +        assertEquals(left.getPiece(), PieceType.ROCK, "Rock is on bottom left square");
   23.29 +        assertEquals(left.getPieceColor(), Color.W, "It is white");
   23.30 +        assertEquals(left.getColor(), Color.B, "Square is black");
   23.31 +    }
   23.32  
   23.33      @Test public void e2e4e7e6() {
   23.34 -        Board b = BoardModel.createBoard();
   23.35 -        assertEquals(b.getTurn(), ColorType.WHITE);
   23.36 +        Board b = Rules.createBoard();
   23.37 +        b.setGameId("myId");
   23.38 +        setPlayer(b, Color.W);
   23.39 +        assertEquals(b.getTurn(), Color.W);
   23.40          
   23.41          Square e2 = BoardModel.findSquare(b, 'E', 2);
   23.42          assertNotNull(e2);
   23.43 @@ -52,26 +67,113 @@
   23.44          
   23.45          BoardModel.selected(b, e4);
   23.46          
   23.47 +        assertTrue(e4.isPending(), "e4 marked as pending move");
   23.48 +        assertNull(e2.getPiece(), "No pawn at e2");
   23.49 +
   23.50 +        // ignore all other figures than the two pawns
   23.51 +        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
   23.52 +            Collections.singletonList("Pe7"), Color.B, null
   23.53 +        );
   23.54 +
   23.55 +        assertFalse(e4.isPending(), "e4 now the move is real");
   23.56          assertNull(e2.getPiece(), "No pawn at e2");
   23.57          assertEquals(e4.getPiece(), BoardModel.PieceType.PAWN, "Pawn moved successfully");
   23.58          assertNull(BoardModel.findSelectedSquare(b), "No square selected");
   23.59          
   23.60          BoardModel.selected(b, e4);
   23.61          assertNull(BoardModel.findSelectedSquare(b), "No square selected, it is blacks turn");
   23.62 +
   23.63 +        List<Move> mvs1 = b.getMoves();
   23.64 +        assertEquals(1, mvs1.size(), "First move was made: " + mvs1);
   23.65 +        Move firstMove = mvs1.get(0);
   23.66 +        assertEquals(firstMove.getPiece(), PieceType.PAWN, "Moving with pawn");
   23.67 +        assertEquals(firstMove.getRound(), 1, "First round of moves");
   23.68 +        assertEquals(firstMove.getTurn(), Color.W, "Moved by white");
   23.69 +        assertTrue(firstMove.isWhiteMove(), "Really moved by white");
   23.70          
   23.71          assertTrue(b.isBlackTurn(), "black's turn");
   23.72          
   23.73          
   23.74          Square e7 = BoardModel.findSquare(b, 'E', 7);
   23.75          BoardModel.selected(b, e7);
   23.76 -        assertEquals(BoardModel.findSelectedSquare(b), e7);
   23.77 +        assertNull(BoardModel.findSelectedSquare(b), "Can't select anything when I am white player");
   23.78          
   23.79 -        BoardModel.selected(b, BoardModel.findSquare(b, 'E', 6));
   23.80 +        Move blackMv = BoardModel.MoveImpl.valueOf("E7E6");
   23.81 +        BoardModel.moveUpdate(b, blackMv, 
   23.82 +            Collections.singletonList("PE4"), 
   23.83 +            Collections.singletonList("PE6"), 
   23.84 +            Color.W, null
   23.85 +        );
   23.86 +        
   23.87          assertNull(e7.getPiece(), "Piece has been moved");
   23.88 +        
   23.89 +        List<Move> mvs = b.getMoves();
   23.90 +        assertEquals(2, mvs.size(), "There are two moves now: " + mvs);
   23.91 +        Move secondMove = mvs.get(1);
   23.92 +        assertEquals(secondMove.getPiece(), PieceType.PAWN, "Moving with pawn");
   23.93 +        assertEquals(secondMove.getRound(), 1, "Still 1st round of moves");
   23.94 +        assertEquals(secondMove.getTurn(), Color.B, "Moved by black");
   23.95 +        assertFalse(secondMove.isWhiteMove(), "Really moved by black");
   23.96 +    }
   23.97 +
   23.98 +    @Test public void unselect() {
   23.99 +        Board b = Rules.createBoard();
  23.100 +        b.setGameId("myId");
  23.101 +        setPlayer(b, Color.W);
  23.102 +        assertEquals(b.getTurn(), Color.W);
  23.103 +        
  23.104 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  23.105 +        assertNotNull(e2);
  23.106 +        BoardModel.selected(b, e2);
  23.107 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  23.108 +        
  23.109 +        BoardModel.selected(b, e2);
  23.110 +        assertNull(BoardModel.findSelectedSquare(b), "E2 is unselected");
  23.111 +        
  23.112 +        for (Row row : b.getRows()) {
  23.113 +            for (Square s : row.getColumns()) {
  23.114 +                assertFalse(s.isAccessible(), "No square is accessible anymore: " + s);
  23.115 +            }
  23.116 +        }
  23.117 +    }
  23.118 +    
  23.119 +    @Test public void discaredMove() {
  23.120 +        Board b = Rules.createBoard();
  23.121 +        b.setGameId("myId");
  23.122 +        setPlayer(b, Color.W);
  23.123 +        assertEquals(b.getTurn(), Color.W);
  23.124 +        
  23.125 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  23.126 +        assertNotNull(e2);
  23.127 +        BoardModel.selected(b, e2);
  23.128 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  23.129 +        
  23.130 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  23.131 +        assertNotNull(e4);
  23.132 +        
  23.133 +        BoardModel.selected(b, e4);
  23.134 +        
  23.135 +        assertTrue(e4.isPending(), "e4 marked as pending move");
  23.136 +        assertNull(e2.getPiece(), "No pawn at e2");
  23.137 +        
  23.138 +        assertEquals(b.getMoves().size(), 1, "One move recorded");
  23.139 +        assertEquals(b.getMoves().get(0), b.getPendingMove(), "Pending move is waiting");
  23.140 +
  23.141 +        // ignore all other figures than the two pawns
  23.142 +        BoardModel.moveResponse(b, "No way, can't play like this", Collections.singletonList("PE2"), 
  23.143 +            Collections.singletonList("Pe7"), Color.W, null
  23.144 +        );
  23.145 +        
  23.146 +        assertEquals(b.getAlertMessage(), "No way, can't play like this");
  23.147 +        assertNull(e4.getPiece(), "No piece on e4");
  23.148 +        assertEquals(e2.getPiece(), PieceType.PAWN, "Pawn is back");
  23.149 +        
  23.150 +        assertEquals(b.getMoves().size(), 0, "Move was discarded");
  23.151 +        assertNull(b.getPendingMove(), "No pending moves");
  23.152      }
  23.153      
  23.154      @Test public void cantSelectEmptySquare() {
  23.155 -        Board b = BoardModel.createBoard();
  23.156 +        Board b = Rules.createBoard();
  23.157          Square e3 = BoardModel.findSquare(b, 'E', 3);
  23.158          assertNotNull(e3);
  23.159          BoardModel.selected(b, e3);
  23.160 @@ -79,7 +181,8 @@
  23.161      }
  23.162  
  23.163      @Test public void cantTakeOwnPiece() {
  23.164 -        Board b = BoardModel.createBoard();
  23.165 +        Board b = Rules.createBoard();
  23.166 +        setPlayer(b, Color.W);
  23.167          Square e1 = BoardModel.findSquare(b, 'E', 1);
  23.168          assertNotNull(e1);
  23.169          BoardModel.selected(b, e1);
  23.170 @@ -97,7 +200,8 @@
  23.171      }
  23.172      
  23.173      @Test public void knightMustMoveToF3() {
  23.174 -        Board b = BoardModel.createBoard();
  23.175 +        Board b = Rules.createBoard();
  23.176 +        setPlayer(b, Color.W);
  23.177          Square g1 = BoardModel.findSquare(b, 'G', 1);
  23.178          BoardModel.selected(b, g1);
  23.179          
  23.180 @@ -122,7 +226,7 @@
  23.181      }
  23.182      
  23.183      @Test public void pawnCanTakeToSide() {
  23.184 -        Board b = BoardModel.createBoard();
  23.185 +        Board b = Rules.createBoard();
  23.186          Square e2 = BoardModel.findSquare(b, 'E', 2);
  23.187          Square e4 = BoardModel.findSquare(b, 'E', 4);
  23.188          Square d7 = BoardModel.findSquare(b, 'D', 7);
  23.189 @@ -130,13 +234,307 @@
  23.190          
  23.191          BoardModel.selected(b, e2);
  23.192          BoardModel.selected(b, e4);
  23.193 +        
  23.194 +        // ignore all other figures than the two pawns
  23.195 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  23.196 +            Collections.singletonList("PD7"), Color.B, null
  23.197 +        );
  23.198 +        
  23.199 +        setPlayer(b, Color.B);
  23.200 +        
  23.201          BoardModel.selected(b, d7);
  23.202          BoardModel.selected(b, d5);
  23.203          
  23.204 +        // ignore all other figures than the two pawns
  23.205 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  23.206 +            Collections.singletonList("PD5"), Color.W, null
  23.207 +        );
  23.208 +        
  23.209 +        setPlayer(b, Color.W);
  23.210 +        
  23.211          BoardModel.selected(b, e4);
  23.212          assertTrue(d5.isAccessible(), "Can take on d5");
  23.213          BoardModel.selected(b, d5);
  23.214          assertNull(e4.getPiece(), "No pawn on e4");
  23.215 -        assertEquals(d5.getPieceColor(), ColorType.WHITE, "White Pawn on d5");
  23.216 +        assertEquals(d5.getPieceColor(), Color.W, "White Pawn on d5");
  23.217 +    }
  23.218 +    
  23.219 +    @Test public void pawnCanJumpOnAnother() {
  23.220 +        Board b = Rules.createBoard();
  23.221 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  23.222 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  23.223 +        Square d7 = BoardModel.findSquare(b, 'D', 7);
  23.224 +        Square d5 = BoardModel.findSquare(b, 'D', 5);
  23.225 +        Square e7 = BoardModel.findSquare(b, 'E', 7);
  23.226 +        Square e6 = BoardModel.findSquare(b, 'E', 6);
  23.227 +        Square e5 = BoardModel.findSquare(b, 'E', 5);
  23.228 +        
  23.229 +        BoardModel.selected(b, e2);
  23.230 +        BoardModel.selected(b, e4);
  23.231 +        
  23.232 +        // ignore all other figures than the three pawns
  23.233 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  23.234 +            Arrays.asList("PD7", "PE7"), Color.B, null
  23.235 +        );
  23.236 +        
  23.237 +        setPlayer(b, Color.B);
  23.238 +        
  23.239 +        BoardModel.selected(b, d7);
  23.240 +        BoardModel.selected(b, d5);
  23.241 +        
  23.242 +        // ignore all other figures than the three pawns
  23.243 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  23.244 +            Arrays.asList("PD5", "PE7"), Color.W, null
  23.245 +        );
  23.246 +        
  23.247 +        setPlayer(b, Color.W);
  23.248 +        
  23.249 +        BoardModel.selected(b, e4);
  23.250 +        BoardModel.selected(b, e5);
  23.251 +        
  23.252 +        // ignore all other figures than the three pawns
  23.253 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE5"), 
  23.254 +            Arrays.asList("PD5", "PE7"), Color.B, null
  23.255 +        );
  23.256 +        
  23.257 +        setPlayer(b, Color.B);
  23.258 +        
  23.259 +        BoardModel.selected(b, e7);
  23.260 +        assertTrue(e6.isAccessible(), "Can move by one piece");
  23.261 +        assertFalse(e5.isAccessible(), "Can't move where other pawn is");
  23.262 +    }
  23.263 +    
  23.264 +    @Test public void showFirstMove() {
  23.265 +        Board b = Rules.createBoard();
  23.266 +        setPlayer(b, Color.W);
  23.267 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  23.268 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  23.269 +        Square d7 = BoardModel.findSquare(b, 'D', 7);
  23.270 +        Square d5 = BoardModel.findSquare(b, 'D', 5);
  23.271 +        
  23.272 +        BoardModel.selected(b, e2);
  23.273 +        BoardModel.selected(b, e4);
  23.274 +        
  23.275 +        // ignore all other figures than the two pawns
  23.276 +        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
  23.277 +            Collections.singletonList("PD7"), Color.B, null
  23.278 +        );
  23.279 +        
  23.280 +        Move blackMv = BoardModel.MoveImpl.valueOf("D7D5");
  23.281 +        BoardModel.moveUpdate(b, blackMv, 
  23.282 +            Collections.singletonList("PE4"), 
  23.283 +            Collections.singletonList("PD5"), 
  23.284 +            Color.W, null
  23.285 +        );
  23.286 +        
  23.287 +
  23.288 +        assertEquals(b.getMoves().size(), 2, "Two moves");
  23.289 +        BoardModel.showPosition(b, b.getMoves().get(0));
  23.290 +        
  23.291 +        assertEquals(b.getRows().size(), 8, "Still eight rows");
  23.292 +        assertEquals(b.getRows().get(0).getColumns().size(), 8, "Eight columns");
  23.293 +        
  23.294 +        assertNull(e2.getPiece(), "e2 is empty");
  23.295 +        assertEquals(e4.getPiece(), PieceType.PAWN, "e4 has pawn");
  23.296 +        assertEquals(d7.getPiece(), PieceType.PAWN, "d7 has pawn");
  23.297 +        assertNull(d5.getPiece(), "Second move is not made");
  23.298 +        assertNull(b.getTurn(), "Nobody to make a move");
  23.299 +    }
  23.300 +    
  23.301 +    @Test public void initialPositionReadFromAServer() {
  23.302 +        List<String> blacks = Arrays.asList(
  23.303 +            "Pa7",
  23.304 +            "Pb7",
  23.305 +            "Pc7",
  23.306 +            "Pd7",
  23.307 +            "Pe7",
  23.308 +            "Pf7",
  23.309 +            "Pg7",
  23.310 +            "Ph7",
  23.311 +            "Ra8",
  23.312 +            "Nb8",
  23.313 +            "Bc8",
  23.314 +            "Qd8",
  23.315 +            "Ke8",
  23.316 +            "Bf8",
  23.317 +            "Ng8",
  23.318 +            "Rh8"
  23.319 +        );
  23.320 +        List<String> whites = Arrays.asList(
  23.321 +            "Ra1",
  23.322 +            "Nb1",
  23.323 +            "Bc1",
  23.324 +            "Qd1",
  23.325 +            "Ke1",
  23.326 +            "Bf1",
  23.327 +            "Ng1",
  23.328 +            "Rh1",
  23.329 +            "Pa2",
  23.330 +            "Pb2",
  23.331 +            "Pc2",
  23.332 +            "Pd2",
  23.333 +            "Pe2",
  23.334 +            "Pf2",
  23.335 +            "Pg2",
  23.336 +            "Ph2"
  23.337 +        );
  23.338 +        
  23.339 +        Board b = Rules.createBoard();
  23.340 +        Rules.initBoard(b, whites, blacks, Color.W);
  23.341 +        
  23.342 +        Board b2 = Rules.createBoard();
  23.343 +        Rules.initBoard(b2);
  23.344 +        
  23.345 +        for (int i = 0; i < 7; i++) {
  23.346 +            for (int j = 0; j < 7; j++) {
  23.347 +                Square s = b.getRows().get(i).getColumns().get(j);
  23.348 +                Square s2 = b2.getRows().get(i).getColumns().get(j);
  23.349 +                
  23.350 +                assertEquals(s.getPiece(), s2.getPiece(), "Same piece at " + i + "/" + j);
  23.351 +                assertEquals(s.getPieceColor(), s2.getPieceColor(), "Same piece color at " + i + "/" + j);
  23.352 +            }
  23.353 +        }
  23.354 +    }
  23.355 +    
  23.356 +    @Test public void allowSmallRochade() {
  23.357 +        Board b = Rules.createBoard();
  23.358 +        setPlayer(b, Color.W);
  23.359 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  23.360 +        f1.setPiece(null);
  23.361 +        f1.setPieceColor(null);
  23.362 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  23.363 +        g1.setPiece(null);
  23.364 +        g1.setPieceColor(null);
  23.365 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  23.366 +        
  23.367 +        BoardModel.selected(b, e1);
  23.368 +        assertTrue(g1.isAccessible(), "Can do 0-0");
  23.369 +    }
  23.370 +    
  23.371 +    @Test public void allowSmallRochadeForBlack() {
  23.372 +        Board b = Rules.createBoard();
  23.373 +        setPlayer(b, Color.B);
  23.374 +        b.setTurn(Color.B);
  23.375 +        Square f8 = BoardModel.findSquare(b, 'F', 8);
  23.376 +        f8.setPiece(null);
  23.377 +        f8.setPieceColor(null);
  23.378 +        Square g8 = BoardModel.findSquare(b, 'G', 8);
  23.379 +        g8.setPiece(null);
  23.380 +        g8.setPieceColor(null);
  23.381 +        Square e8 = BoardModel.findSquare(b, 'E', 8);
  23.382 +        
  23.383 +        BoardModel.selected(b, e8);
  23.384 +        assertTrue(g8.isAccessible(), "Can do 0-0");
  23.385 +    }
  23.386 +    
  23.387 +    @Test public void disallowSmallRochadeWhenNoRock() {
  23.388 +        Board b = Rules.createBoard();
  23.389 +        setPlayer(b, Color.W);
  23.390 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  23.391 +        f1.setPiece(null);
  23.392 +        f1.setPieceColor(null);
  23.393 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  23.394 +        g1.setPiece(null);
  23.395 +        g1.setPieceColor(null);
  23.396 +        Square h1 = BoardModel.findSquare(b, 'H', 1);
  23.397 +        h1.setPiece(null);
  23.398 +        h1.setPieceColor(null);
  23.399 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  23.400 +        
  23.401 +        BoardModel.selected(b, e1);
  23.402 +        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is no rock");
  23.403 +    }
  23.404 +    
  23.405 +    @Test public void disallowSmallRochadeWhenBishop() {
  23.406 +        Board b = Rules.createBoard();
  23.407 +        setPlayer(b, Color.W);
  23.408 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  23.409 +        g1.setPiece(null);
  23.410 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  23.411 +        
  23.412 +        BoardModel.selected(b, e1);
  23.413 +        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is bishop");
  23.414 +    }
  23.415 +
  23.416 +    @Test public void disallowSmallRochadeWhenKnight() {
  23.417 +        Board b = Rules.createBoard();
  23.418 +        setPlayer(b, Color.W);
  23.419 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  23.420 +        f1.setPiece(null);
  23.421 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  23.422 +        
  23.423 +        BoardModel.selected(b, e1);
  23.424 +        assertFalse(f1.isAccessible(), "Cannot do 0-0 when there is knight");
  23.425 +    }
  23.426 +    
  23.427 +    @Test public void allowBigRochadeForBlack() {
  23.428 +        Board b = Rules.createBoard();
  23.429 +        setPlayer(b, Color.B);
  23.430 +        b.setTurn(Color.B);
  23.431 +        Square b8 = BoardModel.findSquare(b, 'B', 8);
  23.432 +        b8.setPiece(null);
  23.433 +        b8.setPieceColor(null);
  23.434 +        Square c8 = BoardModel.findSquare(b, 'C', 8);
  23.435 +        c8.setPiece(null);
  23.436 +        c8.setPieceColor(null);
  23.437 +        Square d8 = BoardModel.findSquare(b, 'D', 8);
  23.438 +        d8.setPiece(null);
  23.439 +        d8.setPieceColor(null);
  23.440 +        Square e8 = BoardModel.findSquare(b, 'E', 8);
  23.441 +        
  23.442 +        BoardModel.selected(b, e8);
  23.443 +        assertTrue(c8.isAccessible(), "Can do 0-0-0");
  23.444 +    }
  23.445 +    
  23.446 +    @Test public void enPassant() {
  23.447 +        Board b = Rules.createBoard();
  23.448 +        setPlayer(b, Color.B);
  23.449 +        b.setTurn(Color.B);
  23.450 +
  23.451 +        Square e7 = BoardModel.findSquare(b, 'E', 7);
  23.452 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  23.453 +        movePiece(e7, e4);
  23.454 +        
  23.455 +        Move move = new Move();
  23.456 +        move.setFrom(position('D', 2));
  23.457 +        move.setTo(position('D', 4));
  23.458 +        move.setPiece(PieceType.PAWN);
  23.459 +        b.getMoves().add(move);
  23.460 +        
  23.461 +        Square d2 = BoardModel.findSquare(b, 'D', 2);
  23.462 +        Square d4 = BoardModel.findSquare(b, 'D', 4);
  23.463 +        movePiece(d2, d4);
  23.464 +        
  23.465 +        BoardModel.selected(b, e4);
  23.466 +        
  23.467 +        Square e3 = BoardModel.findSquare(b, 'E', 3);
  23.468 +        assertTrue(e3.isAccessible(), "Obviously can move to e3");
  23.469 +        
  23.470 +        Square d3 = BoardModel.findSquare(b, 'D', 3);
  23.471 +        assertTrue(d3.isAccessible(), "Can also take on d3");
  23.472 +    }
  23.473 +
  23.474 +    private void movePiece(Square from, Square to) {
  23.475 +        to.setPiece(from.getPiece());
  23.476 +        to.setPieceColor(from.getPieceColor());
  23.477 +        from.setPiece(null);
  23.478 +        from.setPieceColor(null);
  23.479 +    }
  23.480 +
  23.481 +    private Position position(char c, int i) {
  23.482 +        Position p = new Position();
  23.483 +        p.setX(c);
  23.484 +        p.setY(i);
  23.485 +        return p;
  23.486 +    }
  23.487 +    
  23.488 +    private static void setPlayer(Board b, Color c) {
  23.489 +        b.setWhitePlayer("x");
  23.490 +        b.setBlackPlayer("y");
  23.491 +        if (c == Color.B) {
  23.492 +            b.setPlayer("y");
  23.493 +        } else {
  23.494 +            b.setPlayer("x");
  23.495 +        }
  23.496      }
  23.497  }