diff --git a/src/main/java/ru/ulstu/TimeSeriesUtils.java b/src/main/java/ru/ulstu/TimeSeriesUtils.java new file mode 100644 index 0000000..d79e422 --- /dev/null +++ b/src/main/java/ru/ulstu/TimeSeriesUtils.java @@ -0,0 +1,35 @@ +package ru.ulstu; + +import ru.ulstu.models.TimeSeries; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +public class TimeSeriesUtils { + /** + * Вычисляет среднее значение между датами временного ряда + * + * @param timeSeries объект, содержащий временной ряд + * @return средняя разница между датами исходного временного ряда в миллисекундах + */ + public static long getTimeDifferenceInMilliseconds(TimeSeries timeSeries) { + long diffMilliseconds = 0; + for (int i = 1; i < timeSeries.getLength(); i++) { + diffMilliseconds += timeSeries.getValues().get(i - 1).getDate() + .until(timeSeries.getValues().get(i).getDate(), ChronoUnit.MILLIS); + } + return diffMilliseconds / (timeSeries.getLength() - 1); + } + + public static TimeSeries fillDates(TimeSeries timeSeries, long milliseconds) { + timeSeries.getLastValue().setDate(LocalDateTime.now()); + for (int i = timeSeries.getLength() - 2; i >= 0; i--) { + timeSeries.getValues().get(i).setDate(timeSeries.getValues().get(i + 1).getDate().minus(milliseconds, ChronoUnit.MILLIS)); + } + return timeSeries; + } + + public static TimeSeries fillDates(TimeSeries timeSeries) { + return fillDates(timeSeries, 1000 * 60 * 60 * 24); + } +} diff --git a/src/main/java/ru/ulstu/controllers/TimeSeriesController.java b/src/main/java/ru/ulstu/controllers/TimeSeriesController.java index 86c1752..835cbea 100644 --- a/src/main/java/ru/ulstu/controllers/TimeSeriesController.java +++ b/src/main/java/ru/ulstu/controllers/TimeSeriesController.java @@ -38,6 +38,18 @@ public class TimeSeriesController { return new ResponseEntity<>(timeSeriesService.getRandomTimeSeries(length), HttpStatus.OK); } + @GetMapping("getFromString") + @ApiOperation("Преобразовать строку с разделителями во временной ряд") + public ResponseEntity getTimeSeriesFromString(@RequestParam("tsString") String tsString) { + return new ResponseEntity<>(timeSeriesService.getTimeSeriesFromString(tsString), HttpStatus.OK); + } + + @PostMapping("timeSeriesToString") + @ApiOperation("Преобразовать временной ряд в строку с разделителями") + public ResponseEntity getTimeSeriesToString(@RequestBody TimeSeries timeSeries) { + return new ResponseEntity<>(timeSeriesService.getTimeSeriesToString(timeSeries), HttpStatus.OK); + } + @PostMapping("getForecast") @ApiOperation("Получить прогноз временного ряда") public ResponseEntity getForecastTimeSeries(@RequestBody ForecastParams forecastParams) throws ModelingException { diff --git a/src/main/java/ru/ulstu/models/TimeSeries.java b/src/main/java/ru/ulstu/models/TimeSeries.java index 619412e..68d0b1f 100644 --- a/src/main/java/ru/ulstu/models/TimeSeries.java +++ b/src/main/java/ru/ulstu/models/TimeSeries.java @@ -24,6 +24,10 @@ public class TimeSeries { } + public TimeSeries(List values) { + this.values = values; + } + public List getValues() { return values; } diff --git a/src/main/java/ru/ulstu/models/TimeSeriesValue.java b/src/main/java/ru/ulstu/models/TimeSeriesValue.java index a96df51..838a925 100644 --- a/src/main/java/ru/ulstu/models/TimeSeriesValue.java +++ b/src/main/java/ru/ulstu/models/TimeSeriesValue.java @@ -20,6 +20,10 @@ public class TimeSeriesValue { this.date = date; } + public TimeSeriesValue(Double value) { + this.value = value; + } + public LocalDateTime getDate() { return date; } diff --git a/src/main/java/ru/ulstu/services/TimeSeriesService.java b/src/main/java/ru/ulstu/services/TimeSeriesService.java index ccee4d0..78a8e03 100644 --- a/src/main/java/ru/ulstu/services/TimeSeriesService.java +++ b/src/main/java/ru/ulstu/services/TimeSeriesService.java @@ -3,6 +3,7 @@ package ru.ulstu.services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import ru.ulstu.TimeSeriesUtils; import ru.ulstu.models.Forecast; import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeriesValue; @@ -10,6 +11,9 @@ import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.tsMethods.exponential.NoTrendNoSeason; import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; @Service @@ -27,7 +31,34 @@ public class TimeSeriesService { } public Forecast getForecast(TimeSeries timeSeries, int countPoints) throws ModelingException { - NoTrendNoSeason nn = new NoTrendNoSeason(0.1); + NoTrendNoSeason nn = new NoTrendNoSeason(0.8); return nn.getForecast(timeSeries, countPoints); } + + public TimeSeries getTimeSeriesFromString(String tsString) { + List tsValues = Arrays.stream(tsString.split("\n")) + .flatMap(v -> Arrays.stream(v.split(";"))) + .flatMap(v -> Arrays.stream(v.split(","))) + .flatMap(v -> Arrays.stream(v.split("
"))) + .filter(v -> { + try { + Double.parseDouble(v); + return true; + } catch (NumberFormatException e) { + return false; + } + }) + .map(Double::parseDouble) + .map(TimeSeriesValue::new) + .collect(Collectors.toList()); + return TimeSeriesUtils.fillDates(new TimeSeries(tsValues)); + } + + public String getTimeSeriesToString(TimeSeries timeSeries) { + return timeSeries + .getValues() + .stream() + .map(v -> v.getValue().toString().replaceAll("\\.", ",")) + .collect(Collectors.joining(";")); + } } diff --git a/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java b/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java index 5e74e89..a6a055c 100644 --- a/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java +++ b/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java @@ -1,5 +1,6 @@ package ru.ulstu.tsMethods; +import ru.ulstu.TimeSeriesUtils; import ru.ulstu.models.Forecast; import ru.ulstu.models.Model; import ru.ulstu.models.TimeSeries; @@ -8,8 +9,6 @@ import ru.ulstu.models.exceptions.ForecastValidateException; import ru.ulstu.models.exceptions.ModelingException; import ru.ulstu.models.exceptions.TimeSeriesValidateException; -import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.temporal.ChronoUnit; /** @@ -58,7 +57,7 @@ public abstract class TimeSeriesMethod { } /** - * Выполняет построение прогноза ждя уже сгенерированных будущих точек временного ряда. + * Выполняет построение прогноза для уже сгенерированных будущих точек временного ряда. * * @param forecast Заготовка прогноза временного ряда с пустыми значениями * @return @@ -66,14 +65,7 @@ public abstract class TimeSeriesMethod { protected abstract Forecast makeForecast(Forecast forecast); protected Forecast generateEmptyForecastPoints(Forecast forecast, int countPointForecast) { - long diffMilliseconds = getTimeDifferenceInMilliseconds(forecast); - LocalDateTime lastTimeSeriesDateTime = forecast - .getModel() - .getOriginalTimeSeries() - .getLastValue() - .getDate() - .atZone(ZoneId.systemDefault()) - .toLocalDateTime(); + long diffMilliseconds = TimeSeriesUtils.getTimeDifferenceInMilliseconds(forecast.getModel().getOriginalTimeSeries()); forecast.getForecastTimeSeries() .addValue(new TimeSeriesValue(forecast.getModel().getModelTimeSeries().getLastValue().getDate())); for (int i = 1; i < countPointForecast + 1; i++) { @@ -83,21 +75,6 @@ public abstract class TimeSeriesMethod { return forecast; } - /** - * Вычисляет среднее значение между датами исходного временного ряда - * - * @param forecast объект, содержащий результат прогнозирования - * @return средняя разница между датами исходного временного ряда в миллисекундах - */ - protected long getTimeDifferenceInMilliseconds(Forecast forecast) { - long diffMilliseconds = 0; - for (int i = 1; i < forecast.getModel().getOriginalTimeSeries().getLength(); i++) { - diffMilliseconds += forecast.getModel().getOriginalTimeSeries().getValues().get(i - 1).getDate() - .until(forecast.getModel().getOriginalTimeSeries().getValues().get(i).getDate(), ChronoUnit.MILLIS); - } - return diffMilliseconds / (forecast.getModel().getOriginalTimeSeries().getLength() - 1); - } - /** * Выполняет построение модели и прогноза временного ряда. Даты спрогнозированных точек будут сгенерированы * по модельным точкам. diff --git a/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java b/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java index 13ac7ef..ce8b2b5 100644 --- a/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java +++ b/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java @@ -34,7 +34,7 @@ public class NoTrendNoSeason extends TimeSeriesMethod { forecast.getForecastTimeSeries() .getValues() .get(t) - .setValue(alpha * forecast.getForecastTimeSeries().getValues().get(t - 1).getValue()); + .setValue(forecast.getForecastTimeSeries().getValues().get(t - 1).getValue()); } return forecast; }