#9 -- add validation
This commit is contained in:
parent
430d9496fb
commit
03a9abb428
@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.ulstu.configuration.ApiConfiguration;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.db.DbService;
|
||||
import ru.ulstu.db.model.TimeSeriesMeta;
|
||||
@ -52,29 +53,29 @@ public class DbController {
|
||||
}
|
||||
|
||||
@GetMapping("add-time-series-set")
|
||||
public void addTimeSeriesSet(@RequestParam("setKey") String setKey) {
|
||||
dbService.addSet(setKey);
|
||||
public boolean addTimeSeriesSet(@RequestParam("setKey") String setKey) {
|
||||
return dbService.addSet(setKey);
|
||||
}
|
||||
|
||||
@PostMapping("add-time-series")
|
||||
public void addTimeSeries(@RequestParam("setKey") String setKey, @RequestBody TimeSeries timeSeries) throws IOException {
|
||||
public void addTimeSeries(@RequestParam("setKey") String setKey, @RequestBody TimeSeries timeSeries) throws IOException, ModelingException {
|
||||
dbService.addTimeSeries(new TimeSeriesSet(setKey), timeSeries);
|
||||
}
|
||||
|
||||
@PostMapping("add-time-series-string")
|
||||
public void addTimeSeries(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey, @RequestBody String timeSeries) throws IOException {
|
||||
public void addTimeSeries(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey, @RequestBody String timeSeries) throws IOException, ModelingException {
|
||||
TimeSeries timeSeriesWithKey = utilService.getTimeSeriesFromString(timeSeries);
|
||||
timeSeriesWithKey.setKey(timeSeriesKey);
|
||||
dbService.addTimeSeries(new TimeSeriesSet(setKey), timeSeriesWithKey);
|
||||
}
|
||||
|
||||
@DeleteMapping("delete-time-series")
|
||||
public void deleteTimeSeries(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey) throws IOException {
|
||||
dbService.deleteTimeSeries(new TimeSeriesSet(setKey), timeSeriesKey);
|
||||
public boolean deleteTimeSeries(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey) throws IOException {
|
||||
return dbService.deleteTimeSeries(new TimeSeriesSet(setKey), timeSeriesKey);
|
||||
}
|
||||
|
||||
@DeleteMapping("delete-time-series-set")
|
||||
public void deleteTimeSeriesSet(@RequestParam("setKey") String setKey) throws IOException {
|
||||
dbService.deleteTimeSeriesSet(new TimeSeriesSet(setKey));
|
||||
public boolean deleteTimeSeriesSet(@RequestParam("setKey") String setKey) throws IOException {
|
||||
return dbService.deleteTimeSeriesSet(new TimeSeriesSet(setKey));
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,12 @@ package ru.ulstu.db;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.db.model.TimeSeriesMeta;
|
||||
import ru.ulstu.db.model.TimeSeriesSet;
|
||||
import ru.ulstu.service.UtilService;
|
||||
import ru.ulstu.service.ValidationUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
@ -72,17 +74,18 @@ public class DbFileService implements DbService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSet(String key) {
|
||||
public boolean addSet(String key) {
|
||||
TimeSeriesSet timeSeriesSet = new TimeSeriesSet(key);
|
||||
if (isTimeSeriesSetExists(timeSeriesSet)) {
|
||||
throw new RuntimeException(String.format("Time series set %s already exists", timeSeriesSet.getKey()));
|
||||
} else {
|
||||
Paths.get(timeSeriesDbPath, timeSeriesSet.getKey()).toFile().mkdirs();
|
||||
return Paths.get(timeSeriesDbPath, timeSeriesSet.getKey()).toFile().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTimeSeries(TimeSeriesSet timeSeriesSet, TimeSeries timeSeries) throws IOException {
|
||||
public void addTimeSeries(TimeSeriesSet timeSeriesSet, TimeSeries timeSeries) throws IOException, ModelingException {
|
||||
ValidationUtils.validateTimeSeries(timeSeries);
|
||||
if (!isTimeSeriesSetExists(timeSeriesSet)) {
|
||||
addSet(timeSeriesSet.getKey());
|
||||
}
|
||||
@ -100,16 +103,17 @@ public class DbFileService implements DbService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTimeSeries(TimeSeriesSet set, String timeSeriesKey) throws IOException {
|
||||
public boolean deleteTimeSeries(TimeSeriesSet set, String timeSeriesKey) throws IOException {
|
||||
validateDb(set, timeSeriesKey);
|
||||
Files.delete(getTimeSeriesFile(set, timeSeriesKey).toPath());
|
||||
Files.delete(getTimeSeriesMetaFile(set, timeSeriesKey).toPath());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTimeSeriesSet(TimeSeriesSet timeSeriesSet) {
|
||||
public boolean deleteTimeSeriesSet(TimeSeriesSet timeSeriesSet) {
|
||||
validateDb(timeSeriesSet);
|
||||
deleteDirectory(getSetPath(timeSeriesSet));
|
||||
return deleteDirectory(getSetPath(timeSeriesSet));
|
||||
}
|
||||
|
||||
private void validateDb(TimeSeriesSet timeSeriesSet, String timeSeriesKey) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package ru.ulstu.db;
|
||||
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.db.model.TimeSeriesMeta;
|
||||
import ru.ulstu.db.model.TimeSeriesSet;
|
||||
@ -20,11 +21,11 @@ public interface DbService {
|
||||
|
||||
TimeSeries getTimeSeries(TimeSeriesSet timeSeriesSet, String timeSeriesKey) throws IOException;
|
||||
|
||||
void addSet(String key);
|
||||
boolean addSet(String key);
|
||||
|
||||
void addTimeSeries(TimeSeriesSet timeSeriesSet, TimeSeries timeSeries) throws IOException;
|
||||
void addTimeSeries(TimeSeriesSet timeSeriesSet, TimeSeries timeSeries) throws IOException, ModelingException;
|
||||
|
||||
void deleteTimeSeries(TimeSeriesSet set, String timeSeriesKey) throws IOException;
|
||||
boolean deleteTimeSeries(TimeSeriesSet set, String timeSeriesKey) throws IOException;
|
||||
|
||||
void deleteTimeSeriesSet(TimeSeriesSet timeSeriesSet) throws IOException;
|
||||
boolean deleteTimeSeriesSet(TimeSeriesSet timeSeriesSet) throws IOException;
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ import ru.ulstu.TimeSeriesUtils;
|
||||
import ru.ulstu.datamodel.Model;
|
||||
import ru.ulstu.datamodel.exception.ForecastValidateException;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.exception.TimeSeriesValidateException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.service.ValidationUtils;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
@ -44,7 +44,7 @@ public abstract class Method {
|
||||
* @throws ModelingException генерируется, если есть проблемы моделирования при задании параметров
|
||||
*/
|
||||
public Model getModel(TimeSeries timeSeries, List<MethodParamValue> parameters) throws ModelingException {
|
||||
validateTimeSeries(timeSeries);
|
||||
ValidationUtils.validateTimeSeries(timeSeries);
|
||||
validateAdditionalParams(timeSeries, parameters);
|
||||
return getModelOfValidTimeSeries(timeSeries, parameters);
|
||||
}
|
||||
@ -60,7 +60,7 @@ public abstract class Method {
|
||||
|
||||
public boolean canMakeForecast(TimeSeries timeSeries, List<MethodParamValue> parameters, int countPoints) {
|
||||
try {
|
||||
validateTimeSeries(timeSeries);
|
||||
ValidationUtils.validateTimeSeries(timeSeries);
|
||||
validateAdditionalParams(timeSeries, parameters);
|
||||
validateForecastParams(countPoints);
|
||||
} catch (ModelingException ex) {
|
||||
@ -71,7 +71,7 @@ public abstract class Method {
|
||||
|
||||
public boolean canMakeModel(TimeSeries timeSeries, List<MethodParamValue> parameters) {
|
||||
try {
|
||||
validateTimeSeries(timeSeries);
|
||||
ValidationUtils.validateTimeSeries(timeSeries);
|
||||
validateAdditionalParams(timeSeries, parameters);
|
||||
} catch (ModelingException ex) {
|
||||
return false;
|
||||
@ -112,21 +112,6 @@ public abstract class Method {
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateTimeSeries(TimeSeries timeSeries) throws ModelingException {
|
||||
if (timeSeries == null || timeSeries.isEmpty()) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен быть не пустым");
|
||||
}
|
||||
if (timeSeries.getLength() < 2) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен содержать хотя бы 2 точки");
|
||||
}
|
||||
if (timeSeries.getValues().stream().anyMatch(val -> val == null || val.getValue() == null)) {
|
||||
throw new TimeSeriesValidateException("Временной ряд содержит пустые значения");
|
||||
}
|
||||
if (timeSeries.getValues().stream().anyMatch(val -> val.getDate() == null)) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен иметь отметки времени");
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateAdditionalParams(TimeSeries timeSeries, List<MethodParamValue> parameters) throws ModelingException {
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class ScoreMethod {
|
||||
private final String name;
|
||||
@ -31,13 +32,10 @@ public abstract class ScoreMethod {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected TimeSeriesValue getValueOnSameDate(TimeSeriesValue timeSeriesValueToFind, TimeSeries timeSeries) throws ModelingException {
|
||||
return timeSeries.getValues()
|
||||
.stream()
|
||||
.filter(v -> v.getDate().equals(timeSeriesValueToFind.getDate()))
|
||||
.findAny()
|
||||
protected Double getValueOnSameDate(Map<LocalDateTime, Double> tsValues, TimeSeriesValue modelValue) throws ModelingException {
|
||||
return Optional.ofNullable(tsValues.get(modelValue.getDate()))
|
||||
.orElseThrow(() -> new ModelingException("Значение модельного ряда не найдено в оригинальном ряде: "
|
||||
+ timeSeriesValueToFind.getDate()
|
||||
+ " " + timeSeries));
|
||||
+ modelValue.getDate()
|
||||
+ " " + tsValues));
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
@ -25,10 +24,7 @@ public class Smape extends ScoreMethod {
|
||||
public Number evaluate(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException {
|
||||
double sum = 0;
|
||||
for (TimeSeriesValue modelValue : model.getValues()) {
|
||||
//double actualValue = getValueOnSameDate(modelValue, original).getValue();
|
||||
double actualValue = Optional.ofNullable(tsValues.get(modelValue.getDate()))
|
||||
.orElseThrow(() -> new ModelingException("Значение модельного ряда не найдено в оригинальном ряде: "
|
||||
+ modelValue.getDate()));
|
||||
double actualValue = getValueOnSameDate(tsValues, modelValue);
|
||||
sum += abs(modelValue.getValue() - actualValue)
|
||||
/ ((abs(actualValue) + abs(modelValue.getValue())) / 2);
|
||||
}
|
||||
|
@ -59,8 +59,7 @@ public class MethodParamBruteForce {
|
||||
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||
if (methodInstance.canMakeForecast(reducedTimeSeries, parametersValues, countPoints)) {
|
||||
results.add(executors.submit(() -> {
|
||||
TimeSeries forecast = methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints);
|
||||
forecast = syncDates(forecast, timeSeries);
|
||||
TimeSeries forecast = syncDates(methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints), timeSeries);
|
||||
return new ModelingResult(forecast, null,
|
||||
parametersValues,
|
||||
scoreMethod.getScore(tsValues, forecast),
|
||||
|
36
src/main/java/ru/ulstu/service/ValidationUtils.java
Normal file
36
src/main/java/ru/ulstu/service/ValidationUtils.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
||||
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||
*
|
||||
*/
|
||||
|
||||
package ru.ulstu.service;
|
||||
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.exception.TimeSeriesValidateException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class ValidationUtils {
|
||||
public static void validateTimeSeries(TimeSeries timeSeries) throws ModelingException {
|
||||
if (timeSeries == null || timeSeries.isEmpty()) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен быть не пустым");
|
||||
}
|
||||
if (timeSeries.getLength() < 2) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен содержать хотя бы 2 точки");
|
||||
}
|
||||
if (timeSeries.getValues().stream().anyMatch(val -> val == null || val.getValue() == null)) {
|
||||
throw new TimeSeriesValidateException("Временной ряд содержит пустые значения");
|
||||
}
|
||||
if (timeSeries.getValues().stream().anyMatch(val -> val.getDate() == null)) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен иметь отметки времени");
|
||||
}
|
||||
|
||||
if (timeSeries.getValues().stream().map(TimeSeriesValue::getDate).collect(Collectors.toSet()).size() < timeSeries.getLength()) {
|
||||
throw new TimeSeriesValidateException("Временной ряд должен иметь разные отметки времени");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user