====== Второй семестр ======
===== Тур де Франс =====
Наша задача состоит в том, чтобы написать красивую объектно-ориентированную программу, которая будет заниматься обработкой данных результатов велогонки Тур де Франс. Данные гонки хранятся в трех текстовых файлах.
* {{: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 лучших каждого этапа?
- Кто из участников по своей воле сошел с дистанции и на каких этапах?
- На каких этапах среднее время участников, которые не сошли с дистанции, было самым малым?
- Кто из участников набрал наибольшую среднюю скорость на том или ином этапе, и на каком этапе?
- В какой команде участники двигаются с одинаковой скоростью (т.е. время на этап примерно одинаковое)? Каков разрыв между самым слабым и самым сильными гонщиками команд?