# HG changeset patch # User Jaroslav Tulach # Date 1253363909 -7200 # Node ID 8b899ed24f9f7e9299469218cb687f08c8b26ccd # Parent fed05535725f8f5ce450998f879f60ca57c248dc Browsable history of each game diff -r fed05535725f -r 8b899ed24f9f freemarkerdor/pom.xml --- a/freemarkerdor/pom.xml Sat Sep 19 12:51:50 2009 +0200 +++ b/freemarkerdor/pom.xml Sat Sep 19 14:38:29 2009 +0200 @@ -10,7 +10,7 @@ org.apidesign freemarkerdor freemarkerdor - 1.11 + 1.15 http://maven.apache.org diff -r fed05535725f -r 8b899ed24f9f freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Sat Sep 19 12:51:50 2009 +0200 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Sat Sep 19 14:38:29 2009 +0200 @@ -140,20 +140,34 @@ } private Viewable board(String id) { - return board(id, ""); + return board(id, "", null); } @GET @Path("games/{id}/") @Produces(MediaType.TEXT_HTML) - public Viewable board(@PathParam("id") String id, @QueryParam("format") @DefaultValue("") String format) { - return board(id, null, format); + public Viewable board( + @PathParam("id") String id, + @QueryParam("format") @DefaultValue("") String format, + @QueryParam("move") @DefaultValue("-1") String move + ) { + return board(id, null, format, move); } - private Viewable board(@PathParam("id") String id, String msg, String format) { + private Viewable board(@PathParam("id") String id, String msg, String format, String m) { Viewable v = checkLogin(); if (v != null) { return v; } - Document doc = base.path("games").path(id).accept(MediaType.TEXT_XML).get(Document.class); + int move; + try { + move = Integer.parseInt(m); + } catch (NumberFormatException ex) { + move = -1; + } + WebResource url = base.path("games").path(id); + if (move >= 0) { + url = url.queryParam("move", "" + move); + } + Document doc = url.accept(MediaType.TEXT_XML).get(Document.class); Board b; try { b = Board.valueOf(doc.getElementsByTagName("board").item(0).getTextContent()); @@ -196,7 +210,7 @@ return board(id); } } catch (UniformInterfaceException ex) { - return board(id, "WRONG_MOVE"); + return board(id, "WRONG_MOVE", "-1"); } return board(id); } diff -r fed05535725f -r 8b899ed24f9f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle.properties --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle.properties Sat Sep 19 12:51:50 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle.properties Sat Sep 19 14:38:29 2009 +0200 @@ -24,8 +24,14 @@ WHITE=White BLACK=Black -BOARD_IMAGE=Image -BOARD_TEXT=Text View +NEXT=Next +PREVIOUS=Prev +LATEST=Last + +BOARD_VIEW=View: +BOARD_IMAGE=Large +BOARD_SMALL=Small +BOARD_TEXT=Text players={0} vs. {1} PLACE=Place! diff -r fed05535725f -r 8b899ed24f9f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle_cs.properties --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle_cs.properties Sat Sep 19 12:51:50 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle_cs.properties Sat Sep 19 14:38:29 2009 +0200 @@ -33,8 +33,18 @@ 432000#{4}-ti dny\ } -BOARD_IMAGE=Grafick\u00FD pohled -BOARD_TEXT=Textov\u00FD pohled +NEXT=Dal\u0161\u00ED +PREVIOUS=P\u0159edchoz\u00ED +LATEST=Posledn\u00ED + +NEXT=Dal\u0161\u00ED +PREVIOUS=P\u0159edchoz\u00ED +LATEST=Posledn\u00ED + +BOARD_VIEW=Pohled: +BOARD_IMAGE=Obrovsk\u00FD +BOARD_SMALL=Drobn\u00FD +BOARD_TEXT=Textov\u00FD players={0} proti {1} PLACE=Um\u00EDstit diff -r fed05535725f -r 8b899ed24f9f freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Sat Sep 19 12:51:50 2009 +0200 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Sat Sep 19 14:38:29 2009 +0200 @@ -29,12 +29,24 @@

+ ${bundle.MOVENUMBER}: ${(doc.game.@currentMove?number / 2 + 1)?string("0")}
${bundle.WHITE}: <@status doc.game.id.@white/> ${bundle("FENCES_LEFT", board.players[0].fences)}
${bundle.BLACK}: <@status doc.game.id.@black/> ${bundle("FENCES_LEFT", board.players[1].fences)}

${bundle.ROOT} + <#if (doc.game.@currentMove?number > 0)> + ${bundle.PREVIOUS} + <#else> + ${bundle.PREVIOUS} + + ${bundle.LATEST} + <#if (doc.game.@currentMove?number < doc.game.moves.*?size)> + ${bundle.NEXT} + <#else> + ${bundle.NEXT} +

<#if message?? > @@ -99,20 +111,38 @@ - +

+ ${bundle.BOARD_VIEW} <#if format?? && format = "text">

${doc.game.board}
+ ${bundle.BOARD_SMALL} ${bundle.BOARD_IMAGE} + ${bundle.BOARD_TEXT} + <#elseif format?? && format = "small"> +

+ ${bundle.BOARD_TEXT} +

+ ${bundle.BOARD_SMALL} + ${bundle.BOARD_IMAGE} + ${bundle.BOARD_TEXT} <#else>

- text + ${bundle.BOARD_TEXT}

+ ${bundle.BOARD_SMALL} + ${bundle.BOARD_IMAGE} ${bundle.BOARD_TEXT} - + <#macro printMove item> + <#if item.@index = doc.game.@currentMove> + ${item.@move} + <#else> + ${item.@move} + + -

${bundle.MOVES}

+

${bundle.MOVES}

@@ -125,11 +155,12 @@ <#assign index = 0> <#list doc.game.moves.* as item> + <#if item.@index?number % 2 = 1> <#assign index = index + 1> - + <#else> - + diff -r fed05535725f -r 8b899ed24f9f webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Sat Sep 19 14:38:29 2009 +0200 @@ -56,6 +56,7 @@ @XmlElement @XmlJavaTypeAdapter(MoveAdapter.class) private List moves; + private Integer move; Game() { } @@ -115,6 +116,35 @@ return moves; } + @XmlAttribute + public int getCurrentMove() { + return move == null ? getMoves().size() : move; + } + + public Game snapshot(int move) throws IllegalPositionException { + Board b = Board.empty(); + int cnt = 0; + for (Move m : getMoves()) { + if (move-- <= 0) { + break; + } + b = b.apply(m); + cnt++; + } + + Game g = new Game( + new GameId( + id.getId(), id.getWhite(), id.getBlack(), + new Date(id.getStarted()), new Date(id.getModified()), + GameStatus.history + ) + ); + g.board = b; + g.move = cnt; + g.moves = new ArrayList(getMoves()); + return g; + } + @XmlAccessorType(XmlAccessType.FIELD) private static final class MoveTmp { @XmlAttribute diff -r fed05535725f -r 8b899ed24f9f webidor/src/main/java/cz/xelfi/quoridor/webidor/GameStatus.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameStatus.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/GameStatus.java Sat Sep 19 14:38:29 2009 +0200 @@ -36,7 +36,8 @@ whiteMove, blackMove, whiteWon, - blackWon; + blackWon, + history; /** Creates appropriate status of the game based on the state * on the board. diff -r fed05535725f -r 8b899ed24f9f webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/BoardImage.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/BoardImage.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/BoardImage.java Sat Sep 19 14:38:29 2009 +0200 @@ -40,13 +40,7 @@ * @author Jaroslav Tulach */ final class BoardImage { - - - public static Image draw(Board b) { - return draw(b, 50); - } - - private static Image draw(Board b, int fieldSize) { + static Image draw(Board b, int fieldSize) { int fifth = fieldSize / 10; BufferedImage img = new BufferedImage(fieldSize * 9, fieldSize * 9, BufferedImage.TYPE_INT_ARGB); diff -r fed05535725f -r 8b899ed24f9f webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Games.java Sat Sep 19 14:38:29 2009 +0200 @@ -43,6 +43,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -121,23 +122,26 @@ @GET @Path("{id}") @Produces("image/png") - public Image getBoardImage(@PathParam("id") String id) { - Game g = findGame(id); + public Image getBoardImage( + @PathParam("id") String id, + @QueryParam("fieldSize") @DefaultValue("50") int fieldSize, + @QueryParam("move") @DefaultValue("-1") int move + ) { + Game g = findGame(id, move); if (g == null) { throw new IllegalArgumentException("Unknown game " + id); } - return BoardImage.draw(g.getBoard()); + return BoardImage.draw(g.getBoard(), fieldSize); } @GET @Path("{id}") @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) - public Game getBoardInfo(@PathParam("id") String id) { - Game g = findGame(id); - if (g == null) { - throw new IllegalArgumentException("Unknown game " + id); - } - return g; + public Game getBoardInfo( + @PathParam("id") String id, + @QueryParam("move") @DefaultValue("-1") int move + ) { + return findGame(id, move); } @PUT @@ -194,6 +198,18 @@ } return null; } + private Game findGame(String id, int move) { + Game g = findGame(id); + if (g == null) { + throw new IllegalArgumentException("Unknown game " + id); + } + try { + return move == -1 ? g : g.snapshot(move); + } catch (IllegalPositionException ex) { + Logger.getLogger(Games.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } private Game readGame(File f) throws IOException { BufferedReader r = new BufferedReader(new FileReader(f)); diff -r fed05535725f -r 8b899ed24f9f webidor/src/test/java/cz/xelfi/quoridor/webidor/GamesTest.java --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/GamesTest.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/GamesTest.java Sat Sep 19 14:38:29 2009 +0200 @@ -82,7 +82,7 @@ Thread.sleep(1000); Games games = new Games(dir, new Quoridor()); - Game g = games.getBoardInfo("x"); + Game g = games.getBoardInfo("x", -1); assertNotNull("Game found", g); assertNotNull("Board found", g.getBoard()); assertEquals("List of moves has two", 2, g.getMoves().size()); diff -r fed05535725f -r 8b899ed24f9f webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Sat Sep 19 12:51:50 2009 +0200 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Sat Sep 19 14:38:29 2009 +0200 @@ -161,6 +161,11 @@ if (s2.getModified() <= now) { fail("The game is newly modified"); } + Game snapshot = webResource.path("games/" + s.getId()).queryParam("move", "0").accept(MediaType.TEXT_XML).get(Game.class); + assertEquals("All moves listed", 2, snapshot.getMoves().size()); + assertEquals("Current move", 0, snapshot.getCurrentMove()); + assertEquals("Position 0", 0, snapshot.getBoard().getPlayers().get(0).getRow()); + assertEquals("Position 8", 8, snapshot.getBoard().getPlayers().get(1).getRow()); File game = new File(new File(dir, "games"), s2.getId()); assertTrue("File for game exists", game.exists());
${index}${item.@move}
${index}<@printMove item/>${item.@move}
<@printMove item/>