import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Vector; /** * GameAnalyser class. * * Main class for analysing of all the plays of the match. * This class holds all the intial plays and rules for the matches * which it tests against. * The player class sends touch details and the Pmode passings the current * state of play. It also uses the ball position to identify where in the field * the ball is. * * @author Akbar Sherwani * @date 27th October * @version 0.7 */ public class GameAnalyser { public Vector kicks; // Keeps the last 20 touches public ArrayList kickcleaned; // Last players public ArrayList modes; // Keeps last 20 changes in playmode public String teaml = ""; // Team name on the left private String teamr = ""; // Team name on the right private String position = "centre"; // Ball position private String playmode = ""; // Last playmode private int time = 0; // Time of the match private int scorel = 0; // Score for left team private int scorer= 0; // Score for right team private boolean pitchbool = true; private boolean halftime = true; private boolean fulltime = false; // Stats booleans controlling what has already been spoken // names are self expantotary private int laststat = 0; private boolean topgoal = true; private boolean busykeeper = true; private boolean score1 = true; private boolean score2 = true; private boolean open = true; private boolean shots = true; private boolean offside = true; private boolean shoton = true; private boolean shotoff = true; private boolean poss = true; // Intial Classes setup from GA private CommentaryProducer cp; public Output out; public Stats stats; public Ball ball; public Logger log; public PitchView pitch; public CrowdManager crowd; public PastGames past; public Goals goals; public GUI gui; public DetailedStats dstats; /** * GameAnalyser * Constructor for Game Analyser Class * @param ball Ball Class * @param gui2 * @param picth PitchView */ public GameAnalyser(Ball ball, PitchView pitch, GUI gui) { // Intialise the classes kicks = new Vector(); kickcleaned = new ArrayList(); modes = new ArrayList(); out = new Output(2, gui); // change to 2 for voice dstats = new DetailedStats(); stats = new Stats(ball, dstats); // Call Stats cp = new CommentaryProducer(out, stats); goals = new Goals(); this.pitch = pitch; pitch.setCP(cp); this.ball = ball; // Add 99 to kicks so last touch can be checked kicks.add(99); // starts logger File file = new File("loglastmatch.txt"); crowd = new CrowdManager(); try { past = new PastGames(); } catch (FileNotFoundException e1) { e1.printStackTrace(); } try { log = new Logger(file); } catch (NullPointerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * timeset * Sets game time * @param int time of game */ public void timeset(int time) { this.time = time; if(time == 1500) { cp.speakMatchTime(1500); } if(time == 2700) { cp.speakMatchTime(2700); } // Insure only spoken on halftime only if(time == 3000 & halftime) { cp.speakMatchTime(2999); dstats.changedOver(); halftime = false; goals.show(); resetStats(); } if(time == 4500) { cp.speakMatchTime(4500); } if(time == 5700) { cp.speakMatchTime(5700); } } /** * PlayerKicked * Registers when a player is kicked (touched the ball) * @param int player number */ public void PlayerKicked(int player_no) { // Call various classes to register kick kicks.add(player_no); pitch.PlayerKick(player_no, time); // Calling main commentary check CommGen(); // Stats call outs if(CheckTeam1(player_no)) { stats.addKickTeam0(); } else { stats.addKickTeam1(); } } /** * PlayModeChange * Registers when the Playmode is changed * @param string play mode string * @throws IOException */ public void PlayModeChange(String mode) throws IOException { // Print Out Mode // System.out.println(mode); // If it was goal get last kicker and add some further commentary if(mode.equals("GOAL")) { int a = GetLastKicker(); if(a == 1 || a == 12) { int b = GetLastKickerI(); int howmany = goals.playerScored(b); // Needs player details to cp cp.speakGoal(true, ball.BallGoal(b),b, (howmany +1)); // Determine goal distance log.write("*Goal Distance " + ball.BallGoal(b), time); // crowd to goal wav file crowd.goal(); // add to goal datbase goals.goalScored(time, b, ball.BallGoal(b), ball.BallGoalPlayer(b), ball.getBallPos()); if(CheckTeam1(b)) { stats.addShotOnTargetTeam0(); } else { stats.addShotOnTargetTeam1(); } } else { int howmany = goals.playerScored(a); cp.speakGoal(false, ball.BallGoal(a), a, (howmany +1)); // write to log log.write("Goal Distance " + ball.BallGoal(a) + " Goal by " + a, time); crowd.goal(); goals.goalScored(time, a, ball.BallGoal(a), ball.BallGoalPlayer(a), ball.getBallPos()); if(CheckTeam1(a)) { stats.addShotOnTargetTeam0(); } else { stats.addShotOnTargetTeam1(); } } } // If Goalkick mention it was close if(mode.startsWith("GoalKick")) { int a = GetLastKickerI(); int distance = goalKick(); // cp.speakShotMissed(a, distance); cp.speakShotMissed(a, distance); log.write("Goal Kick player missed " + a, time); // call crowd files crowd.missedOpportunity(); if(CheckTeam1(a)) { stats.addShotOffTargetTeam0(); } else { stats.addShotOffTargetTeam1();; } } // Before kick off check and check what was result last time if(mode.startsWith("Before Kick") && time == 0) { if((past.getResult(teaml+teamr) == null) && (past.getResult(teamr+teaml) == null)) { // First time they are meeting each other cp.gameStart(teaml, teamr, "", -1); System.out.println("First time they have met"); } else { Matches last = null; // get last results if(past.getResult(teaml+teamr) != null) { last = past.getResult(teaml+teamr); String win = last.getWteam(); int amount = last.getMargin(); if(amount != 0) { System.out.println(win + " won by " + amount); } else { System.out.println("draw last time"); } cp.gameStart(teaml, teamr, win, amount); } if(past.getResult(teamr+teaml) != null) { last = past.getResult(teamr+teaml); String win = last.getWteam(); int amount = last.getMargin(); if(amount != 0) { System.out.println(win + " won by " + amount); } else { System.out.println("draw last time"); } cp.gameStart(teaml, teamr, win, amount); } } } if(mode.startsWith("Time")) { if(scorel == scorer) { cp.speakDraw(goals.getGoals()); crowd.endOfMatch(); // Save match to details past.saveMatch(teaml, teamr, 0); } else if(scorel > scorer) { int winMargin = scorel - scorer; cp.speakWin(teaml, winMargin, goals.getGoals()); past.saveMatch(teaml, teamr, winMargin); } else { int winMargin = scorer - scorel; cp.speakWin(teamr, winMargin, goals.getGoals()); past.saveMatch(teamr, teaml, winMargin); } goals.show(); fulltime = true; } // Corner kick details below if(mode.startsWith("Corner")) { if(GetLastKicker() == 1 || GetLastKicker() == 12) { cp.speakVerticalOut(true); log.write("Corner - off Goalkeeper", time); } else { cp.speakVerticalOut(false); log.write("Corner - off defender", time); } if(mode.equals("CornerKick Left")) { stats.addCornerTeam0(); } else { stats.addCornerTeam1(); } } // Offside check if(mode.startsWith("OffSide")) { cp.speakOffside(); crowd.foul(); // add stats check if(mode.equals("OffSide Left")) { stats.addOffsideTeam0(); } else { stats.addOffsideTeam1(); } } // Ball of pitch check if(mode.startsWith("Kick In")) { // Ball goes out of play cp.speakHorizontalOut(); log.write("Out of play", time); } // FreeKick check if(mode.startsWith("FreeKick")) { if(mode.equals("FreeKick Left")) { cp.speakFreeKick(teaml); log.write("FreeKick to" + teaml, time); } else { cp.speakFreeKick(teamr); log.write("FreeKick to" + teamr, time); } } // restart of game if(mode.startsWith("Play")) { crowd.whistle(); } // Truncate the kicks as change in playmode means details are not needed Truncate(kicks); playmode = mode; } /** * ballPosition * Register the ball movement and whether close to either goal * @param x double x * @param y double y */ public void ballPosition(double x, double y) { String temp; if(x > 22.0) { // Ball is in the right hand side temp = "right"; } else if(x < -22.0) { // Ball is in the left hand side temp = "left"; } else { // otherwise in the center region temp = "center"; statGen(); } if(temp != position) { // To be changed to out etc.. position = temp; if(temp.equals("right") || temp.equals("left")) { cp.speakDefenderPressure(); } // System.out.println("In region " + position); } } /** * teamScores * Gets the team names and scores * @param team1 string team1 * @param x int of team1 * @param team2 string team2 * @param y int of team2 */ public void teamsScores(String team1, int x,String team2, int y) { teaml = team1; teamr = team2; scorel = x; scorer = y; stats.score(scorel, scorer); // Set teams and score // Call to pitchview however kept to minumum for efficeny if(pitchbool) { pitch.setTeams(teaml, teamr); pitchbool = false; gui.getTeam1().setText(teaml); gui.getTeam2().setText(teamr); } } /** * CommGen * Is called and generates comments on the match * Calls the check passes methods when game state is in play * All checks are called from commGen */ public void CommGen() { // Only run if its not fulltime if(!fulltime) { // Gets int value to get last value in arraylist int last = kicks.size() -1; // Gets last and second to last value int tempa = (int) kicks.get(last); int tempb = (int) kicks.get(last -1); // One two check if(CheckOnetwo(tempa)) { // ignore pass check } else { //Pass Check CheckPass(tempa, tempb); } //Dribble check CheckDribble(tempa); //Team passes TeamPasses(tempa); } } /** * CheckPass * Checks if last two touches were on the same team hence it is a pass * @param a int first player * @param b int second player */ public void CheckPass(int a, int b) { // Checks if it was pass and get rid of 99 in arraylist kick if(a != b && (a != 99 && b !=99)) { // Checks if pass was to same team if((a < 12 && b < 12) || ((a < 22 && a > 11)&& (b < 22 && b > 11))) { // Has to be a pass cp.speakPass(b, a, ball.BallPass(a, b), position); } else if(a == 1 || a== 12) { // A shot to goakeeper cp.speakShot(b, ball.BallShot(a, b)); // Stats adding if(CheckTeam1(b)) { stats.addShotOnTargetTeam0(); } else { stats.addShotOnTargetTeam1(); } crowd.missedOpportunity(); } else if(b == 1 || b== 12) { // A Goal Kick not going to own team cp.speakBadGoalKick(); } else { // Lost the ball cp.speakPossessionLost(b); } } } /** * CheckDribble * Checks if last 6 touches are from same player hence a dribble * @param int last player */ public void CheckDribble(int tempa) { // size of array larger than 5 kicks if(kicks.size() > 7) { int x = 0; int y = 0; // Checks last 5 touches if same person while(x < (kicks.size()-1)) { int tempcompare = (int) kicks.get(x); if(tempcompare == tempa) { y ++; } x++; } // Check if last player has touched the ball 5 times if(y == 6) { cp.speakPlayerDribbles(tempa); } } } /** * CheckOnetwo * Checks one two from last touches * @param int last player */ public boolean CheckOnetwo(int tempa) { clean(); // wait untill 3 touches then check if(kickcleaned.size() > 3) { int a = kickcleaned.size() -3; int b = kickcleaned.size() -2; if(tempa == kickcleaned.get(a)) { // B has to be on the same team as A if(sameteam(tempa, kickcleaned.get(b))) { cp.speakOneTwo(tempa, kickcleaned.get(b) ); log.write("One two between " + tempa + " and " + kickcleaned.get(b), time); return true; } else { cp.speakWinsPossession(tempa); } } } return false; } /** * Statskick * Stats testing * @param player int * @param kick int public void Statskick(int player, int kick) { // I have not moved this to the CP as it may need to be moved // into the stats class out.out("Player " + player + " has had " + kick + " shots", OutputVocal.STANDARD_VOICE ); } */ /** * TeamPasses * Passes by same team * @param a int */ public void TeamPasses(int a) { // Wait untill 5 different touches are made if(kickcleaned.size() > 5) { int test = kickcleaned.size() - 1; boolean con1 = sameteam(kickcleaned.get(test-1), a); boolean con2 = sameteam(kickcleaned.get(test-2), kickcleaned.get(test-3)); boolean con3 = sameteam(kickcleaned.get(test-1), kickcleaned.get(test-2)); // check last 3 touches if(con1 && con2 && con3) { // all in same team String team = ""; if(kickcleaned.get(test-1) > 11) { team = teamr; } else { team = teaml; } cp.speakTeamKeepingPossession(team); } } } /** * Truncate * Cleans Kicked Arraylist * @param a arraylist of int */ public void Truncate(Vector a) { int last = kicks.size() -1; int start = 0; while(start < last) { a.remove(start); last = kicks.size() -1; start++; } a.add(99); // Truncate needed to save on resoucres and also help same commentary being said again } /** * GetLastKicker * Gets last kicker on check for goal * @return int */ public int GetLastKicker() { int last = kicks.size() -1; int tempa = (int) kicks.get(last); return tempa; } /** * GetLastKickerI * Gets last kicker on check for goal ignore goakeepers * @return int */ public int GetLastKickerI() { int last = kicks.size() -1; int tempa = (int) kicks.get(last); while(tempa == 1 || tempa == 12) { last = last - 1; tempa = (int) kicks.get(last); } // Ignore keeper to save error on ball position and length return tempa; } /** * clean * Gets different players who touched the ball * Rather than each touches of a player it needs to be find different players who have touched */ public void clean() { // go through Kicks and int temp = 99; int x = 0; kickcleaned.clear(); while(x < (kicks.size() - 1)) { int a = kicks.get(x); if(temp != a) { kickcleaned.add(a); temp = a; } x++; } // Can use hashmap to array method } /** * sameteam * Check on same team * @param a first player * @param b second player */ public boolean sameteam(int a, int b) { if(a <= 11) { if(b <= 11) { return true; } } else { if(b > 11 && b <= 22) { return true; } } return false; } /** * CheckTeam1 * @param a int * @return boolean */ public boolean CheckTeam1(int a) { if(a <= 11) { return true; } else { return false; } // Quick check whether its on the 1st team for stats } /** * GUI set for stats and * @param gui GUI class to add */ public void setGUI(GUI gui) { stats.setGUI(gui); gui.getTeam1().setText(teaml); gui.getTeam2().setText(teamr); this.gui = gui; } /** * How far ball was from goal posts when its a goal kick * @return int distance y */ public int goalKick() { double x = ball.getPosy(); x = Math.abs(x); int distance = 0; if(x > 7.5) { distance = (int) (x - 7.5); } return distance; } /** * Stat Generation * Throws certain stats based on intellgient analsyis to the CP every * 500 mins when ball is in center * Determines them in a intelligent way insuring that its not said more than once * in a half */ public void statGen() { if(time > 500 && (time > (laststat + 500)) && playmode.startsWith("Play")) { // No shots on target yet if(stats.getShotsOnTargetT0() == 0 && stats.getShotsOnTargetT1() == 0 && shoton) { cp.speakStat("Still no shots on target for both teams"); shoton = false; } else if(stats.getShotsOnTargetT0() == 0 && time > 1800 && shots) { cp.speakStat(teaml + " really need a shot on target"); shots = false; } else if(stats.getShotsOnTargetT1() == 0 && time > 1800 && shots) { cp.speakStat(teamr + " really need a shot on target"); shots = false; } else if(scorer > (scorel + 3) && score1) { cp.speakStat("No chance back for " + teaml + ", shooting practise for " + teamr); score1 = false; } else if(scorel > (scorer + 3) && score1) { cp.speakStat("No chance back for " + teamr + ", shooting practise for " + teaml); score1 = false; } else if (scorer == (scorel + 1) && score2) { cp.speakStat(teaml + " can still come back only one goal behind"); score2 = false; } else if (scorel == (scorer + 1) && score2) { cp.speakStat(teamr + " can still come back only one goal behind"); score2 = false; } else if(scorer == scorel && open) { cp.speakStat("Still a open game at the moment great for the crowd"); open = false; } else if((stats.getNumOffsidesT0() + stats.getNumOffsidesT1()) >= 2 && offside) { // Player 11+ check needs to be done cp.speakStat("need to control their runs, too many offsides"); offside = false; } else if(goals.getGoals() != 0 && topgoal) { // Player 11+ check needs to be done cp.speakStat(markupRawPlayer(goals.getGoals()) + " on top form today"); topgoal = false; } else if(stats.getShotsOnTargetT0() > 5 && busykeeper) { cp.speakStat("Busy time for " + teamr + " keeper today"); busykeeper = false; } else if(stats.getShotsOnTargetT1() > 5 && busykeeper) { cp.speakStat("Busy time for " + teaml + " keeper today"); busykeeper = false; } else if(stats.getShotsOffTargetT0() > 1 && stats.getShotsOffTargetT1() > 1 && shotoff) { cp.speakStat("both teams need to get the ball on target, too many off target"); shotoff = false; } else if(stats.getPossT0() > stats.getPossT1() && poss) { cp.speakStat(teaml + " keeping possession more than " + teamr); poss = false; } else if(stats.getPossT1() > stats.getPossT0() && poss) { cp.speakStat(teamr + " keeping possession more than " + teaml); poss = false; } laststat = time; } // Possesion check } /** * resetStats which are to be said */ public void resetStats() { topgoal = true; busykeeper = true; score1 = true; score2 = true; open = true; shots = true; offside = true; shoton = true; shotoff = true; poss = true; } /** * gets Team player * @param rawPlayer * @return string */ private String markupRawPlayer(int rawPlayer) { if(rawPlayer < 12) return "Blue " + rawPlayer; else return "Red " + (rawPlayer - 11); } }