Merge pull request '1-method-choosing' (#2) from 1-method-choosing into master
Reviewed-on: #2
This commit is contained in:
commit
ed0300a148
29
build.gradle
29
build.gradle
@ -1,14 +1,7 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
|
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||||
id 'org.springframework.boot' version '2.3.3.RELEASE'
|
id 'org.springframework.boot' version '2.6.4'
|
||||||
id "org.sonarqube" version "2.7"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
@ -16,26 +9,29 @@ jar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
maven {
|
||||||
mavenCentral()
|
url "https://repo.athene.tech/repository/maven-central/"
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url "https://repo.athene.tech/repository/maven-releases/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = 11
|
sourceCompatibility = '11'
|
||||||
targetCompatibility = 11
|
targetCompatibility = '11'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
ext {
|
ext {
|
||||||
versionSLF4J = '1.7.24'
|
versionSLF4J = '1.7.24'
|
||||||
versionJetty = '9.3.16.v20170120'
|
versionJetty = '9.3.16.v20170120'
|
||||||
versionJackson = '2.9.4'
|
versionJackson = '2.9.4'
|
||||||
versionSwagger = '2.5.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
|
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
|
||||||
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
|
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
|
||||||
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
|
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
|
||||||
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J
|
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J
|
||||||
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
|
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0'
|
||||||
implementation group: 'org.javassist', name: 'javassist', version: '3.25.0-GA'
|
implementation group: 'org.javassist', name: 'javassist', version: '3.25.0-GA'
|
||||||
implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: versionJetty
|
implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: versionJetty
|
||||||
|
|
||||||
@ -43,8 +39,7 @@ dependencies {
|
|||||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: versionJackson
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: versionJackson
|
||||||
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: versionJackson
|
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: versionJackson
|
||||||
|
|
||||||
implementation group: 'io.springfox', name: 'springfox-swagger2', version: versionSwagger
|
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
|
||||||
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: versionSwagger
|
|
||||||
|
|
||||||
implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
|
implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
|
||||||
implementation group: 'org.webjars', name: 'bootstrap', version: '4.6.0'
|
implementation group: 'org.webjars', name: 'bootstrap', version: '4.6.0'
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.configuration;
|
package ru.ulstu.configuration;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
package ru.ulstu.configuration;
|
package ru.ulstu.configuration;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springdoc.core.GroupedOpenApi;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
|
||||||
import springfox.documentation.spi.DocumentationType;
|
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableSwagger2
|
|
||||||
public class SwaggerConfiguration {
|
public class SwaggerConfiguration {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Docket swaggerApi() {
|
public GroupedOpenApi swaggerApi() {
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
log.info("Creating Swagger API configuration bean");
|
||||||
.select()
|
return GroupedOpenApi.builder()
|
||||||
.apis(RequestHandlerSelectors.any())
|
.group("timetable-api")
|
||||||
.paths(Predicates.not(PathSelectors.regex("/error")))
|
.pathsToMatch(ApiConfiguration.API_1_0 + "**")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
/*
|
|
||||||
* 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.configuration;
|
package ru.ulstu.configuration;
|
||||||
|
|
||||||
import nz.net.ultraq.thymeleaf.LayoutDialect;
|
import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.controller;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.controller;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
/*
|
|
||||||
* 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.controller;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -17,7 +12,6 @@ import ru.ulstu.datamodel.ts.TimeSeries;
|
|||||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||||
import ru.ulstu.db.DbService;
|
import ru.ulstu.db.DbService;
|
||||||
import ru.ulstu.service.TimeSeriesService;
|
import ru.ulstu.service.TimeSeriesService;
|
||||||
import springfox.documentation.annotations.ApiIgnore;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -29,7 +23,7 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@ApiIgnore
|
@Hidden
|
||||||
public class IndexController {
|
public class IndexController {
|
||||||
private final TimeSeriesService timeSeriesService;
|
private final TimeSeriesService timeSeriesService;
|
||||||
private final DbService dbService;
|
private final DbService dbService;
|
||||||
@ -56,15 +50,45 @@ 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()), model);
|
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), null, model);
|
||||||
}
|
}
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChartToModel(TimeSeries timeSeries, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
@GetMapping("/method")
|
||||||
|
public String method(Model model) throws IOException {
|
||||||
|
model.addAttribute("sets", dbService.getSets());
|
||||||
|
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
||||||
|
model.addAttribute("chartForm", new ChartForm());
|
||||||
|
return "method";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("chartMethod")
|
||||||
|
public String chartMethod(@ModelAttribute ChartForm chartForm, Model model) throws IOException, ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||||
|
model.addAttribute("sets", dbService.getSets());
|
||||||
|
model.addAttribute("methods", timeSeriesService.getAvailableMethods());
|
||||||
|
if (chartForm.getSet() != null && !chartForm.getSet().getKey().equals("")) {
|
||||||
|
model.addAttribute("listTimeSeries", dbService.getTimeSeriesMeta(chartForm.getSet()));
|
||||||
|
}
|
||||||
|
if (chartForm.getTimeSeriesMeta() != null
|
||||||
|
&& chartForm.getTimeSeriesMeta().getKey() != null
|
||||||
|
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
||||||
|
&& chartForm.getMethodClassName() != null
|
||||||
|
&& !chartForm.getMethodClassName().equals("")) {
|
||||||
|
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), chartForm.getMethodClassName(), model);
|
||||||
|
}
|
||||||
|
return "method";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addChartToModel(TimeSeries timeSeries, String method, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
||||||
TimeSeries timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries);
|
TimeSeries timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
||||||
ModelingResult modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
ModelingResult modelingResult;
|
||||||
|
if (method == null) {
|
||||||
|
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
||||||
|
} else {
|
||||||
|
modelingResult = timeSeriesService.getForecast(timeSeries, method, countForecastPoints);
|
||||||
|
}
|
||||||
TimeSeries forecast = modelingResult.getTimeSeries();
|
TimeSeries forecast = modelingResult.getTimeSeries();
|
||||||
TimeSeries testForecast = modelingResult.getTestForecast();
|
TimeSeries testForecast = modelingResult.getTestForecast();
|
||||||
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
model.addAttribute("dates", getDatesForChart(timeSeries, forecast));
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
/*
|
|
||||||
* 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.controller;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -21,11 +16,13 @@ import ru.ulstu.datamodel.ForecastParams;
|
|||||||
import ru.ulstu.datamodel.ModelingResult;
|
import ru.ulstu.datamodel.ModelingResult;
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
import ru.ulstu.service.MethodParamBruteForce;
|
import ru.ulstu.method.Method;
|
||||||
import ru.ulstu.service.TimeSeriesService;
|
import ru.ulstu.service.TimeSeriesService;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.validation.Valid;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -34,17 +31,14 @@ public class TimeSeriesController {
|
|||||||
private final static Logger LOGGER = LoggerFactory.getLogger(TimeSeriesController.class);
|
private final static Logger LOGGER = LoggerFactory.getLogger(TimeSeriesController.class);
|
||||||
|
|
||||||
private final TimeSeriesService timeSeriesService;
|
private final TimeSeriesService timeSeriesService;
|
||||||
private final MethodParamBruteForce methodParamBruteForce;
|
|
||||||
|
|
||||||
public TimeSeriesController(TimeSeriesService timeSeriesService,
|
public TimeSeriesController(TimeSeriesService timeSeriesService) {
|
||||||
MethodParamBruteForce methodParamBruteForce) {
|
|
||||||
this.timeSeriesService = timeSeriesService;
|
this.timeSeriesService = timeSeriesService;
|
||||||
this.methodParamBruteForce = methodParamBruteForce;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("getForecast")
|
@PostMapping("getForecast")
|
||||||
@ApiOperation("Получить прогноз временного ряда")
|
@Operation(description = "Получить прогноз временного ряда любым методом")
|
||||||
public ResponseEntity<ModelingResult> getForecastTimeSeries(@RequestBody ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
public ResponseEntity<ModelingResult> getForecastTimeSeries(@RequestBody @Valid ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
||||||
LOGGER.info("Forecast: " + forecastParams);
|
LOGGER.info("Forecast: " + forecastParams);
|
||||||
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
||||||
@ -54,12 +48,30 @@ public class TimeSeriesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("getSmoothed")
|
@PostMapping("getSmoothed")
|
||||||
@ApiOperation("Получить сглаженный временной ряд")
|
@Operation(description = "Получить сглаженный временной ряд любым методом")
|
||||||
public ResponseEntity<ModelingResult> getSmoothedTimeSeries(@RequestBody TimeSeries timeSeries, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
public ResponseEntity<ModelingResult> getSmoothedTimeSeries(@RequestBody TimeSeries timeSeries, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||||
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
||||||
LOGGER.info("Time series for smoothing: " + timeSeries);
|
LOGGER.info("Time series for smoothing: " + timeSeries);
|
||||||
ResponseEntity<ModelingResult> result = new ResponseEntity<>(methodParamBruteForce.getSmoothedTimeSeries(timeSeries), HttpStatus.OK);
|
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.smoothTimeSeries(timeSeries), HttpStatus.OK);
|
||||||
LOGGER.info("Smoothing complete");
|
LOGGER.info("Smoothing complete");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("getSpecificMethodForecast")
|
||||||
|
@Operation(description = "Получить прогноз временного ряда указанным методом")
|
||||||
|
public ResponseEntity<ModelingResult> getForecastTimeSeriesSpecificMethod(@RequestBody @Valid ForecastParams forecastParams, HttpServletRequest request) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
LOGGER.info("User ip: " + HttpUtils.getUserIp(request));
|
||||||
|
LOGGER.info("Forecast: " + forecastParams);
|
||||||
|
ResponseEntity<ModelingResult> result = new ResponseEntity<>(timeSeriesService.getForecast(forecastParams.getOriginalTimeSeries(),
|
||||||
|
forecastParams.getMethodClassName(),
|
||||||
|
forecastParams.getCountForecast()), HttpStatus.OK);
|
||||||
|
LOGGER.info("Forecast result complete");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("availableMethods")
|
||||||
|
@Operation(description = "Получить список доступных методов моделирования")
|
||||||
|
public ResponseEntity<List<Method>> getAvailableMethods() {
|
||||||
|
return new ResponseEntity<>(timeSeriesService.getAvailableMethods(), HttpStatus.OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
/*
|
|
||||||
* 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.controller;
|
package ru.ulstu.controller;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -30,25 +24,25 @@ public class UtilController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("isAlive")
|
@GetMapping("isAlive")
|
||||||
@ApiOperation("Проверка сервиса")
|
@Operation(description = "Проверка сервиса")
|
||||||
public ResponseEntity<Boolean> isAlive() {
|
public ResponseEntity<Boolean> isAlive() {
|
||||||
return new ResponseEntity<>(true, HttpStatus.OK);
|
return new ResponseEntity<>(true, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("getRandom")
|
@GetMapping("getRandom")
|
||||||
@ApiOperation("Получить временной ряд рандомной длины")
|
@Operation(description = "Получить временной ряд рандомной длины")
|
||||||
public ResponseEntity<TimeSeries> getRandomTimeSeries(@RequestParam("length") int length) {
|
public ResponseEntity<TimeSeries> getRandomTimeSeries(@RequestParam("length") int length) {
|
||||||
return new ResponseEntity<>(utilService.getRandomTimeSeries(length), HttpStatus.OK);
|
return new ResponseEntity<>(utilService.getRandomTimeSeries(length), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("getFromString")
|
@GetMapping("getFromString")
|
||||||
@ApiOperation("Преобразовать строку с разделителями во временной ряд")
|
@Operation(description = "Преобразовать строку с разделителями во временной ряд")
|
||||||
public ResponseEntity<TimeSeries> getTimeSeriesFromString(@RequestParam("tsString") String tsString) {
|
public ResponseEntity<TimeSeries> getTimeSeriesFromString(@RequestParam("tsString") String tsString) {
|
||||||
return new ResponseEntity<>(utilService.getTimeSeriesFromString(tsString), HttpStatus.OK);
|
return new ResponseEntity<>(utilService.getTimeSeriesFromString(tsString), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("timeSeriesToString")
|
@PostMapping("timeSeriesToString")
|
||||||
@ApiOperation("Преобразовать временной ряд в строку с разделителями")
|
@Operation(description = "Преобразовать временной ряд в строку с разделителями")
|
||||||
public ResponseEntity<String> getTimeSeriesToString(@RequestBody TimeSeries timeSeries) {
|
public ResponseEntity<String> getTimeSeriesToString(@RequestBody TimeSeries timeSeries) {
|
||||||
return new ResponseEntity<>(utilService.getTimeSeriesToString(timeSeries), HttpStatus.OK);
|
return new ResponseEntity<>(utilService.getTimeSeriesToString(timeSeries), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import ru.ulstu.db.model.TimeSeriesMeta;
|
import ru.ulstu.db.model.TimeSeriesMeta;
|
||||||
@ -12,6 +6,7 @@ import ru.ulstu.db.model.TimeSeriesSet;
|
|||||||
public class ChartForm {
|
public class ChartForm {
|
||||||
private TimeSeriesSet set;
|
private TimeSeriesSet set;
|
||||||
private TimeSeriesMeta timeSeriesMeta;
|
private TimeSeriesMeta timeSeriesMeta;
|
||||||
|
private String methodClassName = null;
|
||||||
|
|
||||||
public TimeSeriesSet getSet() {
|
public TimeSeriesSet getSet() {
|
||||||
return set;
|
return set;
|
||||||
@ -28,4 +23,12 @@ public class ChartForm {
|
|||||||
public void setTimeSeriesMeta(TimeSeriesMeta timeSeriesMeta) {
|
public void setTimeSeriesMeta(TimeSeriesMeta timeSeriesMeta) {
|
||||||
this.timeSeriesMeta = timeSeriesMeta;
|
this.timeSeriesMeta = timeSeriesMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMethodClassName() {
|
||||||
|
return methodClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethodClassName(String methodClassName) {
|
||||||
|
this.methodClassName = methodClassName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class ForecastParams {
|
public class ForecastParams {
|
||||||
|
@NotNull
|
||||||
private TimeSeries originalTimeSeries;
|
private TimeSeries originalTimeSeries;
|
||||||
|
@NotNull
|
||||||
private int countForecast;
|
private int countForecast;
|
||||||
|
private String methodClassName;
|
||||||
|
|
||||||
public TimeSeries getOriginalTimeSeries() {
|
public TimeSeries getOriginalTimeSeries() {
|
||||||
return originalTimeSeries;
|
return originalTimeSeries;
|
||||||
@ -28,6 +27,14 @@ public class ForecastParams {
|
|||||||
this.countForecast = countForecast;
|
this.countForecast = countForecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMethodClassName() {
|
||||||
|
return methodClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethodClassName(String methodClassName) {
|
||||||
|
this.methodClassName = methodClassName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ForecastParams{" +
|
return "ForecastParams{" +
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel;
|
package ru.ulstu.datamodel;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.exception;
|
package ru.ulstu.datamodel.exception;
|
||||||
|
|
||||||
public class ForecastValidateException extends ModelingException {
|
public class ForecastValidateException extends ModelingException {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.exception;
|
package ru.ulstu.datamodel.exception;
|
||||||
|
|
||||||
public class ModelingException extends Exception {
|
public class ModelingException extends Exception {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.exception;
|
package ru.ulstu.datamodel.exception;
|
||||||
|
|
||||||
public class TimeSeriesValidateException extends ModelingException {
|
public class TimeSeriesValidateException extends ModelingException {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.response;
|
package ru.ulstu.datamodel.response;
|
||||||
|
|
||||||
class ControllerResponse<D, E> {
|
class ControllerResponse<D, E> {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.response;
|
package ru.ulstu.datamodel.response;
|
||||||
|
|
||||||
class ControllerResponseError<D> {
|
class ControllerResponseError<D> {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.response;
|
package ru.ulstu.datamodel.response;
|
||||||
|
|
||||||
public enum ErrorConstants {
|
public enum ErrorConstants {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.response;
|
package ru.ulstu.datamodel.response;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.response;
|
package ru.ulstu.datamodel.response;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.ts;
|
package ru.ulstu.datamodel.ts;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.datamodel.ts;
|
package ru.ulstu.datamodel.ts;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.db;
|
package ru.ulstu.db;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.db;
|
package ru.ulstu.db;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.db.model;
|
package ru.ulstu.db.model;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
/*
|
|
||||||
* 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.db.model;
|
package ru.ulstu.db.model;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class TimeSeriesSet {
|
public class TimeSeriesSet {
|
||||||
private String key;
|
private final String key;
|
||||||
|
|
||||||
public TimeSeriesSet(File dir) {
|
public TimeSeriesSet(File dir) {
|
||||||
this.key = dir.getName();
|
this.key = dir.getName();
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
/*
|
|
||||||
* 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.method;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import ru.ulstu.TimeSeriesUtils;
|
import ru.ulstu.TimeSeriesUtils;
|
||||||
import ru.ulstu.datamodel.Model;
|
import ru.ulstu.datamodel.Model;
|
||||||
import ru.ulstu.datamodel.exception.ForecastValidateException;
|
import ru.ulstu.datamodel.exception.ForecastValidateException;
|
||||||
@ -20,7 +13,7 @@ import java.time.temporal.ChronoUnit;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Наиболее общая логика моделировании и прогнозирования временных рядов
|
* Наиболее общая логика моделирования и прогнозирования временных рядов
|
||||||
*/
|
*/
|
||||||
public abstract class Method {
|
public abstract class Method {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@ -93,7 +86,9 @@ public abstract class Method {
|
|||||||
Model model = getModel(timeSeries, parameters);
|
Model model = getModel(timeSeries, parameters);
|
||||||
TimeSeries forecast = generateEmptyForecastPoints(model.getTimeSeriesModel(), countPoints);
|
TimeSeries forecast = generateEmptyForecastPoints(model.getTimeSeriesModel(), countPoints);
|
||||||
forecast.getFirstValue().setValue(model.getTimeSeriesModel().getLastValue().getValue());
|
forecast.getFirstValue().setValue(model.getTimeSeriesModel().getLastValue().getValue());
|
||||||
return getForecastWithValidParams(model, forecast);
|
forecast = getForecastWithValidParams(model, forecast);
|
||||||
|
forecast.getFirstValue().setValue(timeSeries.getLastValue().getValue());
|
||||||
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TimeSeries generateEmptyForecastPoints(TimeSeries model, int countPointForecast) {
|
protected TimeSeries generateEmptyForecastPoints(TimeSeries model, int countPointForecast) {
|
||||||
@ -117,8 +112,13 @@ public abstract class Method {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@JsonProperty("name")
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
return getClass().getSimpleName();
|
return getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract String getName();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
public class MethodParamValue {
|
public class MethodParamValue {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method;
|
package ru.ulstu.method;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.addtrendaddseason;
|
package ru.ulstu.method.exponential.addtrendaddseason;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -92,4 +86,9 @@ public class AddTrendAddSeason extends Method {
|
|||||||
public List<MethodParameter> getAvailableParameters() {
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
return AddTrendAddSeasonModel.getAvailableParameters();
|
return AddTrendAddSeasonModel.getAvailableParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Экспоненциальный метод с аддитивным трендом и аддитивной сезонностью (метод Хольта-Уинтерса)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.addtrendaddseason;
|
package ru.ulstu.method.exponential.addtrendaddseason;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.addtrendnoseason;
|
package ru.ulstu.method.exponential.addtrendnoseason;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -58,4 +52,9 @@ public class AddTrendNoSeason extends Method {
|
|||||||
public List<MethodParameter> getAvailableParameters() {
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
return AddTrendNoSeasonModel.getAvailableParameters();
|
return AddTrendNoSeasonModel.getAvailableParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Экспоненциальный метод с аддитивным трендом без сезонной компоненты (метод Хольта)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.addtrendnoseason;
|
package ru.ulstu.method.exponential.addtrendnoseason;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.notrendnoseason;
|
package ru.ulstu.method.exponential.notrendnoseason;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -48,4 +42,9 @@ public class NoTrendNoSeason extends Method {
|
|||||||
public List<MethodParameter> getAvailableParameters() {
|
public List<MethodParameter> getAvailableParameters() {
|
||||||
return NoTrendNoSeasonModel.getAvailableParameters();
|
return NoTrendNoSeasonModel.getAvailableParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Экспоненциальный метод без трендовой и сезонной компоненты";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.notrendnoseason;
|
package ru.ulstu.method.exponential.notrendnoseason;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Alpha extends ExponentialMethodParameter {
|
public class Alpha extends ExponentialMethodParameter {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Beta extends ExponentialMethodParameter {
|
public class Beta extends ExponentialMethodParameter {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class ExponentialMethodParamValue<T extends ExponentialMethodParameter> {
|
public class ExponentialMethodParamValue<T extends ExponentialMethodParameter> {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Gamma extends ExponentialMethodParameter {
|
public class Gamma extends ExponentialMethodParameter {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.method.exponential.parameter;
|
package ru.ulstu.method.exponential.parameter;
|
||||||
|
|
||||||
public class Season extends ExponentialMethodParameter {
|
public class Season extends ExponentialMethodParameter {
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.score;
|
package ru.ulstu.score;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.Score;
|
import ru.ulstu.datamodel.Score;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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.score;
|
package ru.ulstu.score;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -33,7 +27,7 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class MethodParamBruteForce {
|
class MethodParamBruteForce {
|
||||||
private final int DEFAULT_THREAD_COUNT = 50;
|
private final int DEFAULT_THREAD_COUNT = 50;
|
||||||
private final List<Method> methods;
|
private final List<Method> methods;
|
||||||
private final ScoreMethod scoreMethod = new Smape();
|
private final ScoreMethod scoreMethod = new Smape();
|
||||||
@ -43,9 +37,9 @@ public class MethodParamBruteForce {
|
|||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelingResult getForecast(TimeSeries timeSeries, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
private ModelingResult getForecastByMethods(TimeSeries timeSeries, List<Method> methods, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> futureModelingResults = new ArrayList<>();
|
||||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
List<ModelingResult> modelingResults = new CopyOnWriteArrayList<>();
|
||||||
final int countPoints = (countPointsForecast > timeSeries.getLength()) ? timeSeries.getLength() / 3 : countPointsForecast;
|
final int countPoints = (countPointsForecast > timeSeries.getLength()) ? timeSeries.getLength() / 3 : countPointsForecast;
|
||||||
TimeSeries reducedTimeSeries = new TimeSeries(timeSeries.getValues().stream().limit(timeSeries.getLength() - countPoints).collect(Collectors.toList()),
|
TimeSeries reducedTimeSeries = new TimeSeries(timeSeries.getValues().stream().limit(timeSeries.getLength() - countPoints).collect(Collectors.toList()),
|
||||||
"test part of " + timeSeries.getKey());
|
"test part of " + timeSeries.getKey());
|
||||||
@ -58,7 +52,7 @@ public class MethodParamBruteForce {
|
|||||||
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
||||||
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||||
if (methodInstance.canMakeForecast(reducedTimeSeries, parametersValues, countPoints)) {
|
if (methodInstance.canMakeForecast(reducedTimeSeries, parametersValues, countPoints)) {
|
||||||
results.add(executors.submit(() -> {
|
futureModelingResults.add(executors.submit(() -> {
|
||||||
TimeSeries forecast = syncDates(methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints), timeSeries);
|
TimeSeries forecast = syncDates(methodInstance.getForecast(reducedTimeSeries, parametersValues, countPoints), timeSeries);
|
||||||
return new ModelingResult(forecast, null,
|
return new ModelingResult(forecast, null,
|
||||||
parametersValues,
|
parametersValues,
|
||||||
@ -68,17 +62,39 @@ public class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Future<ModelingResult> futureModelingResult : results) {
|
for (Future<ModelingResult> futureModelingResult : futureModelingResults) {
|
||||||
results2.add(futureModelingResult.get());
|
modelingResults.add(futureModelingResult.get());
|
||||||
}
|
}
|
||||||
ModelingResult bestResult = results2.stream()
|
|
||||||
|
return getBestResultForecast(modelingResults, timeSeries, countPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, String methodClassName, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
Method method = methods.stream()
|
||||||
|
.filter(m -> m.getClass().getSimpleName().equals(methodClassName))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(() -> new ModelingException("Неизвестный метод прогнозирования"));
|
||||||
|
return getForecastByMethods(timeSeries, List.of(method), countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, Method method, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return getForecastByMethods(timeSeries, List.of(method), countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult getForecast(TimeSeries timeSeries, int countPointsForecast) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
|
return getForecastByMethods(timeSeries, methods, countPointsForecast);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelingResult getBestResultForecast(List<ModelingResult> modelingResults,
|
||||||
|
TimeSeries timeSeries,
|
||||||
|
int countPoints) throws ModelingException {
|
||||||
|
ModelingResult bestResult = modelingResults.stream()
|
||||||
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
||||||
.orElseThrow(() -> new ModelingException("Лучший метод не найден"));
|
.orElseThrow(() -> new ModelingException("Лучший метод не найден"));
|
||||||
|
|
||||||
TimeSeries forecast = bestResult.getTimeSeriesMethod().getForecast(timeSeries,
|
TimeSeries forecast = bestResult.getTimeSeriesMethod().getForecast(timeSeries,
|
||||||
bestResult.getParamValues(),
|
bestResult.getParamValues(),
|
||||||
countPoints);
|
countPoints);
|
||||||
forecast.getValue(0).setValue(timeSeries.getNumericValue(timeSeries.getLength() - 1));
|
|
||||||
|
|
||||||
return new ModelingResult(forecast,
|
return new ModelingResult(forecast,
|
||||||
bestResult.getTimeSeries(),
|
bestResult.getTimeSeries(),
|
||||||
@ -96,9 +112,12 @@ public class MethodParamBruteForce {
|
|||||||
return forecast;
|
return forecast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) {
|
public TimeSeries getForecastWithOptimalLength(TimeSeries timeSeries) {
|
||||||
throw new RuntimeException("Not implemented");
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
public ModelingResult getSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||||
@ -139,7 +158,7 @@ public class MethodParamBruteForce {
|
|||||||
parameterOffset.put(methodParameter, 0);
|
parameterOffset.put(methodParameter, 0);
|
||||||
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
parameterValues.put(methodParameter, methodParameter.getAvailableValues());
|
||||||
}
|
}
|
||||||
while (!isAllValuesUsed(parameterOffset, parameterValues)) {
|
while (isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
||||||
List<MethodParamValue> resultRow = new ArrayList<>();
|
List<MethodParamValue> resultRow = new ArrayList<>();
|
||||||
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
||||||
resultRow.add(new MethodParamValue(methodParameter,
|
resultRow.add(new MethodParamValue(methodParameter,
|
||||||
@ -155,7 +174,7 @@ public class MethodParamBruteForce {
|
|||||||
Map<MethodParameter, List<Number>> parameterValues) {
|
Map<MethodParameter, List<Number>> parameterValues) {
|
||||||
List<MethodParameter> parameters = new ArrayList<>(parameterOffset.keySet());
|
List<MethodParameter> parameters = new ArrayList<>(parameterOffset.keySet());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < parameters.size() && !isAllValuesUsed(parameterOffset, parameterValues)) {
|
while (i < parameters.size() && isNotAllParameterValuesUsed(parameterOffset, parameterValues)) {
|
||||||
if (parameterOffset.get(parameters.get(i)) == parameterValues.get(parameters.get(i)).size() - 1) {
|
if (parameterOffset.get(parameters.get(i)) == parameterValues.get(parameters.get(i)).size() - 1) {
|
||||||
parameterOffset.put(parameters.get(i), 0);
|
parameterOffset.put(parameters.get(i), 0);
|
||||||
i++;
|
i++;
|
||||||
@ -169,13 +188,17 @@ public class MethodParamBruteForce {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAllValuesUsed(Map<MethodParameter, Integer> parameterOffset,
|
private boolean isNotAllParameterValuesUsed(Map<MethodParameter, Integer> parameterOffset,
|
||||||
Map<MethodParameter, List<Number>> parameterValues) {
|
Map<MethodParameter, List<Number>> parameterValues) {
|
||||||
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
for (MethodParameter methodParameter : parameterOffset.keySet()) {
|
||||||
if (parameterOffset.get(methodParameter) != parameterValues.get(methodParameter).size() - 1) {
|
if (parameterOffset.get(methodParameter) != parameterValues.get(methodParameter).size() - 1) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Method> getAvailableMethods() {
|
||||||
|
return methods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,41 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.ulstu.datamodel.ModelingResult;
|
import ru.ulstu.datamodel.ModelingResult;
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||||
|
import ru.ulstu.method.Method;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class TimeSeriesService {
|
public class TimeSeriesService {
|
||||||
private final MethodParamBruteForce methodParamBruteForce;
|
private final MethodParamBruteForce methodParamBruteForce;
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
public TimeSeriesService(MethodParamBruteForce methodParamBruteForce) {
|
public TimeSeriesService(MethodParamBruteForce methodParamBruteForce,
|
||||||
|
ApplicationContext applicationContext) {
|
||||||
this.methodParamBruteForce = methodParamBruteForce;
|
this.methodParamBruteForce = methodParamBruteForce;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelingResult getForecast(TimeSeries timeSeries, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
public ModelingResult getForecast(TimeSeries timeSeries, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
return methodParamBruteForce.getForecast(timeSeries, countPoints);
|
return methodParamBruteForce.getForecast(timeSeries, countPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSeries smoothTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
public ModelingResult getForecast(TimeSeries timeSeries, String methodClassName, int countPoints) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||||
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries).getTimeSeries();
|
return methodParamBruteForce.getForecast(timeSeries, methodClassName, countPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelingResult smoothTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||||
|
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Method> getAvailableMethods() {
|
||||||
|
return methodParamBruteForce.getAvailableMethods();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/*
|
|
||||||
* 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;
|
package ru.ulstu.service;
|
||||||
|
|
||||||
import ru.ulstu.datamodel.exception.ModelingException;
|
import ru.ulstu.datamodel.exception.ModelingException;
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
spring.main.banner-mode=off
|
spring.main.banner-mode=off
|
||||||
logging.level.tech.athene=DEBUG
|
logging.level.tech.athene=DEBUG
|
||||||
server.port=8080
|
server.port=8080
|
||||||
@ -11,3 +5,4 @@ spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
|
|||||||
joinfaces.primefaces.theme=afterwork
|
joinfaces.primefaces.theme=afterwork
|
||||||
joinfaces.primefaces.font-awesome=true
|
joinfaces.primefaces.font-awesome=true
|
||||||
time-series.db-path=time-series-db
|
time-series.db-path=time-series-db
|
||||||
|
messages.basename.path=messages_en.properties
|
@ -1,8 +1,3 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
messages.app-name=Time Series Smoothing
|
messages.app-name=Time Series Smoothing
|
||||||
messages.menu.home=Main
|
messages.menu.home=Main
|
||||||
messages.time_series_forecast=Time series forecast
|
messages.time_series_forecast=Time series forecast
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
messages.app-name=Time Series Smoothing
|
messages.app-name=Time Series Smoothing
|
||||||
messages.menu.home=Main
|
messages.menu.home=Main
|
||||||
messages.time_series_forecast=Time series forecast
|
messages.time_series_forecast=Time series forecast
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
messages.app-name=Time Series Smoothing
|
messages.app-name=Time Series Smoothing
|
||||||
messages.menu.home=На главную
|
messages.menu.home=На главную
|
||||||
messages.time_series_forecast=Прогноз временного ряда
|
messages.time_series_forecast=Прогноз временного ряда
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
~ You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ru"
|
<html lang="ru"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml">
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||||
@ -19,10 +13,24 @@
|
|||||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-light bg-light">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<a class="navbar-brand" href="/">
|
<a class="navbar-brand" href="/">
|
||||||
<img src="img/logo.png" width="180" height="60" alt="">
|
<img src="img/logo.png" width="180" height="60" alt="">
|
||||||
</a>
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="/">Главная <span class="sr-only">(current)</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/method">Выбрать метод</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div id="sidebar" class="collapse navbar-collapse sidebar-mobile">
|
<div id="sidebar" class="collapse navbar-collapse sidebar-mobile">
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (C) 2021 Anton Romanov - All Rights Reserved
|
|
||||||
~ You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||||
<html
|
<html
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||||
|
156
src/main/resources/templates/method.html
Normal file
156
src/main/resources/templates/method.html
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||||
|
<html
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<head>
|
||||||
|
<title>Time series smoothing</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
</head>
|
||||||
|
<div class="container" layout:fragment="content">
|
||||||
|
<script src="/webjars/highcharts/7.0.0/highcharts.js"></script>
|
||||||
|
<script th:inline="javascript" th:if="${timeSeries != null}">
|
||||||
|
$(document).ready(function () {
|
||||||
|
var chart = {
|
||||||
|
renderTo: 'container',
|
||||||
|
style: {
|
||||||
|
fontFamily: 'arial'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var title = {
|
||||||
|
text: [[#{messages.time_series_forecast}]]
|
||||||
|
};
|
||||||
|
var xAxis = {
|
||||||
|
categories: [[${dates}]],
|
||||||
|
title: {
|
||||||
|
enabled: true,
|
||||||
|
text: [[#{messages.date}]]
|
||||||
|
},
|
||||||
|
startOnTick: true,
|
||||||
|
endOnTick: true,
|
||||||
|
showLastLabel: true
|
||||||
|
};
|
||||||
|
var yAxis = {
|
||||||
|
title: {
|
||||||
|
text: [[#{messages.value}]]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var plotOptions = {
|
||||||
|
scatter: {
|
||||||
|
marker: {
|
||||||
|
radius: 5,
|
||||||
|
states: {
|
||||||
|
hover: {
|
||||||
|
enabled: true,
|
||||||
|
lineColor: 'rgb(100,100,100)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
hover: {
|
||||||
|
marker: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
headerFormat: '<b>{series.name}</b><br>',
|
||||||
|
pointFormat: '{point.y}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var series = [
|
||||||
|
{
|
||||||
|
name: [[#{messages.time_series}]],
|
||||||
|
color: 'rgba(119,152,191,0.5)',
|
||||||
|
data: [[${timeSeries}]]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: [[#{messages.time_series_model}]],
|
||||||
|
color: 'rgba(255,200,0,0.5)',
|
||||||
|
data: [[${model}]]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: [[#{messages.time_series_test_forecast}]],
|
||||||
|
color: 'rgba(255,0,0,0.5)',
|
||||||
|
data: [[${testForecast}]]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: [[#{messages.time_series_forecast_short}]],
|
||||||
|
color: 'rgba(255,0,0,0.5)',
|
||||||
|
data: [[${forecast}]]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
var json = {};
|
||||||
|
json.chart = chart;
|
||||||
|
json.title = title;
|
||||||
|
json.xAxis = xAxis;
|
||||||
|
json.yAxis = yAxis;
|
||||||
|
json.series = series;
|
||||||
|
json.plotOptions = plotOptions;
|
||||||
|
$('#chart').highcharts(json);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<form action="#" th:action="chartMethod" th:object="${chartForm}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-3">
|
||||||
|
<select id="select-set" class="selectpicker" data-live-search="true" th:field="*{set}"
|
||||||
|
data-width="90%" onchange="$('#select-ts').val(''); form.submit();">
|
||||||
|
<option value="">Набор временных рядов</option>
|
||||||
|
<option th:each="set : ${sets}"
|
||||||
|
th:value="${set.key}"
|
||||||
|
th:utext="${set.key}">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<script th:inline="javascript" th:if="*{set != null}">
|
||||||
|
$('#select-set').val([[*{set.key}]]);
|
||||||
|
$('#select-set').selectpicker('refresh');
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<select id="select-ts" class="selectpicker" data-live-search="true" th:field="*{timeSeriesMeta}"
|
||||||
|
data-width="90%" onchange="form.submit();">
|
||||||
|
<option value="">Временной ряд</option>
|
||||||
|
<option th:each="ts : ${listTimeSeries}"
|
||||||
|
th:value="${ts.key}"
|
||||||
|
th:utext="${ts.key}">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<script th:inline="javascript" th:if="*{timeSeriesMeta != null}">
|
||||||
|
$('#select-ts').val([[*{timeSeriesMeta.key}]]);
|
||||||
|
$('#select-ts').selectpicker('refresh');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<select id="select-method" class="selectpicker" data-live-search="true" th:field="*{methodClassName}"
|
||||||
|
data-width="90%" onchange="form.submit();">
|
||||||
|
<option value="">Метод прогнозирования</option>
|
||||||
|
<option th:each="method : ${methods}"
|
||||||
|
th:value="${method.key}"
|
||||||
|
th:utext="${method.name}">
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<script th:inline="javascript" th:if="*{methodClassName != null && methodClassName != ''}">
|
||||||
|
$('#select-method').val([[*{methodClassName}]]);
|
||||||
|
$('#select-method').selectpicker('refresh');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
||||||
|
<p> Метод прогнозирования: <span th:text="${forecastDescription.timeSeriesMethod}"> </span>
|
||||||
|
<p> Оценка: <span th:text="${forecastDescription.score.value}"> </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-9">
|
||||||
|
<div id="chart" style="width: 550px; height: 400px; margin: 0 auto"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user