webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 18 Sep 2009 23:28:13 +0200
changeset 95 36ace6ba1dc1
parent 82 9ac7acee7d9f
child 96 2eeaa41236c3
permissions -rw-r--r--
Ability to display the board as image
     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * The contents of this file are subject to the terms of either the GNU
     5  * General Public License Version 2 only ("GPL") or the Common
     6  * Development and Distribution License("CDDL") (collectively, the
     7  * "License"). You may not use this file except in compliance with the
     8  * License. You can obtain a copy of the License at
     9  * http://www.netbeans.org/cddl-gplv2.html
    10  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    11  * specific language governing permissions and limitations under the
    12  * License.  When distributing the software, include this License Header
    13  * Notice in each file and include the License file at
    14  * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    15  * particular file as subject to the "Classpath" exception as provided
    16  * by Sun in the GPL Version 2 section of the License file that
    17  * accompanied this code. If applicable, add the following below the
    18  * License Header, with the fields enclosed by brackets [] replaced by
    19  * your own identifying information:
    20  * "Portions Copyrighted [year] [name of copyright owner]"
    21  *
    22  * Contributor(s):
    23  *
    24  * Portions Copyrighted 2009 Jaroslav Tulach
    25  */
    26 
    27 package cz.xelfi.quoridor.webidor.resources;
    28 
    29 import cz.xelfi.quoridor.IllegalPositionException;
    30 import cz.xelfi.quoridor.webidor.*;
    31 import cz.xelfi.quoridor.Move;
    32 import java.awt.Image;
    33 import java.io.BufferedReader;
    34 import java.io.BufferedWriter;
    35 import java.io.File;
    36 import java.io.FileReader;
    37 import java.io.FileWriter;
    38 import java.io.IOException;
    39 import java.io.PrintWriter;
    40 import java.util.ArrayList;
    41 import java.util.Date;
    42 import java.util.List;
    43 import java.util.logging.Level;
    44 import java.util.logging.Logger;
    45 import javax.ws.rs.GET;
    46 import javax.ws.rs.POST;
    47 import javax.ws.rs.PUT;
    48 import javax.ws.rs.Path;
    49 import javax.ws.rs.PathParam;
    50 import javax.ws.rs.Produces;
    51 import javax.ws.rs.QueryParam;
    52 import javax.ws.rs.WebApplicationException;
    53 import javax.ws.rs.core.MediaType;
    54 import javax.ws.rs.core.Response.Status;
    55 
    56 /**
    57  *
    58  * @author Jaroslav Tulach <jtulach@netbeans.org>
    59  */
    60 public final class Games {
    61     private final Quoridor quoridor;
    62     private final List<Game> games = new ArrayList<Game>();
    63     private final File dir;
    64     private static final Logger LOG = Logger.getLogger(Games.class.getName());
    65 
    66     public Games(File dir, Quoridor quoridor) {
    67         this.dir = dir;
    68         this.quoridor = quoridor;
    69         File[] arr = dir.listFiles();
    70         if (arr != null) {
    71             for (File f : arr) {
    72                 try {
    73                     Game g = readGame(f);
    74                     games.add(g);
    75                 } catch (IOException ex) {
    76                     LOG.log(Level.WARNING, "Wrong game in " + f, ex);
    77                 }
    78             }
    79         }
    80     }
    81 
    82     @POST
    83     @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
    84     public GameId createGame(
    85         @QueryParam("loginID") String id,
    86         @QueryParam("white") String white,
    87         @QueryParam("black") String black
    88     ) throws IOException {
    89         String logUser = quoridor.isLoggedIn(id);
    90         if (logUser == null) {
    91             throw new WebApplicationException(Status.UNAUTHORIZED);
    92         }
    93         if (white == null) {
    94             throw new WebApplicationException(Status.PRECONDITION_FAILED);
    95         }
    96         if (black == null) {
    97             throw new WebApplicationException(Status.PRECONDITION_FAILED);
    98         }
    99         if (!logUser.equals(white) && !logUser.equals(black)) {
   100             throw new WebApplicationException(Status.PRECONDITION_FAILED);
   101         }
   102 
   103         Game g = new Game(white, black);
   104         storeGame(g);
   105         games.add(g);
   106         return g.getId();
   107     }
   108 
   109     @GET
   110     @Path("{id}")
   111     @Produces(MediaType.TEXT_PLAIN)
   112     public String getBoard(@PathParam("id") String id) {
   113         Game g = findGame(id);
   114         if (g == null) {
   115             throw new IllegalArgumentException("Unknown game " + id);
   116         }
   117         return g.getBoard().toString();
   118     }
   119 
   120     @GET
   121     @Path("{id}")
   122     @Produces("image/png")
   123     public Image getBoardImage(@PathParam("id") String id) {
   124         Game g = findGame(id);
   125         if (g == null) {
   126             throw new IllegalArgumentException("Unknown game " + id);
   127         }
   128         return BoardImage.draw(g.getBoard());
   129     }
   130 
   131     @GET
   132     @Path("{id}")
   133     @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   134     public Game getBoardInfo(@PathParam("id") String id) {
   135         Game g = findGame(id);
   136         if (g == null) {
   137             throw new IllegalArgumentException("Unknown game " + id);
   138         }
   139         return g;
   140     }
   141 
   142     @PUT
   143     @Path("{id}")
   144     @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   145     public GameId applyMove(
   146         @QueryParam("loginID") String loginId,
   147         @PathParam("id") String id,
   148         @QueryParam("player") String player,
   149         @QueryParam("move") String move
   150     ) throws IllegalPositionException {
   151         String logUser = quoridor.isLoggedIn(loginId);
   152         if (logUser == null) {
   153             throw new WebApplicationException(Status.UNAUTHORIZED);
   154         }
   155         if (!logUser.equals(player)) {
   156             throw new WebApplicationException(Status.UNAUTHORIZED);
   157         }
   158 
   159         Game g = findGame(id);
   160         if (g == null) {
   161             throw new IllegalArgumentException("Unknown game " + id);
   162         }
   163         Move m = Move.valueOf(move);
   164         g.apply(player, m, new Date());
   165         try {
   166             storeGame(g);
   167         } catch (IOException ex) {
   168             LOG.log(Level.WARNING, "Cannot store game " + id, ex);
   169         }
   170         return g.getId();
   171     }
   172 
   173     @GET
   174     @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
   175     public List<GameId> listGames() {
   176         List<GameId> arr = new ArrayList<GameId>(games.size());
   177         for (Game g : games) {
   178             arr.add(g.getId());
   179         }
   180         return arr;
   181     }
   182 
   183     public List<Game> getGames() {
   184         return games;
   185     }
   186 
   187     private Game findGame(String id) {
   188         for (Game g : games) {
   189             if (g.getId().getId().equals(id)) {
   190                 return g;
   191             }
   192         }
   193         return null;
   194     }
   195 
   196     private Game readGame(File f) throws IOException {
   197         BufferedReader r = new BufferedReader(new FileReader(f));
   198         String white = null;
   199         String black = null;
   200         Game g = null;
   201         for (;;) {
   202             String line = r.readLine();
   203             if (line == null) {
   204                 line = "finish";
   205             }
   206             line = line.trim();
   207             if (line.length() == 0) {
   208                 continue;
   209             }
   210             if (line.startsWith("# white: ")) {
   211                 white = line.substring(9);
   212                 continue;
   213             }
   214             if (line.startsWith("# black: ")) {
   215                 black = line.substring(9);
   216                 continue;
   217             }
   218             if (line.startsWith("#")) {
   219                 continue;
   220             }
   221             if (white == null || black == null) {
   222                 throw new IOException("Missing white and black identification in " + f);
   223             }
   224             if (g == null) {
   225                 GameId id = new GameId(f.getName(), white, black, new Date(f.lastModified()), new Date(f.lastModified()), GameStatus.whiteMove);
   226                 g = new Game(id);
   227             }
   228             if (line.equals("finish")) {
   229                 break;
   230             }
   231             String[] moves = line.split(" ");
   232             if (moves.length == 0) {
   233                 continue;
   234             }
   235             if (moves.length > 2) {
   236                 throw new IOException("Too much moves on line: " + line);
   237             }
   238             try {
   239                 g.apply(white, Move.valueOf(moves[0]), null);
   240                 if (moves.length == 2) {
   241                     g.apply(black, Move.valueOf(moves[1]), null);
   242                 }
   243             } catch (IllegalPositionException ex) {
   244                 throw new IOException("Wrong move: " + ex.getMessage());
   245             }
   246         }
   247         if (g == null) {
   248             throw new IOException("No moves in " + f);
   249         }
   250         return g;
   251     }
   252 
   253     private void storeGame(Game g) throws IOException {
   254         dir.mkdirs();
   255         File f = new File(dir, g.getId().getId());
   256         PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(f)));
   257         pw.println("# white: " + g.getId().getWhite());
   258         pw.println("# black: " + g.getId().getBlack());
   259         pw.println("# status: " + g.getId().getStatus());
   260         int cnt = 0;
   261         for (Move m : g.getMoves()) {
   262             pw.print(m.toString());
   263             if (++cnt % 2 == 0) {
   264                 pw.println();
   265             } else {
   266                 pw.print(' ');
   267             }
   268         }
   269         pw.println();
   270         pw.println();
   271         pw.flush();
   272         pw.close();
   273     }
   274 }