/* * ConcreteSplitViewer program for analazing splits. * Copyright (C) 2006-2007 Mytinski Leonid (Leonid.Mytinski@gmail.com) * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ /* * OCT2007Reader.java * * Created on 08 October 2007, 19:52 * */ package ru.concretesoft.concretesplitviewer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author Valeri Mytinski * * Reader of so called "OCT2007" format files. * OCT2007 has no formal specification at the moment. * St.Petersburg people just started to use it in september or october 2007 without any * agreement or preliminary discussions. * I write it on base of examination several such files. * * We count file as OCT2007 if it consists of series "athlete-patterns". * Athlete-pattern is three lines like these: * 1 206 МАВЧУН ГЕОРГИЙ 2000 кмс СПбГУ 33:58 04:16 05:17 06:30 08:27 13:50 20:01 22:55 29:37 31:12 32:14 * 04:16 01:01 01:13 01:57 05:23 06:11 02:54 06:42 01:35 01:02 * ------------------------------------------------------------------------------------------------------------------------------------------------------------- * */ public class OCT2007Reader extends SplitReader{ private File file; private FileInputStream fIS; private String all; private String nameOfComp; private Vector<String> groupsNames; private Vector<Group> allGroups; private String encoding = "CP1251"; private int version = 0; // 0 - unknown version private String eventDescription = ""; // Event description if it presents in file // Number of points in a group = number of times in the first line for first athlete in a group private int numberOfPoints = 0; /** * Creates a new instance of OCT2007Reader * * @param file splits file * @throws java.io.IOException * @throws ru.concretesoft.concretesplitviewer.NotRightFormatException */ public OCT2007Reader(File file) throws IOException, NotRightFormatException { this.file=file; fIS = new FileInputStream(file); int length = (int)file.length(); byte[] s = null; try { s = new byte[length]; } catch (java.lang.OutOfMemoryError e) { throw new IOException("File too long to fit into memory."); } fIS.read(s); try{ all=new String(s,encoding); } catch(UnsupportedEncodingException e){ all = ""; } /* * Check if there are two "athlete-pattern" - one just after another - * in the file. * If yes, it seems OCT2007 format. * If no, we will not parse file. */ String firstLineOfPattern = "[ \\t]*\\d+[ \\t]+\\d+[ \\t\\S]*([ \\t]+(\\d{1,2}:)?\\d\\d:\\d\\d)+[ \\t]*"; String secondLineOfPattern = "([ \\t]+(\\d{1,2}:)?\\d\\d:\\d\\d)+[ \\t]*"; String thirdLineOfPattern = "---+[ \\t]*"; Pattern hyphenPattern = Pattern.compile(thirdLineOfPattern + "\\r\\n"); Matcher hyphenMatcher = hyphenPattern.matcher(all); Pattern athletePattern = Pattern.compile(firstLineOfPattern + "\\r\\n" + secondLineOfPattern + "\\r\\n" + thirdLineOfPattern + "\\r\\n"); Matcher athleteMatcher = athletePattern.matcher(all); if (!hyphenMatcher.find()) { throw new NotRightFormatException(file, "OCT2007", "it not contains line of hyphens"); } else { if (!athleteMatcher.find()) { throw new NotRightFormatException(file, "OCT2007", "it not contains athlete pattern"); } else { if (!athleteMatcher.find(athleteMatcher.end())) { throw new NotRightFormatException(file, "OCT2007", "it not contains two sequential athlete pattern"); } } } /* * OK. It seems OCT2007 format. * Try to parse it. */ Pattern groupPattern = Pattern.compile("^\\s+([^-\\s:]+)\\s*(\\r\\n)+", Pattern.MULTILINE); Matcher groupMatcher = groupPattern.matcher(all); groupsNames = new Vector<String>(); allGroups = new Vector<Group>(); /* * Find group pattern, find next group pattern (or end of text) * Then find all athlete patterns between them. */ int groupPatternIndex = 0; while (groupMatcher.find(groupPatternIndex)) { // New group begins allGroups.add(new Group()); // Store it's name String groupName = groupMatcher.group(1); groupsNames.add(groupName); allGroups.lastElement().setName(groupName); // Parse athletes in group int curIndex = groupMatcher.start(); int endIndex = 0; if (groupMatcher.find(groupMatcher.end())) { endIndex = groupMatcher.start(); } else { endIndex = all.length() - 1; } numberOfPoints = 0; boolean athleteFinded = true; while ((curIndex < endIndex) && (athleteFinded)) { athleteFinded = false; if (athleteMatcher.find(curIndex)) { curIndex = athleteMatcher.start(); if (curIndex < endIndex) { // Parse athlete parseAthlete(athleteMatcher.group(), allGroups.lastElement()); athleteFinded = true; curIndex = athleteMatcher.end(); } } } //Remove group if it doesn't have athletes if(allGroups.lastElement().getAthletes().size() == 0){ allGroups.remove(allGroups.lastElement()); groupsNames.remove(groupsNames.lastElement()); }else{ // Store group's distance int groupDistance = 5000; Distance d = new Distance(groupName, groupDistance, numberOfPoints); allGroups.lastElement().setDistance(d); d.setLengthsOfDists(Tools.calculatLengthsOfLaps(d.getGroups())); } groupPatternIndex = endIndex; } } /** * Parse string for athlete information. * Create new athlete and add it to group. * * @param s String - three lines - to parse * @param g Group for new athlete */ private void parseAthlete(String s, Group g) { String[] lines = s.split("\\r\\n"); // 1-st line is like // 1 206 МАВЧУН ГЕОРГИЙ 2000 кмс СПбГУ 33:58 04:16 05:17 06:30 08:27 13:50 20:01 22:55 29:37 31:12 32:14 // 2-nd line is like // 04:16 01:01 01:13 01:57 05:23 06:11 02:54 06:42 01:35 01:02 // 3-d line is like // ------------------------------------------------------------------------------------------------------------------------------------------------------------- // Catch last and first names from 1-st line - 3-d and 4-th words. String[] words = lines[0].trim().split("\\s++"); String lastName = words[2]; String firstName = words[3]; String athleteResult = "24:00:00"; // Then find first word that matches time pattern - it is the result time int firstTimeIndex = 3; while (firstTimeIndex < words.length) { if (words[firstTimeIndex].matches("(\\d{1,2}:)?\\d\\d:\\d\\d")) { athleteResult = words[firstTimeIndex]; break; } firstTimeIndex++; } // Set or check number of points if (numberOfPoints == 0) { // This is first athlete in the group. Set number of points numberOfPoints = words.length - firstTimeIndex; } else { // Check number of points for all others athlete if ((words.length - firstTimeIndex) != numberOfPoints) { // Possible reasons: DSQ, ... return; } } /* * This crazy format does not contain finish split time. * We must calculate it. * We are finding last word - time on pre-finish point. * Then subtract it from finish time, result is finish split time. */ String preFinishTime = words[words.length -1]; String finishSplit = secondsToString(stringToSeconds(athleteResult) - stringToSeconds(preFinishTime)); // Now catch split times from third line String[] splits = lines[1].trim().split("\\s++"); // Create array of all splits Time[] athleteSplits = new Time[splits.length + 1]; // Fill array with splits... for (int i = 0; i < splits.length; i++) { String[] fields = splits[i].split(":"); athleteSplits[i] = new Time(splits[i], fields.length); } // ...and with finish split String[] fields = finishSplit.split(":"); athleteSplits[athleteSplits.length - 1] = new Time(finishSplit, fields.length); // U-u-ph Athlete a = new Athlete(lastName, firstName, athleteSplits, allGroups.lastElement(), 1900, athleteResult); } private int stringToSeconds(String s) { String[] hhmmss = s.trim().split(":"); int seconds = 0; for (int i = 0; i < hhmmss.length; i++) { seconds = 60 * seconds + Integer.parseInt(hhmmss[i]); } return seconds; } private String secondsToString(int seconds) { int h,m,s; s = seconds; h = s / 3600; s = s - 3600*h; m = s / 60; s = s - 60*m; return (h>0?String.format("%02d:",h):"")+String.format("%02d:",m)+String.format("%02d",s); } public Vector<String> getGroupsNames() { return groupsNames; } public Vector<Group> getAllGroups() { return allGroups; } public Group getGroup(String name) { int index = groupsNames.indexOf(name); return allGroups.get(index); } public Group getGroup(int number) { return allGroups.get(number); } public Vector<Group> getGroupsByDist(int number) { return null; } public String getFileName() { return file.getName(); } public String getEventDescription() { return eventDescription; } }