#12 -- Divide TS presentation and forecasting
This commit is contained in:
parent
52561af526
commit
cefc1542c3
@ -54,53 +54,60 @@ public class IndexController {
|
|||||||
if (chartForm.getTimeSeriesMeta() != null
|
if (chartForm.getTimeSeriesMeta() != null
|
||||||
&& chartForm.getTimeSeriesMeta().getKey() != null
|
&& chartForm.getTimeSeriesMeta().getKey() != null
|
||||||
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()) {
|
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()) {
|
||||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), null, model);
|
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()),
|
||||||
|
null,
|
||||||
|
chartForm.isNeedForecast(),
|
||||||
|
model);
|
||||||
}
|
}
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChartToModel(TimeSeries timeSeries, String method, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
private void addChartToModel(TimeSeries timeSeries, String method, boolean needForecast, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
if (needForecast) {
|
||||||
TimeSeries timeSeriesModel;
|
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
||||||
ModelingResult modelingResult;
|
TimeSeries timeSeriesModel;
|
||||||
if (method == null) {
|
ModelingResult modelingResult;
|
||||||
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
if (method == null) {
|
||||||
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
||||||
} else {
|
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
||||||
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries, method).getTimeSeries();
|
|
||||||
modelingResult = timeSeriesService.getForecast(timeSeries, method, countForecastPoints);
|
|
||||||
}
|
|
||||||
TimeSeries forecast = modelingResult.getTimeSeries();
|
|
||||||
TimeSeries testForecast = modelingResult.getTestForecast();
|
|
||||||
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
|
||||||
model.addAttribute("timeSeries", timeSeries.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
|
||||||
// если временной ряд был сжат моделью, то для графика нужно вставить пустые значения
|
|
||||||
TimeSeries modelWithSkips = new TimeSeries(timeSeriesModel.getKey());
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < timeSeries.getLength(); i++) {
|
|
||||||
if (timeSeries.getValue(i).getDate().equals(timeSeriesModel.getValue(j).getDate())) {
|
|
||||||
modelWithSkips.addValue(timeSeriesModel.getValue(j));
|
|
||||||
j++;
|
|
||||||
} else {
|
} else {
|
||||||
modelWithSkips.addValue(new TimeSeriesValue((Double) null));
|
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries, method).getTimeSeries();
|
||||||
|
modelingResult = timeSeriesService.getForecast(timeSeries, method, countForecastPoints);
|
||||||
}
|
}
|
||||||
|
TimeSeries forecast = modelingResult.getTimeSeries();
|
||||||
|
TimeSeries testForecast = modelingResult.getTestForecast();
|
||||||
|
// если временной ряд был сжат моделью, то для графика нужно вставить пустые значения
|
||||||
|
TimeSeries modelWithSkips = new TimeSeries(timeSeriesModel.getKey());
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < timeSeries.getLength(); i++) {
|
||||||
|
if (timeSeries.getValue(i).getDate().equals(timeSeriesModel.getValue(j).getDate())) {
|
||||||
|
modelWithSkips.addValue(timeSeriesModel.getValue(j));
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
modelWithSkips.addValue(new TimeSeriesValue((Double) null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model.addAttribute("model", modelWithSkips.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
||||||
|
timeSeries.getValues().remove(timeSeries.getValues().size() - 1);
|
||||||
|
|
||||||
|
List<Double> forecastValues = timeSeries.getValues().stream().map(v -> (Double) null).collect(Collectors.toList());
|
||||||
|
forecastValues.addAll(forecast.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()));
|
||||||
|
model.addAttribute("forecast", forecastValues.toArray());
|
||||||
|
|
||||||
|
List<Double> testForecastValues = timeSeries.getValues()
|
||||||
|
.stream()
|
||||||
|
.skip(countForecastPoints)
|
||||||
|
.map(v -> (Double) null)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
testForecastValues.addAll(testForecast.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()));
|
||||||
|
model.addAttribute("testForecast", testForecastValues.toArray());
|
||||||
|
model.addAttribute("forecastDescription", modelingResult);
|
||||||
|
model.addAttribute("statistic", statisticService.getStatistic(timeSeries));
|
||||||
|
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
||||||
|
} else {
|
||||||
|
model.addAttribute("dates", getDatesForChart(timeSeries, new TimeSeries()));
|
||||||
}
|
}
|
||||||
model.addAttribute("model", modelWithSkips.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
model.addAttribute("timeSeries", timeSeries.getValues().stream().map(TimeSeriesValue::getValue).toArray());
|
||||||
timeSeries.getValues().remove(timeSeries.getValues().size() - 1);
|
|
||||||
|
|
||||||
List<Double> forecastValues = timeSeries.getValues().stream().map(v -> (Double) null).collect(Collectors.toList());
|
|
||||||
forecastValues.addAll(forecast.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()));
|
|
||||||
model.addAttribute("forecast", forecastValues.toArray());
|
|
||||||
|
|
||||||
List<Double> testForecastValues = timeSeries.getValues()
|
|
||||||
.stream()
|
|
||||||
.skip(countForecastPoints)
|
|
||||||
.map(v -> (Double) null)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
testForecastValues.addAll(testForecast.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList()));
|
|
||||||
model.addAttribute("testForecast", testForecastValues.toArray());
|
|
||||||
model.addAttribute("forecastDescription", modelingResult);
|
|
||||||
model.addAttribute("statistic", statisticService.getStatistic(timeSeries));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getDatesForChart(TimeSeries timeSeries, TimeSeries forecast) {
|
private List<String> getDatesForChart(TimeSeries timeSeries, TimeSeries forecast) {
|
||||||
@ -132,7 +139,10 @@ public class IndexController {
|
|||||||
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
||||||
&& chartForm.getMethodClassName() != null
|
&& chartForm.getMethodClassName() != null
|
||||||
&& !chartForm.getMethodClassName().equals("")) {
|
&& !chartForm.getMethodClassName().equals("")) {
|
||||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), chartForm.getMethodClassName(), model);
|
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()),
|
||||||
|
chartForm.getMethodClassName(),
|
||||||
|
chartForm.isNeedForecast(),
|
||||||
|
model);
|
||||||
}
|
}
|
||||||
return "method";
|
return "method";
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ public class ChartForm {
|
|||||||
private TimeSeriesMeta timeSeriesMeta;
|
private TimeSeriesMeta timeSeriesMeta;
|
||||||
private String methodClassName = null;
|
private String methodClassName = null;
|
||||||
|
|
||||||
|
private boolean needForecast;
|
||||||
|
|
||||||
public TimeSeriesSet getSet() {
|
public TimeSeriesSet getSet() {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
@ -31,4 +33,12 @@ public class ChartForm {
|
|||||||
public void setMethodClassName(String methodClassName) {
|
public void setMethodClassName(String methodClassName) {
|
||||||
this.methodClassName = methodClassName;
|
this.methodClassName = methodClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isNeedForecast() {
|
||||||
|
return needForecast;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNeedForecast(boolean needForecast) {
|
||||||
|
this.needForecast = needForecast;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,10 @@
|
|||||||
$('#select-ts').val([[*{timeSeriesMeta.key}]]);
|
$('#select-ts').val([[*{timeSeriesMeta.key}]]);
|
||||||
$('#select-ts').selectpicker('refresh');
|
$('#select-ts').selectpicker('refresh');
|
||||||
</script>
|
</script>
|
||||||
|
<input id="need-forecast" type="hidden" th:field="*{needForecast}">
|
||||||
|
<button type="button" class="btn btn-primary" onclick="$('#need-forecast').val(true); form.submit();">
|
||||||
|
Построить прогноз
|
||||||
|
</button>
|
||||||
<h5 th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
<h5 th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
||||||
Результаты моделирования:
|
Результаты моделирования:
|
||||||
</h5>
|
</h5>
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
|
|
||||||
<select id="select-ts" class="selectpicker form-group" data-live-search="true"
|
<select id="select-ts" class="selectpicker form-group" data-live-search="true"
|
||||||
th:field="*{timeSeriesMeta}"
|
th:field="*{timeSeriesMeta}"
|
||||||
data-width="90%" onchange="form.submit();">
|
data-width="90%" onchange="$('#need-forecast').val(false); form.submit();">
|
||||||
<option value="">Временной ряд</option>
|
<option value="">Временной ряд</option>
|
||||||
<option th:each="ts : ${listTimeSeries}"
|
<option th:each="ts : ${listTimeSeries}"
|
||||||
th:value="${ts.key}"
|
th:value="${ts.key}"
|
||||||
@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
<select id="select-method" class="selectpicker form-group" data-live-search="true"
|
<select id="select-method" class="selectpicker form-group" data-live-search="true"
|
||||||
th:field="*{methodClassName}"
|
th:field="*{methodClassName}"
|
||||||
data-width="90%" onchange="form.submit();">
|
data-width="90%" onchange="$('#need-forecast').val(false); form.submit();">
|
||||||
<option value="">Метод прогнозирования</option>
|
<option value="">Метод прогнозирования</option>
|
||||||
<option th:each="method : ${methods}"
|
<option th:each="method : ${methods}"
|
||||||
th:value="${method.key}"
|
th:value="${method.key}"
|
||||||
@ -148,7 +148,10 @@
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<input id="need-forecast" type="hidden" th:field="*{needForecast}">
|
||||||
|
<button type="button" class="btn btn-primary" onclick="$('#need-forecast').val(true); form.submit();">
|
||||||
|
Построить прогноз
|
||||||
|
</button>
|
||||||
<div th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
<div th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
||||||
<p> Метод прогнозирования: <span th:text="${forecastDescription.timeSeriesMethod}"> </span>
|
<p> Метод прогнозирования: <span th:text="${forecastDescription.timeSeriesMethod}"> </span>
|
||||||
<p> Оценка: <span th:text="${forecastDescription.score.value}"> </span>
|
<p> Оценка: <span th:text="${forecastDescription.score.value}"> </span>
|
||||||
|
Loading…
Reference in New Issue
Block a user