Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/main/java/team/shellsort/input/DataProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package team.shellsort.input;

import java.io.IOException;

/**
* Общий контракт для классов, загружающих данные о машинах
* (например, из файла или случайным образом).
*/
public interface DataProvider {

/**
* Загружает данные о машинах.
*
* @return валидные объекты и исходные строки с ошибками
* @throws IOException для источников I/O (файл/сеть)
*/
LoadResult load() throws IOException;
}
64 changes: 61 additions & 3 deletions src/main/java/team/shellsort/input/FileDataProvider.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,67 @@
package team.shellsort.input;

import team.shellsort.model.Car;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

/**
* Источник данных, читающий записи о машинах из ресурса в classpath.
* <p>Формат строк: <b>Модель;Мощность;Год</b> (UTF-8). Пустые строки игнорируются.</p>
*/
public class FileDataProvider implements DataProvider {

private static final String DEFAULT_RESOURCE = "CarList.txt";

private final Supplier<BufferedReader> readerSupplier;

/** По умолчанию читаем из ресурса {@code CarList.txt}. */
public FileDataProvider() {
this(DEFAULT_RESOURCE);
}

/** Чтение из указанного ресурса classpath. */
public FileDataProvider(String resourceName) {
this.readerSupplier = () -> {
InputStream is = getClass().getClassLoader().getResourceAsStream(resourceName);
if (is == null) throw new UncheckedIOException(new IOException("Resource not found: " + resourceName));
return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
};
}

/** Удобно для тестов: подаём внешний {@link Reader}. */
public FileDataProvider(Reader reader) {
this.readerSupplier = () -> new BufferedReader(reader);
}

@Override
public LoadResult load(int limit) {
// TODO: реализовать чтение данных из файла
return null;
public LoadResult load() throws IOException {
List<Car> valid = new ArrayList<>();
List<String> invalid = new ArrayList<>();
LineParser parser = new LineParser();

try (BufferedReader br = readerSupplier.get()) {
for (String line; (line = br.readLine()) != null; ) {
line = line.trim();
if (line.isEmpty()) continue;

Car car = parser.parse(line); // ожидаем: Модель;Мощность;Год
if (Validator.isValid(car)) valid.add(car);
else invalid.add(line);
}
} catch (UncheckedIOException e) {
// прокидываем исходный IOException
throw e.getCause();
}

return new LoadResult(valid, invalid);
}
}
71 changes: 68 additions & 3 deletions src/main/java/team/shellsort/input/RandomDataProvider.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,74 @@
package team.shellsort.input;

import team.shellsort.model.Car;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.random.RandomGenerator;

/**
* Источник данных, генерирующий случайные записи о машинах.
* Используется для тестирования без внешних источников.
* Поддерживает детерминированную генерацию при передаче seed.
*/
public class RandomDataProvider implements DataProvider {

/** Доступные значения для генерации. */
private static final String[] MODELS = {"Almera", "Focus", "Lancer", "Camry", "Corolla"};
private static final int[] YEARS = {2009, 2010, 2011, 2012, 2013, 2014, 2015};
private static final int[] POWERS = {80, 90, 100, 110, 120, 125, 150, 180, 200, 250, 300};

/** Разделитель для сериализации «битых» строк. */
private static final String SEP = ";";

/** Сколько записей генерировать. */
private final int count;

/** Генератор случайных чисел (может быть детерминированным при заданном seed). */
private final RandomGenerator random;

/** По умолчанию — 10 записей в недетерминированном режиме. */
public RandomDataProvider() {
this(10, null);
}

/** Конструктор с указанием количества записей. */
public RandomDataProvider(int count) {
this(count, null);
}

/** Конструктор с количеством записей и опциональным seed. */
public RandomDataProvider(int count, Long seed) {
if (count < 0) throw new IllegalArgumentException("count must be >= 0");
this.count = count;
this.random = (seed == null) ? ThreadLocalRandom.current() : new Random(seed);
}

@Override
public LoadResult load(int limit) {
// TODO: реализовать генерацию случайных данных
return null;
public LoadResult load() {
List<Car> valid = new ArrayList<>();
List<String> invalid = new ArrayList<>();

for (int i = 0; i < count; i++) {
String model = MODELS[random.nextInt(MODELS.length)];
int year = YEARS[random.nextInt(YEARS.length)];
int power = POWERS[random.nextInt(POWERS.length)];

Car car = new Car.CarBuilder()
.setModel(model)
.setYear(year)
.setPower(power)
.build();

if (Validator.isValid(car)) {
valid.add(car);
} else {
invalid.add(model + SEP + power + SEP + year);
}
}

return new LoadResult(valid, invalid);
}
}