package com.chughes.dip.controller; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.JPEGTranscoder; import org.apache.batik.util.XMLResourceDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.w3c.dom.svg.SVGDocument; import org.w3c.dom.svg.SVGElement; import org.xml.sax.SAXException; import com.chughes.dip.data.GameRepository; import com.chughes.dip.data.MapHolder; import com.chughes.dip.data.UserRepository; import com.chughes.dip.game.GameEntity; import com.chughes.dip.game.GameMaster; import com.chughes.dip.game.UserGameEntity; import com.chughes.dip.game.GameEntity.Stage; import com.chughes.dip.misc.UIOrder; import com.chughes.dip.user.UserDetailsImpl; import com.chughes.dip.user.UserEntity; import dip.gui.map.DefaultMapRenderer2; import dip.gui.map.MapException; import dip.gui.map.RenderCommandFactory.RenderCommand; import dip.gui.map.SymbolInjector; import dip.gui.order.GUIOrder; import dip.gui.order.GUIOrder.MapInfo; import dip.gui.order.GUIOrderFactory; import dip.order.Order; import dip.order.OrderException; import dip.order.OrderParser; import dip.order.Orderable; import dip.order.ValidationOptions; import dip.world.Phase; import dip.world.Power; import dip.world.Province; import dip.world.TurnState; import dip.world.Unit; import dip.world.World; import dip.world.variant.VariantManager; import dip.world.variant.data.MapGraphic; import dip.world.variant.data.Variant; @Controller public class HomeController { @Autowired private UserRepository us; @Autowired private GameRepository gameRepo; @Autowired private MapHolder mh; @Autowired private GameMaster gm; private static final Logger logger = LoggerFactory.getLogger(HomeController.class); @RequestMapping("/help") public String help() { return "help"; } @RequestMapping(value = "/") public String dash(Model model){ UserDetailsImpl user = null; Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof UserDetailsImpl){ UserDetails user1 = (UserDetails)auth.getPrincipal(); user = (UserDetailsImpl) user1; UserEntity ue = us.getUserEntity(user.getId()); model.addAttribute("user",ue); model.addAttribute("loggedin", true); model.addAttribute("games", ue.getGames()); } return "dash"; } @RequestMapping(value = "/game/{gameID}") public String home(Model model,@PathVariable(value="gameID") int id) throws Exception { boolean loggedin = false; UserDetailsImpl user = null; Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof UserDetails){ UserDetails user1 = (UserDetails)auth.getPrincipal(); user = (UserDetailsImpl) user1; UserEntity ue = us.getUserEntity(user.getId()); model.addAttribute("user",ue); model.addAttribute("loggedin", true); loggedin = true; } GameEntity game = gameRepo.findById(id); World w = game.getW(); boolean member = false; Power p1 = null; model.addAttribute("gameprivate", (game.getSecret().length() > 0)); model.addAttribute("tournament", game.isTournament()); if (loggedin){ UserGameEntity uge = gameRepo.inGameUser(id, user.getId()); if (uge != null){ member = true; model.addAttribute("me_id", uge.getId()); model.addAttribute("me", uge); model.addAttribute("isready", uge.isReady()); model.addAttribute("phasetype", w.getLastTurnState().getPhase().getPhaseType().getBriefName()); if (game.getStage() == Stage.PLAYING){ Map<String,String> provinces = new HashMap<String,String>(); for (Province p:game.getW().getMap().getProvinces()){ for (String shortn :p.getShortNames()){ provinces.put(shortn, p.getFullName()); } } model.addAttribute("provinces", provinces); //Show orders just for the logged in user. p1 = w.getMap().getPowerMatching(uge.getPower()); List<GUIOrder> orders = w.getLastTurnState().getOrders(p1); Map<String,String> textorders = new HashMap<String,String>(); for (GUIOrder o : orders) { System.out.println(o.toFullString()); textorders.put(o.getSource().toString(), o.toFullString()); } model.addAttribute("textorders", textorders); } } } TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer1 = tf.newTransformer(); transformer1.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer1.setOutputProperty(OutputKeys.METHOD, "xml"); transformer1.setOutputProperty(OutputKeys.INDENT, "yes"); transformer1.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //ByteArrayOutputStream baos = new ByteArrayOutputStream(); StringWriter sw1 = new StringWriter(); transformer1.transform(new DOMSource(renderSVG(id,w, p1, null)), new StreamResult(sw1)); model.addAttribute("svg", sw1.toString()); model.addAttribute("gid", id); DefaultMapRenderer2 mr = mh.getMr(id); Set<UserGameEntity> players = game.getPlayers(); if (game.getStage() == Stage.PLAYING){ for (UserGameEntity player : players) { player.setColor(mr.getMapMetadata().getPowerColor(w.getMap().getPowerMatching(player.getPower()))); } } model.addAttribute("players", players); model.addAttribute("member_of_game", member); model.addAttribute("gamephase", game.getW().getLastTurnState().getPhase().toString()); model.addAttribute("started", game.getStage() != Stage.PREGAME); model.addAttribute("playing", game.getStage() == Stage.PLAYING); model.addAttribute("next", game.getTurnend()); return "board"; } @RequestMapping(value = "/game/m{gameID}") public String homeM(Model model,@PathVariable(value="gameID") int id) throws Exception { boolean loggedin = false; UserDetailsImpl user = null; Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth.getPrincipal() instanceof UserDetails){ UserDetails user1 = (UserDetails)auth.getPrincipal(); user = (UserDetailsImpl) user1; UserEntity ue = us.getUserEntity(user.getId()); model.addAttribute("user",ue); model.addAttribute("loggedin", true); loggedin = true; } GameEntity game = gameRepo.findById(id); World w = game.getW(); boolean member = false; Power p1 = null; model.addAttribute("gameprivate", (game.getSecret().length() > 0)); if (loggedin){ UserGameEntity uge = gameRepo.inGameUser(id, user.getId()); if (uge != null){ member = true; model.addAttribute("me_id", uge.getId()); model.addAttribute("me", uge); model.addAttribute("isready", uge.isReady()); model.addAttribute("phasetype", w.getLastTurnState().getPhase().getPhaseType().getBriefName()); if (game.getStage() == Stage.PLAYING){ Map<String,String> provinces = new HashMap<String,String>(); for (Province p:game.getW().getMap().getProvinces()){ for (String shortn :p.getShortNames()){ provinces.put(shortn, p.getFullName()); } } model.addAttribute("provinces", provinces); //Show orders just for the logged in user. p1 = w.getMap().getPowerMatching(uge.getPower()); List<GUIOrder> orders = w.getLastTurnState().getOrders(p1); Map<String,String> textorders = new HashMap<String,String>(); for (GUIOrder o : orders) { System.out.println(o.toFullString()); textorders.put(o.getSource().toString(), o.toFullString()); } model.addAttribute("textorders", textorders); } } } TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer1 = tf.newTransformer(); transformer1.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer1.setOutputProperty(OutputKeys.METHOD, "xml"); transformer1.setOutputProperty(OutputKeys.INDENT, "yes"); transformer1.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //ByteArrayOutputStream baos = new ByteArrayOutputStream(); StringWriter sw1 = new StringWriter(); transformer1.transform(new DOMSource(renderSVG(id,w, p1, null)), new StreamResult(sw1)); model.addAttribute("svg", sw1.toString()); model.addAttribute("gid", id); DefaultMapRenderer2 mr = mh.getMr(id); Set<UserGameEntity> players = game.getPlayers(); if (game.getStage() == Stage.PLAYING){ for (UserGameEntity player : players) { player.setColor(mr.getMapMetadata().getPowerColor(w.getMap().getPowerMatching(player.getPower()))); } } model.addAttribute("players", players); model.addAttribute("member_of_game", member); model.addAttribute("gamephase", game.getW().getLastTurnState().getPhase().toString()); model.addAttribute("started", game.getStage() != Stage.PREGAME); model.addAttribute("playing", game.getStage() == Stage.PLAYING); model.addAttribute("next", game.getTurnend()); return "boardmcompat"; } private SVGDocument renderSVG(int id, World w, Power p1, String phase) throws TransformerException, IOException, SAXException, ParserConfigurationException, MapException, InterruptedException { World.VariantInfo vi = w.getVariantInfo(); Variant variant = VariantManager.getVariant( vi.getVariantName(), vi.getVariantVersion() ); MapGraphic mg = variant.getMapGrapic( vi.getMapName() ); if(mg == null) { // try a default map graphic mg = variant.getDefaultMapGraphic(); } SymbolInjector si = new SymbolInjector(variant, mg, VariantManager.getSymbolPacks()[2]); si.inject(); TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); StringWriter sw = new StringWriter(); StreamResult result = new StreamResult(sw); transformer.transform(new DOMSource(si.getDocument()), result); sw.flush(); sw.close(); //Create an SVG Document and start drawing the map String parser = XMLResourceDescriptor.getXMLParserClassName(); SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); SVGDocument doc = f.createSVGDocument(VariantManager.getVariantPackageJarURL(variant).toString(), new StringReader(sw.toString())); DefaultMapRenderer2 mr = new DefaultMapRenderer2(doc, w, VariantManager.getSymbolPacks()[3]); mh.setMr(id,mr); TurnState tState; if (phase != null) { tState = w.getTurnState(Phase.parse(phase)); }else { tState = w.getLastTurnState(); mh.setPhase(id,tState.getPhase()); } RenderCommand rc = mr.getRenderCommandFactory().createRCSetTurnstate(mr, tState); RenderCommand rc3 = mr.getRenderCommandFactory().createRCRenderAll(mr); mr.execRenderCommand(rc); if (p1 != null) { //Show orders just for the logged in user. RenderCommand rc2 = mr.getRenderCommandFactory().createRCSetPowerOrdersDisplayed(mr, new Power[]{p1}); mr.execRenderCommand(rc2); List<GUIOrder> orders = tState.getOrders(p1); for (GUIOrder o : orders) { o.updateDOM(mr.new DMRMapInfo(tState)); } }else if (tState != w.getLastTurnState()) { RenderCommand rc2 = mr.getRenderCommandFactory().createRCSetPowerOrdersDisplayed(mr, w.getMap().getPowers()); mr.execRenderCommand(rc2); List<GUIOrder> orders = tState.getAllOrders(); for (GUIOrder o : orders) { o.updateDOM(mr.new DMRMapInfo(tState)); } } //mr.execRenderCommand(rc4); //mr.execRenderCommand(rc5); mr.execRenderCommand(rc3); //Convert SVG Document to String return doc; } @RequestMapping(value="/game/phase/{gameID}/{phase}") public @ResponseBody List<String> phasechange(@PathVariable(value="gameID") int id,@PathVariable(value="phase") String phase){ GameEntity game = gameRepo.findById(id); World w = game.getW(); String longname = null; TurnState tState = w.getTurnState(mh.getPhase(id)); if (phase.equals("previous")){ tState = w.getPreviousTurnState(tState); if (tState == null){ phase = "empty"; }else { mh.setPhase(id,tState.getPhase()); phase = tState.getPhase().getBriefName(); longname = tState.getPhase().toString(); } }else if (phase.equals("next")){ tState = w.getNextTurnState(tState); if (tState == null){ phase = "empty"; }else { mh.setPhase(id,tState.getPhase()); phase = tState.getPhase().getBriefName(); longname = tState.getPhase().toString(); if (tState == w.getLastTurnState()){ phase = "current"; } } } ArrayList<String> result = new ArrayList<String>(2); result.add(0, phase); result.add(1,longname); return result; } @RequestMapping(value="/gameimage/{gameID}/{phase}") public void rasterimage(@PathVariable(value="gameID") int id,@PathVariable(value="phase") String phase, HttpServletResponse response) throws Exception, IOException, SAXException, ParserConfigurationException, MapException, InterruptedException, TranscoderException{ response.setContentType("image/jpeg"); GameEntity game = gameRepo.findById(id); World w = game.getW(); if (w.getLastTurnState().getPhase().compareTo(Phase.parse(phase)) == 0)throw new IllegalAccessError("Cannot Acccess Latest Turn"); JPEGTranscoder t = new JPEGTranscoder(); t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, .95f); SVGDocument svg = renderSVG(id,w, null, phase); TranscoderInput input = new TranscoderInput(svg); TranscoderOutput tOutput = new TranscoderOutput(response.getOutputStream()); t.transcode(input, tOutput); response.getOutputStream().flush(); response.getOutputStream().close(); } @PreAuthorize("hasRole('PLAYER')") @RequestMapping(value = "/game/{gameID}/JSONtextorder") public @ResponseBody Map<String, ?> textOrder(@PathVariable(value="gameID") int id, @RequestBody String order) throws TransformerException{ Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl user = (UserDetailsImpl) auth.getPrincipal(); UserEntity ue = us.getUserEntity(user.getId()); GameEntity game = gameRepo.findById(id); World w = game.getW(); UserGameEntity uge = gameRepo.inGameUser(id, ue.getId()); Power p = w.getMap().getPowerMatching(uge.getPower()); OrderParser op = OrderParser.getInstance(); Order o; try { o = op.parse(new GUIOrderFactory(), order, p, w.getLastTurnState(), true, false); } catch (OrderException e) { return Collections.singletonMap("error", new String[]{e.getLocalizedMessage()}); } return orderJSON(id, w, o, p); } private Map<String,?> orderJSON(int id, World w, Order o, Power p) throws TransformerException{ ValidationOptions vo = new ValidationOptions(); vo.setOption(ValidationOptions.KEY_GLOBAL_PARSING, ValidationOptions.VALUE_GLOBAL_PARSING_STRICT); try{ o.validate(w.getLastTurnState(), vo, w.getRuleOptions()); }catch(OrderException oe){ return Collections.singletonMap("error", new String[]{oe.getLocalizedMessage()}); } DefaultMapRenderer2 mr = mh.getMr(id); MapInfo info = mr.new DMRMapInfo(w.getLastTurnState()); SVGElement element = ((GUIOrder)o).orderSVG(info); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer1 = tf.newTransformer(); transformer1.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer1.setOutputProperty(OutputKeys.METHOD, "xml"); transformer1.setOutputProperty(OutputKeys.INDENT, "yes"); transformer1.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //ByteArrayOutputStream baos = new ByteArrayOutputStream(); StringWriter sw1 = new StringWriter(); transformer1.transform(new DOMSource(element), new StreamResult(sw1)); //Preventing two orders for same unit TurnState ts = w.getLastTurnState(); List<Orderable> orders = ts.getOrders(p); Iterator<Orderable> iter = orders.iterator(); //boolean isDuplicate = false; while(iter.hasNext()) { //System.out.println("Looping"); Orderable listOrder = iter.next(); if( listOrder.getSource().isProvinceEqual(o.getSource()) ) { //System.out.println("Should be removed"); iter.remove(); } } orders.add(o); //model.addAttribute("success", 1); gameRepo.updateTS(ts); String id1 = info.getPowerSVGGElement(p, 1).getId(); Map<String,Object> results = new HashMap<String,Object>(); results.put("orders",Collections.singletonMap(id1,sw1.toString())); results.put("orders_text", Collections.singletonMap(o.getSource().toString(),o.toFullString())); return results; } @PreAuthorize("hasRole('PLAYER')") @RequestMapping(value = "/game/{gameID}/JSONorder") public @ResponseBody Map<String, ?> move(@PathVariable(value="gameID") int id,@RequestBody UIOrder order) throws Exception { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl user = (UserDetailsImpl) auth.getPrincipal(); UserEntity ue = us.getUserEntity(user.getId()); GameEntity game = gameRepo.findById(id); World w = game.getW(); UserGameEntity uge = gameRepo.inGameUser(id, ue.getId()); Power p = w.getMap().getPowerMatching(uge.getPower()); DefaultMapRenderer2 mr = mh.getMr(id); Order o = null; if (order.getType().equals("order-move")){ o = new GUIOrderFactory().createMove(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED, mr.getLocation(order.getLoc1())); }else if (order.getType().equals("order-hold")){ o = new GUIOrderFactory().createHold(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED); }else if (order.getType().equals("order-shold")){ o = new GUIOrderFactory().createSupport(p, mr.getLocation(order.getLoc()),Unit.Type.UNDEFINED, mr.getLocation(order.getLoc1()), w.getLastTurnState().getPosition().getUnit(w.getMap().getProvinceMatching(order.getLoc1())).getPower(), Unit.Type.UNDEFINED); }else if (order.getType().equals("order-smove")){ o = new GUIOrderFactory().createSupport(p, mr.getLocation(order.getLoc()),Unit.Type.UNDEFINED, mr.getLocation(order.getLoc1()), w.getLastTurnState().getPosition().getUnit(w.getMap().getProvinceMatching(order.getLoc1())).getPower(), Unit.Type.UNDEFINED,mr.getLocation(order.getLoc2())); }else if (order.getType().equals("order-convoy")){ o = new GUIOrderFactory().createConvoy(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED, mr.getLocation(order.getLoc1()), w.getLastTurnState().getPosition().getUnit(w.getMap().getProvinceMatching(order.getLoc1())).getPower(), Unit.Type.UNDEFINED,mr.getLocation(order.getLoc2())); }else if (order.getType().equals("order-retreat")){ o = new GUIOrderFactory().createRetreat(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED, mr.getLocation(order.getLoc1())); }else if (order.getType().equals("order-disband")){ o = new GUIOrderFactory().createDisband(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED); }else if (order.getType().equals("order-builda")){ o = new GUIOrderFactory().createBuild(p, mr.getLocation(order.getLoc()), Unit.Type.ARMY); }else if (order.getType().equals("order-buildf")){ o = new GUIOrderFactory().createBuild(p, mr.getLocation(order.getLoc()), Unit.Type.FLEET); }else if (order.getType().equals("order-destroy")){ o = new GUIOrderFactory().createRemove(p, mr.getLocation(order.getLoc()), Unit.Type.UNDEFINED); } //logger.info("From: "+o.getSourceUnitType()); return orderJSON(id, w, o, p); } @PreAuthorize("hasRole('PLAYER')") @RequestMapping(value = "/game/{gameID}/JSONorder-remove") public @ResponseBody String remove(@PathVariable(value="gameID") int id,@RequestParam(value="prov") String province) throws Exception { province = URLDecoder.decode( province, "UTF-8" ); province = province.replace("/", "-"); System.out.println("In:" + province); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl user = (UserDetailsImpl) auth.getPrincipal(); GameEntity game = gameRepo.findById(id); World w = game.getW(); UserGameEntity uge = gameRepo.inGameUser(id, user.getId()); Power p = w.getMap().getPowerMatching(uge.getPower()); DefaultMapRenderer2 mr = mh.getMr(id); List<Orderable> orders = w.getLastTurnState().getOrders(p); Iterator<Orderable> iter = orders.iterator(); //boolean isDuplicate = false; while(iter.hasNext()) { //System.out.println("Looping"); Orderable listOrder = iter.next(); if( listOrder.getSource().isProvinceEqual(mr.getLocation(province)) ) { //System.out.println("Should be removed"); iter.remove(); gameRepo.updateWorld(w); return "success"; } } return "fail"; } @PreAuthorize("hasRole('PLAYER')") @RequestMapping(value = "/game/{gameID}/JSONready") public @ResponseBody Map<String, ?> setReady(@PathVariable(value="gameID") int id){ Authentication auth = SecurityContextHolder.getContext().getAuthentication(); UserDetails user1 = (UserDetails)auth.getPrincipal(); UserDetailsImpl user = (UserDetailsImpl) user1; UserGameEntity uge = gameRepo.inGameUser(id, user.getId()); boolean ready = uge.isReady(); if (uge.isOrderable()){ uge.setReady(!ready); gameRepo.saveInGameUser(uge); gm.processGame(uge.getGame()); } return Collections.singletonMap("ready", uge.isReady()); } }