// // @(#)PositionParser.java 1.00 6/2002 // // Copyright 2002 Zachary DelProposto. All rights reserved. // Use is subject to license terms. // // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Or from http://www.gnu.org/ // package dip.judge.parser; import dip.world.Phase; import dip.misc.Utils; import java.io.*; import java.util.regex.*; import java.util.*; /** * * Parses static position list, if present. This is in game listings and also * sometimes in history files (if from the start). * <p> * * * * */ public class PositionParser { // il8n constants private static final String PP_UNKNOWN_PHASE = "JP.posparser.badphase"; /** * Header phrase 1<br> * Capture groups: 1:season 2:year <br> * PhaseType is assumed to be movement. */ public static final String HEADER_REGEX_1 = "(?i)^starting\\s+position\\s+for\\s+([\\p{Alnum}]+)\\s+of\\s+((\\d+))\\."; /** * Header phrase 2<br> * Capture groups: 1:PhaseType 2:SeasonType 3:year<br> */ public static final String HEADER_REGEX_2 = "(?i)^status\\s+of\\s+the\\s+([\\p{Alnum}]+)\\s+phase\\s+for\\s+([\\p{Alnum}]+)\\s+of\\s+(\\d+)\\."; /** * Capture groups: 1:power, 2:unit, 3:province<br> * Note: a space is not always present between the colon and the unit type. */ public static final String PARSE_REGEX = "^([\\p{Alnum}\\-\\_]+):\\s*([\\p{Alnum}\\-\\_]+)\\s+(([^\\.]+))\\."; // instance variables private PositionInfo[] posInfo = null; private Phase phase = null; /* // for testing only public static void main(String args[]) throws IOException, PatternSyntaxException { String in = "sdkflaakdljf fdakjd slkjdfsa klfd\n"+ "dslkafflddfskj fdakjd slkjdfsa klfd\n"+ "kldsjfkdskajfdsak fdakjd slkjdfsa klfd\n"+ "\n"+ // start "Starting position for Spring of 1901.\n"+ //"Status of the Movement phase for Fall of 1906. (realtime.026)\n"+ "\n"+ "Argentina:Army Santa Cruz.\n"+ "Argentina:Fleet Buenos Aires.\n"+ "Argentina:Fleet Chile.\n"+ "\n"+ "Brazil: Army Brasilia.\n"+ "Brazil: Army Rio de Janeiro.\n"+ "Brazil: Fleet Recife.\n"+ "\n"+ "Oz: Fleet New South Wales.\n"+ "Oz: Fleet Victoria.\n"+ "Oz: Fleet Western Australia.\n"+ "\n"+ "The deadline for the first movement orders is Tue Dec 4 2001 23:30:00 PST.\n"+ // ending text "The next phase of 'ferret' will be Movement for Fall of 1901.\n"+ "The deadline for orders will be Tue Jan 22 2002 23:30:00 -0500.\n"; PositionParser pp = new PositionParser(in); PositionInfo[] pi = pp.getPositionInfo(); System.out.println("# of orders: "+pi.length); System.out.println("phase: "+pp.getPhase()); for(int i=0; i<pi.length; i++) { System.out.println(" "+pi[i]); } }// main() // end testing method */ /** Parses the input for Position information, if any is present. */ public PositionParser(String input) throws IOException, PatternSyntaxException { parseInput(input); }// PositionParser() /** Returns PositionInfo, or a zero-length array */ public PositionInfo[] getPositionInfo() { return posInfo; }// getPositionInfo() /** Returns the Phase; this will be null if getPositionInfo() is a zero-length array */ public Phase getPhase() { return phase; }// getPhase() /** Details the position information */ public static class PositionInfo { private final String power; private final String unit; private final String location; /** Creates a PositionInfo object */ public PositionInfo(String power, String unit, String location) { this.power = power; this.unit = unit; this.location = location; }// PositionInfo() /** Gets the Power */ public String getPowerName() { return power; } /** Gets the Unit */ public String getUnitName() { return unit; } /** Gets the location name */ public String getLocationName() { return location; } /** For debugging only; this may change between versions. */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("PositionInfo[power="); sb.append(power); sb.append(",unit="); sb.append(unit); sb.append(",location="); sb.append(location); sb.append(']'); return sb.toString(); }// toString() }// nested class PositionInfo /** * Parses the input; looks for the appropriate header. Then parses the position list * until no more positions can be found. */ private void parseInput(String input) throws IOException, PatternSyntaxException { // search for header input. once found, shuttle all input to the appropriate // handler type. Pattern pp1 = Pattern.compile(HEADER_REGEX_1); Pattern pp2 = Pattern.compile(HEADER_REGEX_2); // init List posList = new LinkedList(); BufferedReader br = new BufferedReader(new StringReader(input)); // header parse loop String line = ParserUtils.getNextLongLine(br); while(line != null) { Matcher m = pp1.matcher(line); if(m.lookingAt()) { phase = makePhase(null, m.group(1), m.group(2)); parsePositions(br, posList); break; } m = pp2.matcher(line); if(m.lookingAt()) { phase = makePhase(m.group(1), m.group(2), m.group(3)); parsePositions(br, posList); break; } line = ParserUtils.getNextLongLine(br); } // cleanup & create array br.close(); posInfo = (PositionInfo[]) posList.toArray(new PositionInfo[posList.size()]); }// parseInput() /** Parses the positions. */ private void parsePositions(BufferedReader br, List posList) throws IOException, PatternSyntaxException { Pattern mrp = Pattern.compile(PARSE_REGEX); String line = ParserUtils.getNextLongLine(br); while(line != null) { Matcher m = mrp.matcher(line); if(m.find()) { posList.add( new PositionInfo(m.group(1), m.group(2), ParserUtils.filter(m.group(3))) ); } else { // parse failed; break out of loop break; } line = ParserUtils.getNextLongLine(br); } }// parsePositions() /** Makes the phase; throws an exception if we cannot. */ private Phase makePhase(String phaseType, String seasonType, String year) throws IOException { phaseType = (phaseType == null) ? "Movement" : phaseType; StringBuffer sb = new StringBuffer(); sb.append(phaseType); sb.append(' '); sb.append(seasonType); sb.append(' '); sb.append(year); try { return Phase.parse(sb.toString()); } catch(Exception e) { throw new IOException(Utils.getLocalString(PP_UNKNOWN_PHASE, sb.toString())); } }// makePhase() }// class PositionParser