From 62f3ffcf5c330f0bf831eb358c385aae0d73bbe7 Mon Sep 17 00:00:00 2001 From: romanov73 Date: Sat, 24 Feb 2018 23:00:30 +0400 Subject: [PATCH] add first method --- .../controllers/TimeSeriesController.java | 10 +++-- src/main/java/ru/ulstu/models/TimeSeries.java | 29 ++++++++++++ .../java/ru/ulstu/models/TimeSeriesValue.java | 6 ++- .../ru/ulstu/services/TimeSeriesService.java | 8 ++++ src/main/java/ru/ulstu/tsMethods/Param.java | 5 +++ .../ru/ulstu/tsMethods/TimeSeriesMethod.java | 37 +++++++++++++++ .../exponential/NoTrendNoSeason.java | 45 +++++++++++++++++++ 7 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 src/main/java/ru/ulstu/tsMethods/Param.java create mode 100644 src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java create mode 100644 src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java diff --git a/src/main/java/ru/ulstu/controllers/TimeSeriesController.java b/src/main/java/ru/ulstu/controllers/TimeSeriesController.java index ad02e62..de58bb8 100644 --- a/src/main/java/ru/ulstu/controllers/TimeSeriesController.java +++ b/src/main/java/ru/ulstu/controllers/TimeSeriesController.java @@ -3,10 +3,7 @@ package ru.ulstu.controllers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import ru.ulstu.configurations.ApiConfiguration; import ru.ulstu.models.TimeSeries; import ru.ulstu.services.TimeSeriesService; @@ -31,4 +28,9 @@ public class TimeSeriesController { public ResponseEntity getRandomTimeSeries(@RequestParam("length") int length) { return new ResponseEntity<>(timeSeriesService.getRandomTimeSeries(length), HttpStatus.OK); } + + @RequestMapping(value = "ts.get_forecast", method = RequestMethod.POST) + public ResponseEntity getForecastTimeSeries(@RequestBody TimeSeries timeSeries) { + return new ResponseEntity<>(timeSeriesService.getForecast(timeSeries), HttpStatus.OK); + } } diff --git a/src/main/java/ru/ulstu/models/TimeSeries.java b/src/main/java/ru/ulstu/models/TimeSeries.java index 2ef7ff5..f5c95d2 100644 --- a/src/main/java/ru/ulstu/models/TimeSeries.java +++ b/src/main/java/ru/ulstu/models/TimeSeries.java @@ -1,5 +1,8 @@ package ru.ulstu.models; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.ArrayList; import java.util.List; @@ -11,6 +14,16 @@ public class TimeSeries { this.name = name; } + @JsonCreator + public TimeSeries(@JsonProperty(value = "values") List values, @JsonProperty(value = "name") String name) { + this.values = values; + this.name = name; + } + + public TimeSeries() { + + } + public List getValues() { return values; } @@ -26,4 +39,20 @@ public class TimeSeries { public void setName(String name) { this.name = name; } + + public boolean isEmpty() { + return values.isEmpty(); + } + + public void addValue(TimeSeriesValue timeSeriesValue) { + values.add(timeSeriesValue); + } + + public void addValue(TimeSeriesValue basedOnValue, Double value) { + values.add(new TimeSeriesValue(basedOnValue.getDate().plusDays(1), value)); + } + + public TimeSeriesValue getLastValue() { + return values.get(values.size()-1); + } } diff --git a/src/main/java/ru/ulstu/models/TimeSeriesValue.java b/src/main/java/ru/ulstu/models/TimeSeriesValue.java index ceff523..4fe4c0e 100644 --- a/src/main/java/ru/ulstu/models/TimeSeriesValue.java +++ b/src/main/java/ru/ulstu/models/TimeSeriesValue.java @@ -1,12 +1,16 @@ package ru.ulstu.models; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.time.LocalDate; public class TimeSeriesValue { private LocalDate date; private Double value; - public TimeSeriesValue(LocalDate date, Double value) { + @JsonCreator + public TimeSeriesValue(@JsonProperty(value="date") LocalDate date, @JsonProperty(value = "value") Double value) { this.date = date; this.value = value; } diff --git a/src/main/java/ru/ulstu/services/TimeSeriesService.java b/src/main/java/ru/ulstu/services/TimeSeriesService.java index 88db121..8c98db3 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.springframework.stereotype.Service; import ru.ulstu.models.TimeSeries; import ru.ulstu.models.TimeSeriesValue; +import ru.ulstu.tsMethods.exponential.NoTrendNoSeason; import java.time.LocalDate; @@ -18,4 +19,11 @@ public class TimeSeriesService { } return ts; } + + public TimeSeries getForecast(TimeSeries timeSeries) { + NoTrendNoSeason nn = new NoTrendNoSeason(timeSeries, 5); + nn.setAlpa(0.1); + nn.createModel(); + return nn.getForecastTimeSeries(); + } } diff --git a/src/main/java/ru/ulstu/tsMethods/Param.java b/src/main/java/ru/ulstu/tsMethods/Param.java new file mode 100644 index 0000000..f413e76 --- /dev/null +++ b/src/main/java/ru/ulstu/tsMethods/Param.java @@ -0,0 +1,5 @@ +package ru.ulstu.tsMethods; + +public enum Param { + ALPHA +} diff --git a/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java b/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java new file mode 100644 index 0000000..219e506 --- /dev/null +++ b/src/main/java/ru/ulstu/tsMethods/TimeSeriesMethod.java @@ -0,0 +1,37 @@ +package ru.ulstu.tsMethods; + +import ru.ulstu.models.TimeSeries; + +import java.util.HashMap; +import java.util.Map; + +public abstract class TimeSeriesMethod { + protected TimeSeries originalTimeSeries; + protected TimeSeries modelTimeSeries; + protected TimeSeries forecastTimeSeries; + protected int countForecast; + protected Map parameters = new HashMap<>(); + + protected void init() { + modelTimeSeries = new TimeSeries("Model time series of '" + originalTimeSeries.getName() + "'"); + forecastTimeSeries = new TimeSeries("Forecast time series of '" + originalTimeSeries.getName() + "'"); + } + + public TimeSeries getOriginalTimeSeries() { + return originalTimeSeries; + } + + public TimeSeries getModelTimeSeries() { + return modelTimeSeries; + } + + public int getCountForecast() { + return countForecast; + } + + public TimeSeries getForecastTimeSeries() { + return forecastTimeSeries; + } + + public abstract void createModel(); +} diff --git a/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java b/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java new file mode 100644 index 0000000..9bd990d --- /dev/null +++ b/src/main/java/ru/ulstu/tsMethods/exponential/NoTrendNoSeason.java @@ -0,0 +1,45 @@ +package ru.ulstu.tsMethods.exponential; + +import ru.ulstu.models.TimeSeries; +import ru.ulstu.tsMethods.Param; +import ru.ulstu.tsMethods.TimeSeriesMethod; + +public class NoTrendNoSeason extends TimeSeriesMethod { + public NoTrendNoSeason(TimeSeries originalTimeSeries, int countForecast) { + this.originalTimeSeries = originalTimeSeries; + this.countForecast = countForecast; + if (originalTimeSeries.isEmpty()) { + throw new RuntimeException("Time series must not empty"); + } + } + + @Override + protected void init() { + super.init(); + modelTimeSeries.addValue(originalTimeSeries.getValues().get(0)); + forecastTimeSeries.addValue(originalTimeSeries.getValues().get(0)); + parameters.put(Param.ALPHA, 1.0); + } + + public void setAlpa(double value) { + parameters.put(Param.ALPHA, value); + } + + @Override + public void createModel() { + init(); + double e; + + //выполняется проход модели по сглаживанию и прогнозированию countPointForecast точек + for (int t = 0; t < originalTimeSeries.getValues().size() - 1 + countForecast; t++) { + // пока не дошли до конца ряда - сглаживаем, иначе строим прогноз + if (t < originalTimeSeries.getValues().size()) { + e = originalTimeSeries.getValues().get(t).getValue() - forecastTimeSeries.getValues().get(t).getValue(); + } else { + e = 0; + } + modelTimeSeries.addValue(modelTimeSeries.getLastValue(), modelTimeSeries.getValues().get(t).getValue() + parameters.get(Param.ALPHA) * e); // уровень + forecastTimeSeries.addValue(modelTimeSeries.getLastValue()); // прогноз + } + } +}