chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 24 Sep 2013 22:20:24 +0200
branchchess
changeset 49 945fbfff28f3
permissions -rw-r--r--
Advanced version of the chess game
jaroslav@49
     1
/**
jaroslav@49
     2
 * The MIT License (MIT)
jaroslav@49
     3
 *
jaroslav@49
     4
 * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@49
     5
 *
jaroslav@49
     6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
jaroslav@49
     7
 * of this software and associated documentation files (the "Software"), to deal
jaroslav@49
     8
 * in the Software without restriction, including without limitation the rights
jaroslav@49
     9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jaroslav@49
    10
 * copies of the Software, and to permit persons to whom the Software is
jaroslav@49
    11
 * furnished to do so, subject to the following conditions:
jaroslav@49
    12
 *
jaroslav@49
    13
 * The above copyright notice and this permission notice shall be included in
jaroslav@49
    14
 * all copies or substantial portions of the Software.
jaroslav@49
    15
 *
jaroslav@49
    16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jaroslav@49
    17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jaroslav@49
    18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jaroslav@49
    19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jaroslav@49
    20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jaroslav@49
    21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jaroslav@49
    22
 * THE SOFTWARE.
jaroslav@49
    23
 */
jaroslav@49
    24
package com.oracle.chess.client.htmljava;
jaroslav@49
    25
jaroslav@49
    26
import java.io.IOException;
jaroslav@49
    27
import java.net.URISyntaxException;
jaroslav@49
    28
import java.util.HashSet;
jaroslav@49
    29
import java.util.List;
jaroslav@49
    30
import java.util.Set;
jaroslav@49
    31
import java.util.logging.Level;
jaroslav@49
    32
import java.util.logging.Logger;
jaroslav@49
    33
import net.java.html.json.ComputedProperty;
jaroslav@49
    34
import net.java.html.json.Function;
jaroslav@49
    35
import net.java.html.json.Model;
jaroslav@49
    36
import net.java.html.json.ModelOperation;
jaroslav@49
    37
import net.java.html.json.OnPropertyChange;
jaroslav@49
    38
import net.java.html.json.OnReceive;
jaroslav@49
    39
import net.java.html.json.Property;
jaroslav@49
    40
jaroslav@49
    41
/**
jaroslav@49
    42
 *
jaroslav@49
    43
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@49
    44
 */
jaroslav@49
    45
@Model(className = "UI", properties = {
jaroslav@49
    46
    @Property(name = "status", type = String.class),
jaroslav@49
    47
    @Property(name = "selectedGameId", type = String.class),
jaroslav@49
    48
    @Property(name = "boards", type = Board.class, array = true),
jaroslav@49
    49
    @Property(name = "viewGames", type = Games.class),
jaroslav@49
    50
    @Property(name = "settings", type = Settings.class),
jaroslav@49
    51
    @Property(name = "connected", type = boolean.class),
jaroslav@49
    52
    @Property(name = "disconnected", type = boolean.class),
jaroslav@49
    53
})
jaroslav@49
    54
public class UIModel {
jaroslav@49
    55
    private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
jaroslav@49
    56
    
jaroslav@49
    57
    @ComputedProperty static boolean settingsActive(String selectedGameId) {
jaroslav@49
    58
        return selectedGameId == null;
jaroslav@49
    59
    }
jaroslav@49
    60
    
jaroslav@49
    61
    @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
jaroslav@49
    62
        return selectedGameId == null && connected;
jaroslav@49
    63
    }
jaroslav@49
    64
    
jaroslav@49
    65
    @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
jaroslav@49
    66
        Board active = null;
jaroslav@49
    67
        for (Board b : boards) {
jaroslav@49
    68
            b.setActive(false);
jaroslav@49
    69
            if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
jaroslav@49
    70
                b.setActive(true);
jaroslav@49
    71
                active = b;
jaroslav@49
    72
            }
jaroslav@49
    73
        }
jaroslav@49
    74
        return active;
jaroslav@49
    75
    }
jaroslav@49
    76
    
jaroslav@49
    77
    @Function static void activateGame(UI m, Board data) {
jaroslav@49
    78
        m.setSelectedGameId(data.getGameId());
jaroslav@49
    79
    }
jaroslav@49
    80
jaroslav@49
    81
    @Function static void activateSettings(UI m) {
jaroslav@49
    82
        m.setSelectedGameId(null);
jaroslav@49
    83
        refreshGames(m);
jaroslav@49
    84
    }
jaroslav@49
    85
    
jaroslav@49
    86
    @Function static void createGame(UI u) {
jaroslav@49
    87
        u.setStatus("Creating new game...");
jaroslav@49
    88
        Request r = new Request();
jaroslav@49
    89
        r.setMsg(MsgType.CreateGame);
jaroslav@49
    90
        r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
jaroslav@49
    91
        u.sendMsg(r);
jaroslav@49
    92
    }
jaroslav@49
    93
jaroslav@49
    94
    @ModelOperation @Function static void refreshGames(UI u) {
jaroslav@49
    95
        u.setStatus("Refreshing games...");
jaroslav@49
    96
        Request r = new Request();
jaroslav@49
    97
        r.setMsg(MsgType.QueryGames);
jaroslav@49
    98
        u.sendMsg(r);
jaroslav@49
    99
    }
jaroslav@49
   100
    
jaroslav@49
   101
    @ModelOperation static void sendMsg(UI ui, Request r) {
jaroslav@49
   102
        final Settings sttngs = ui.getSettings();
jaroslav@49
   103
        
jaroslav@49
   104
        String url = sttngs.getUrl();
jaroslav@49
   105
        r.setUsername(sttngs.getUsername());
jaroslav@49
   106
        r.setPassword(sttngs.getPassword());
jaroslav@49
   107
        
jaroslav@49
   108
        LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
jaroslav@49
   109
        ui.queryServer(url, r);
jaroslav@49
   110
    }
jaroslav@49
   111
    
jaroslav@49
   112
    
jaroslav@49
   113
    @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError") 
jaroslav@49
   114
    static void queryServer(UI ui, Response r) {
jaroslav@49
   115
        LOG.log(Level.INFO, "Received {0}", r);
jaroslav@49
   116
        if (r == null) {
jaroslav@49
   117
            ui.setDisconnected(false);
jaroslav@49
   118
            verifyLogin(ui);
jaroslav@49
   119
            return;
jaroslav@49
   120
        }
jaroslav@49
   121
        SWITCH: switch (MsgType.forResponse(r.getMsg())) {
jaroslav@49
   122
            case CheckCredentials: {
jaroslav@49
   123
                switch (r.getCheck()) {
jaroslav@49
   124
                    case NOT_REGISTERED:
jaroslav@49
   125
                    case VALID:
jaroslav@49
   126
                        ui.setConnected(true);
jaroslav@49
   127
                        ui.refreshGames();
jaroslav@49
   128
                        ui.setStatus("Connected.");
jaroslav@49
   129
                        return;
jaroslav@49
   130
                    case INVALID:
jaroslav@49
   131
                        ui.setStatus("Password is invalid");
jaroslav@49
   132
                        break;
jaroslav@49
   133
                }
jaroslav@49
   134
                disconnect(ui);
jaroslav@49
   135
            }
jaroslav@49
   136
                
jaroslav@49
   137
            case QueryGames:
jaroslav@49
   138
                ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
jaroslav@49
   139
                ui.setStatus("");
jaroslav@49
   140
                break;
jaroslav@49
   141
            case CreateGame: {
jaroslav@49
   142
                ui.setStatus("Game " + r + " created");
jaroslav@49
   143
                final Board b = Rules.createBoard();
jaroslav@49
   144
                Rules.initBoard(
jaroslav@49
   145
                    b, r.getBoard().getWhites(),
jaroslav@49
   146
                    r.getBoard().getBlacks(),
jaroslav@49
   147
                    r.getTurn()
jaroslav@49
   148
                );
jaroslav@49
   149
                b.setGameId(r.getGameId());
jaroslav@49
   150
                b.setWhitePlayer(r.getWhitePlayer());
jaroslav@49
   151
                b.setBlackPlayer(r.getBlackPlayer());
jaroslav@49
   152
                b.setPlayer(ui.getSettings().getUsername());
jaroslav@49
   153
                b.updateSummary(r.getSummary());
jaroslav@49
   154
                ui.getBoards().add(b);
jaroslav@49
   155
                ui.setSelectedGameId(r.getGameId());
jaroslav@49
   156
                UIModel.refreshGames(ui);
jaroslav@49
   157
                break;
jaroslav@49
   158
            }
jaroslav@49
   159
            case SendMove: {
jaroslav@49
   160
                if (r.getBoard() == null) {
jaroslav@49
   161
                    throw new NullPointerException("No board in " + r);
jaroslav@49
   162
                }
jaroslav@49
   163
                final Board b = findBoard(ui, r.getGameId());
jaroslav@49
   164
                if (b == null) {
jaroslav@49
   165
                    break;
jaroslav@49
   166
                }
jaroslav@49
   167
                b.updateSummary(r.getSummary());
jaroslav@49
   168
                final String errMsg = r.getError() == null ? null : r.getError().getMessage();
jaroslav@49
   169
                final List<String> whites = r.getBoard().getWhites();
jaroslav@49
   170
                final List<String> blacks = r.getBoard().getBlacks();
jaroslav@49
   171
                final Color turn = r.getNextTurn();
jaroslav@49
   172
                BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
jaroslav@49
   173
                break;
jaroslav@49
   174
            }
jaroslav@49
   175
            case JoinGame: {
jaroslav@49
   176
                Board b;
jaroslav@49
   177
                if ((b = findBoard(ui, r.getGameId())) != null) {
jaroslav@49
   178
                    b.setWhitePlayer(r.getWhitePlayer());
jaroslav@49
   179
                    b.setBlackPlayer(r.getBlackPlayer());
jaroslav@49
   180
                    b.setPlayer(ui.getSettings().getUsername());
jaroslav@49
   181
                    b.updateSummary(r.getSummary());
jaroslav@49
   182
                    ui.setSelectedGameId(r.getGameId());
jaroslav@49
   183
                    break SWITCH;
jaroslav@49
   184
                }
jaroslav@49
   185
                ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
jaroslav@49
   186
                b = Rules.createBoard();
jaroslav@49
   187
                Rules.initBoard(
jaroslav@49
   188
                    b, r.getBoard().getWhites(),
jaroslav@49
   189
                    r.getBoard().getBlacks(),
jaroslav@49
   190
                    r.getTurn()
jaroslav@49
   191
                );
jaroslav@49
   192
                b.setGameId(r.getGameId());
jaroslav@49
   193
                b.setWhitePlayer(r.getWhitePlayer());
jaroslav@49
   194
                b.setBlackPlayer(r.getBlackPlayer());
jaroslav@49
   195
                b.setPlayer(ui.getSettings().getUsername());
jaroslav@49
   196
                b.updateSummary(r.getSummary());
jaroslav@49
   197
                if (r.getColor() == Color.B) {
jaroslav@49
   198
                    BoardModel.rotateBoard(b);
jaroslav@49
   199
                }
jaroslav@49
   200
                if (r.getMoves() != null) {
jaroslav@49
   201
                    for (String move : r.getMoves()) {
jaroslav@49
   202
                        Move m = BoardModel.MoveImpl.valueOf(move);
jaroslav@49
   203
                        b.getMoves().add(m);
jaroslav@49
   204
                    }
jaroslav@49
   205
                } else {
jaroslav@49
   206
                    b.getMoves().clear();
jaroslav@49
   207
                }
jaroslav@49
   208
                ui.setSelectedGameId(b.getGameId());
jaroslav@49
   209
                ui.getBoards().add(b);
jaroslav@49
   210
                break;
jaroslav@49
   211
            }
jaroslav@49
   212
            case UpdateGame: {
jaroslav@49
   213
                final Board b = findBoard(ui, r.getGameId());
jaroslav@49
   214
                if (b == null) {
jaroslav@49
   215
                    break;
jaroslav@49
   216
                }
jaroslav@49
   217
                b.updateSummary(r.getSummary());
jaroslav@49
   218
                final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
jaroslav@49
   219
                final List<String> whites = r.getBoard().getWhites();
jaroslav@49
   220
                final List<String> blacks = r.getBoard().getBlacks();
jaroslav@49
   221
                final Color turn = r.getNextTurn();
jaroslav@49
   222
                BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
jaroslav@49
   223
            }
jaroslav@49
   224
        }
jaroslav@49
   225
    }
jaroslav@49
   226
jaroslav@49
   227
jaroslav@49
   228
    private static Board findBoard(UI ui, String gameId) {
jaroslav@49
   229
        for (Board tmp : ui.getBoards()) {
jaroslav@49
   230
            if (tmp.getGameId().equals(gameId)) {
jaroslav@49
   231
                return tmp;
jaroslav@49
   232
            }
jaroslav@49
   233
        }
jaroslav@49
   234
        return null;
jaroslav@49
   235
    }
jaroslav@49
   236
    
jaroslav@49
   237
    
jaroslav@49
   238
    static void wasAnError(UI ui, Exception t) {
jaroslav@49
   239
        if (t == null) {
jaroslav@49
   240
            ui.setConnected(false);
jaroslav@49
   241
            ui.setDisconnected(true);
jaroslav@49
   242
            ui.setStatus("Disconnected.");
jaroslav@49
   243
        } else {
jaroslav@49
   244
            ui.setStatus("Error: " + t.getLocalizedMessage());
jaroslav@49
   245
        }
jaroslav@49
   246
    }
jaroslav@49
   247
    
jaroslav@49
   248
    @Function static void joinGame(UI u, Game data) {
jaroslav@49
   249
        Request r = new Request();
jaroslav@49
   250
        r.setMsg(MsgType.JoinGame);
jaroslav@49
   251
        r.setObserver(false);
jaroslav@49
   252
        r.setGameId(data.getGameId());
jaroslav@49
   253
        u.sendMsg(r);
jaroslav@49
   254
    }
jaroslav@49
   255
jaroslav@49
   256
    @Function static void observeGame(UI u, Game data) {
jaroslav@49
   257
        Request r = new Request();
jaroslav@49
   258
        r.setMsg(MsgType.JoinGame);
jaroslav@49
   259
        r.setObserver(true);
jaroslav@49
   260
        r.setGameId(data.getGameId());
jaroslav@49
   261
        u.sendMsg(r);
jaroslav@49
   262
    }
jaroslav@49
   263
jaroslav@49
   264
    private static final Set<UI> ACTIVE = new HashSet<>();
jaroslav@49
   265
    @OnPropertyChange("connected") static void clearGames(UI m) {
jaroslav@49
   266
        if (m.isDisconnected()) {
jaroslav@49
   267
            m.getBoards().clear();
jaroslav@49
   268
            ACTIVE.remove(m);
jaroslav@49
   269
        } else {
jaroslav@49
   270
            ACTIVE.add(m);
jaroslav@49
   271
        }
jaroslav@49
   272
    }
jaroslav@49
   273
    
jaroslav@49
   274
    static UI findUI(Board b) {
jaroslav@49
   275
        for (UI ui : ACTIVE) {
jaroslav@49
   276
            if (ui.getBoards().contains(b)) {
jaroslav@49
   277
                return ui;
jaroslav@49
   278
            }
jaroslav@49
   279
        }
jaroslav@49
   280
        return null;
jaroslav@49
   281
    }
jaroslav@49
   282
    
jaroslav@49
   283
    @Function static void leave(UI ui, Board data) {
jaroslav@49
   284
        ui.getBoards().remove(data);
jaroslav@49
   285
        ui.setSelectedGameId(null);
jaroslav@49
   286
    }
jaroslav@49
   287
    
jaroslav@49
   288
    @Function static void disconnect(UI ui) {
jaroslav@49
   289
        ui.queryServer(ui.getSettings().getUrl(), null);
jaroslav@49
   290
        ui.setStatus("Disconnecting...");
jaroslav@49
   291
    }
jaroslav@49
   292
jaroslav@49
   293
    private static void verifyLogin(UI ui) {
jaroslav@49
   294
        ui.setStatus("Verifying user credentials...");
jaroslav@49
   295
        Request r = new Request();
jaroslav@49
   296
        r.setMsg(MsgType.CheckCredentials);
jaroslav@49
   297
        ui.sendMsg(r);
jaroslav@49
   298
    }
jaroslav@49
   299
    
jaroslav@49
   300
    @Function static void reconnect(UI ui) {
jaroslav@49
   301
        final Settings s = ui.getSettings();
jaroslav@49
   302
        ui.setStatus("Connecting to the server...");
jaroslav@49
   303
        ui.queryServer(s.getUrl(), null);
jaroslav@49
   304
        s.write(ui);
jaroslav@49
   305
    }
jaroslav@49
   306
    
jaroslav@49
   307
    public static void initialize(String... args) throws URISyntaxException, IOException {
jaroslav@49
   308
        UI ui = new UI();
jaroslav@49
   309
        ui.getSettings().read();
jaroslav@49
   310
        ui.setStatus("Ready.");
jaroslav@49
   311
        ui.setDisconnected(true);
jaroslav@49
   312
        ui.applyBindings();
jaroslav@49
   313
    }
jaroslav@49
   314
jaroslav@49
   315
}