/* ********************************** * Administrator.java * Administrator * **********************************/ package admin; import config.AdminConfig; import edu.neu.ccs.demeterf.demfgen.lib.List; import edu.neu.ccs.demeterf.demfgen.lib.List.Pred; import gen.*; import admin.utils.*; import admin.utils.Game.GameType; import java.io.*; /** Administrator of the game * @authors animesh, mkoscumb, and Alex Dubreuil */ public class Administrator{ private Players players = AdminDocumentHandler.getPlayers(); private Config config = AdminDocumentHandler.getConfig(); private File playerDir = new File(AdminConfig.BLACKBOARD_PATH + AdminConfig.PLAYERS_PATH); private Store store = AdminDocumentHandler.getStore(); private Accounts accounts = AdminDocumentHandler.getAccounts(); Output out; Output results; String maxStack; int roundNum; /** Create a new Administrator with the given Output */ Administrator(Output o, String pStack) { this(o, o, pStack); } Administrator(Output o, Output r, String pStack) { out = o; results = r; roundNum = 1; maxStack = pStack; } /** Connection to the outside world... */ public static void main(String[] args){ final AdminCmdLineParser cmd = new AdminCmdLineParser(args); Output o = (!cmd.outputFile.equals(""))? Output.htmlOutput(cmd.outputFile):Output.htmlOutput(); AdminDocumentHandler.resetFilesToDefault(); if (!cmd.resultsFile.equals("")) new Administrator(o, Output.htmlOutput(cmd.resultsFile), cmd.maxStack).main(cmd.gt); else new Administrator(o, cmd.maxStack).main(cmd.gt); } long curTurnFin = System.currentTimeMillis(); /** Main method for Administrator */ private void main(final GameType g){ long gameStartTime = curTurnFin; out.header(); if(results != out) { results.header(); } while(roundNum <= config.Rounds + 2 && players.length() > 1){ if(overtime(roundNum)){ out.newOTRound(roundNum, config.Rounds); System.err.println(" * Starting Overtime Round #"+(roundNum-config.Rounds)+" of 2."); }else{ out.newRound(roundNum, config.Rounds); System.err.println(" * Starting Round #"+(roundNum)+" of "+config.Rounds); } Round round = new Round(roundNum, players.players.map(new List.Map<Player, PlayerTransaction>(){ public PlayerTransaction map(Player player){ out.time("Admin overhead", curTurnFin); out.line(""); if(passTurn(player, roundNum)){ curTurnFin = System.currentTimeMillis(); PlayerTransaction pTrans = AdminDocumentHandler.getPlayerTrans(player); if(pTrans != null){ Pair<Boolean, String> rules; pTrans = Util.checkDerivatives(pTrans,store); pTrans = Util.computeQualities(pTrans); pTrans = Util.truncateRMs(pTrans, config.MaxRawMaterialLen); if(overtime(roundNum)){ List<Transaction> transs = pTrans.transactions.filter(new Pred<Transaction>(){ public boolean huh(Transaction arg0) { return arg0.ttype instanceof Deliver || arg0.ttype instanceof Finish; } }); pTrans = new PlayerTransaction(pTrans.player, transs); rules = RuleChecker.overtimeRulesFollowed(pTrans,store,accounts,g,config); }else { rules = RuleChecker.rulesFollowed(pTrans,store,accounts,g,config); } if(rules.a){ //long start = System.currentTimeMillis(); updateStore(pTrans); //out.time("Store Update", start); //start = System.currentTimeMillis(); updateAccounts(pTrans); //out.time("Accounts Update", start); return pTrans; } out.violation(rules.b, player); }else out.violation("No Transaction", player); }else out.violation("Time Violation or missing jar", player); takeViolationAction(players, player); // Remove the player from players for next Round players = players.remove(player.id); return new PlayerTransaction(player,List.<Transaction>create()); }})); //long start = System.currentTimeMillis(); AdminDocumentHandler.updateHistory(round); //out.time("History Update", start); roundNum++; } System.err.println("Game finished, calculating results."); out.time("Admin overhead", curTurnFin); out.time("Total Game time", gameStartTime); declareWinner(); out.footer(); } /** Is it overtime? */ protected boolean overtime(int round) { return round > config.Rounds; } /** Declares the player with the largest account the winner. */ private void declareWinner(){ results.finishTable(accounts, players, AdminDocumentHandler.getPlayers()); if(results != out) { results.footer(); } } /** Takes appropriate actions in case one of the players violates rules */ private void takeViolationAction(Players players, Player player){ if(store.contains(player.id)){ // for each derivative in the <boughtstore> of the player // deduct price value from the account of the seller // add the derivative back to the <forSale> store of the seller for(Derivative der: store.getStore(player).bought){ accounts = accounts.update(Util.pair(der.seller, -der.price.val)); store = store.replace(Util.spair(der.seller,store.getStore(der.seller) .pushSale(new Derivative(der.name, der.seller, der.price, der.type)))); } // for each derivative that is created by the player AND in the <boughtStore> of Players // add price value to the account of the buyer // remove derivative from the bought store of the buyer for(Player otherPlayer: players.players){ Pair<PlayerID, PlayerStore> otherPIDAndStore = store.getStorePair(otherPlayer.id); List<Derivative> otherPlayerBoughtStore = otherPIDAndStore.b.bought; for(Derivative der: otherPlayerBoughtStore){ if(der.seller.equals(player.id)){ accounts = accounts.update(Util.pair(otherPIDAndStore.a, der.price.val)); otherPlayerBoughtStore = otherPlayerBoughtStore.remove(der); } } otherPIDAndStore.b.bought = otherPlayerBoughtStore; store = store.replace(otherPIDAndStore); } } // remove the player store from store AdminDocumentHandler.commitStore(store.remove(player.id)); // remove the player account from accounts AdminDocumentHandler.commitAccounts(accounts.remove(player.id)); } /** Updates the store with the player transaction */ private void updateStore(PlayerTransaction trans) { store = StoreUpdater.updateStore(store, trans); AdminDocumentHandler.commitStore(store); } /** Updates the accounts with the player transaction */ private void updateAccounts(PlayerTransaction pTrans) { accounts = AccountUpdater.updateAccounts(accounts, pTrans); AdminDocumentHandler.commitAccounts(accounts); } static Runtime runtime = Runtime.getRuntime(); /** Passes the turn to player */ private boolean passTurn(Player player, int roundNum) { out.println(""); out.line("** Player " + player.id.id + ": Team " + player.name + "'s turn"); String fName = AdminConfig.BLACKBOARD_PATH + AdminConfig.PLAYERS_PATH + "/" + player.name; String jcmdline = "java -Xss" + maxStack + " -jar " + player.name + ".jar " + player.id.id + " " + roundNum; String ccmdline = fName+ ".exe " + player.id.id + " " + player.name; String cmdline = jcmdline; // Determine if the player is C# or Java if(!new File(fName + ".jar").exists()){ if(!new File(fName + ".exe").exists()) return false; cmdline = ccmdline; } Process p; long sTime = 0, eTime = 0; try{ sTime = System.currentTimeMillis(); out.playerStart(); p = runtime.exec(cmdline, null, playerDir); StreamWatcher outWatch = new StreamWatcher(p.getInputStream(), out); StreamWatcher errWatch = new StreamWatcher(p.getErrorStream(), out); ProcessWatcher pWatch = new ProcessWatcher(p); pWatch.waitForTimeLimit(config.Time); eTime = System.currentTimeMillis(); Thread.sleep(2000); System.out.flush(); System.err.flush(); outWatch.kill(); errWatch.kill(); out.playerEnd(); out.time("Player " + player.id.id + ": Team " + player.name + " finished", sTime); out.println(out.vspace()+out.vspace()); if ((eTime - sTime) > config.Time){ p.destroy(); return false; } // Catch for p = r.exec(cmdline); }catch(IOException e) { e.printStackTrace(); // Catch for pWatch.waitForTimeLimit(config.Time); }catch (InterruptedException e) { e.printStackTrace(); } return true; } }