====== Второй семестр ====== ===== Тур де Франс ===== Наша задача состоит в том, чтобы написать красивую объектно-ориентированную программу, которая будет заниматься обработкой данных результатов велогонки Тур де Франс. Данные гонки хранятся в трех текстовых файлах. * {{:java:tdf14_ranks.txt|}} * {{:java:tdf14_stages.txt|}} * {{:java:tdf14_teams.txt|}} **Файл 1** tdf14_teams.txt В нем перечислены участники и команды. В каждой строке файла хранится запись вида: национальность фамилия имя год_рождения номер команда Например SUI ALBASINI Michael 1980 182 ORICA GREENEDGE Каждый участник однозначно идентифицируется по своему имени, а команда по названию (т.е. дубликатов нет) **Файл 2** tdf14_stages.txt В нем перечислены этапы гонки в виде: номер_этапа дата место_отправления место_прибытия дистанция Например 1 05/07/14 Leeds Harrogate 190 **Файл 3** tdf14_ranks.txt В этом файле содержатся рейтинги участников на разных этапах. Каждая строка содержит следующее: Номер_этапа место_участника номер_участника время_участника Участники, сошедшие с дистанции во время этапа с номером i, где (1 ≤ i ≤ 21) исключены из рейтингов для всех последующих этапов. Пример строки 1 198 76 04:58:16 Класс-обертка для чтения из файла прилагается. import java.io.*; public class ReadData { private BufferedReader reader; // читатель из файла /** * Конструктор. */ public ReadData() { reader = null; } /** * открывает текстовый файл * @param fileName имя файла * @return true если открыли успешно, false иначе. */ public boolean open(String fileName) { try { FileReader fr = new FileReader(fileName); reader = new BufferedReader(fr); return true; } catch(IOException ex) { return false; } } /** * Читает строку из файла, открытого методом open() * @return прочитанная строка или null, если прочитать не удалось */ public String readLine() { try { return reader.readLine(); } catch(IOException ex) { return null; } } /** * Закрывает файл */ public void close() { if (reader != null) { try { reader.close(); } catch(IOException ex) { } } } } Работа делится на две части. Первая заключается в создании системы классов и объектов для представления данных и начальном заполнении их информацией из файла. Вторая в статистической обработке данных. ==== Часть 1 ==== Наша задача состоит в обработке файла tdf14_teams.txt. Для этого требуется создать следующие 4 класса. * **Racer** У нашего участника есть имя, фамилия, национальность, год рождения и номер участия. В классе должны быть необходимые геттеры и сеттеры, а так же метод int age(int year), который позволяет вычислить возраст участника, год передается в качестве параметра (например 2014) public class Racer { String name; String surname; String nationality; int yearOfBirth; int number; public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public int getYearOfBirth() { return yearOfBirth; } public void setYearOfBirth(int year) { this.yearOfBirth = year; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return this.suername; } public void setSurname(String surname) { this.surname = surname; } public String getNationality() { return this.nationality; } public void setNationality(String nationality) { this.nationality = nationality; } public int age(int year) { return year - yearOfBirth; } } * **Team** Команда имеет название и список участников. Должны быть реализованы следующие методы: * Team(String name) конструктор, который принимает в качестве аргумента название команды. Список гонщиков инициализируется пустным списком * void insert(Racer racer) добавляет гонщика в команду * String getName() геттер для названия команды * int numberOfRacers() возвращает количество гонщиков в команде * Racer getRacers(int i) возвращает гонщика по номеру. Нумерация идет с нуля. * int totalAge(int year) возвращает суммарный возраст участников. Год передается в качестве параметра. public class Team { String name; ArrayList racers; public Team(String name) { this.name = name; racers = new ArrayList(); } public void insert(Racer racer) { racers.add(racer); } public String getName() { return this.name; } public int numberOfRacers() { return racers.size(); } public Racer getRacers(int i) { return racers.get(i); } public int totalAge(int year) { int sum = 0; for(Racer racer : racers) { sum = sum + racer.totalAge(year); } return sum; } } * **TeamsList** Класс для списка команд. Должны быть реализованы следующие методы: * TeamsList() конструктор, инициализирующий список команд пустым списком. * void insert(Team team) добавляет команду в общий список. * Team getTeam(String teamName) возвращает команду по ее названию. Если такой команды не найдено, должен возвращаться null. * int numberOfTeams() возвращает количество команд * Team getTeam(int i) возвращает i-ю команду. Нумерация с нуля. * **TourDeFrance** главный класс программы, содержащий метод main. В этом классе должны выполнятся вызовы методов для чтения данных о велосипедистах, создаваться необходимые объекты (участники, команды, список команд), показываться информация о командах и их участниках. После чтения данных и заполнения объектов нужно ответить на вопрос: каков средний возраст участников Тур де Франс 2014. Ответ округлить до двух знаков после запятой. Набросок для этого класса приведен далее. public class TourDeFrance { /** * Метод для создания гонщика, на основани файла с списком гонщиков/команд * @param line одна строка из файла * @param teamsList список команд, который заполняется на основании строки из файла */ public static void parceTeamLine(String line, TeamsList teamsList) { // Элементы в строках нашего файла разделени знаками табуляции, их мы // и будем использовать чтобы отличить один элемет от другого. String[] elem = line.split("\t"); // Информация о гонщике String nat = elem[0]; String racerFamilyName = elem[1]; String racerName = elem[2]; int year = Integer.parseInt(elem[3]); int number = Integer.parseInt(elem[4]); String teamName = elem[5]; // TODO Найти команду по имени в списке // TODO Если не найдено, то создать команду и добавить в список // TODO Создать гонщика и добавить в команду } /** * Метод для создания команд * @param fileName Имя файла для команд * @param teamsList список команд * @return если чтение данных прошло успешно, то возвращается true (это значит, * что все команды/участники прочитаны и занесены в список) * В противном случае возвращается false */ public static boolean createTeams(String fileName, TeamsList teamsList) { // Объект, связанный с файлом, откуда мы будем построчно читать данные ReadData reader = new ReadData(); if (reader.open(fileName)) { // Пропустим заголовок String line = reader.readLine(); // Обработаем строку для добавления в список while ((line = reader.readLine()) != null) { parceTeamLine(line, teamsList); } reader.close(); return true; // все прошло хорошо } else { return false; // или плохо } } /** * Главный метод * @param args аргументы командной строки */ public static void main(String[] args) { final int currentYear = 2014; final String teamsFileName = "tdf14_teams.txt"; // TODO Создать список команд (и инициализировать!) // Обработка файла с командами boolean res = createTeams(teamsFileName, temsList); if (!res) { System.out.println("Произошла ошибка с чтением списка команд"); } else { // TODO Оставшаяся часть программы (вывести данные, чтобы удостовериться в корректном чтении файла, // вычислить средний возраст участников и т.д. } } } ==== Часть 2 ==== Задача – это обработать файлы tdf14_stages.txt and tdf14_ranks.txt чтобы ответить на различные вопросы, к примеру: - Какова общая дистанция, которую проехали гонщики? А средняя? - Найти самый длинный и самый короткий этапы - Кто выиграл этап, который начинается в городе Mulhouse? Кто выиграл этап, который заканчивается в городе Risoul? Кто выиграл этап 14 июля? - Какова тройка победителей 2014 года? Какова общая таблица зачета? - Какое общее время потребовалось участникам команды FDJ.FR на завершение гонки? И какое общее время, для 3 лучших каждого этапа? - Кто из участников по своей воле сошел с дистанции и на каких этапах? - На каких этапах среднее время участников, которые не сошли с дистанции, было самым малым? - Кто из участников набрал наибольшую среднюю скорость на том или ином этапе, и на каком этапе? - В какой команде участники двигаются с одинаковой скоростью (т.е. время на этап примерно одинаковое)? Каков разрыв между самым слабым и самым сильными гонщиками команд?