Compare commits
27 Commits
master
...
3-f-transf
Author | SHA1 | Date | |
---|---|---|---|
3f23d32c87 | |||
d1b57b2f76 | |||
0cd1e535ad | |||
1c24fb8055 | |||
cb52a2cce6 | |||
259ca3757e | |||
57e588f4a0 | |||
f4b8089f29 | |||
d236081a45 | |||
ab05f5a509 | |||
63791ecfa0 | |||
7a9044c090 | |||
2b21708d9d | |||
a81149bf01 | |||
fae21d0f87 | |||
55275e1716 | |||
e9adff9a87 | |||
|
0da256106e | ||
|
a8b6cf7d29 | ||
|
292e774d8e | ||
|
4cb14518db | ||
|
ffe303c7af | ||
|
682370f3da | ||
|
c06688d744 | ||
|
78c02d7dad | ||
0a017f8667 | |||
371dfe5665 |
35
build.gradle
35
build.gradle
@ -1,23 +1,27 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.4.2'
|
||||
id 'io.spring.dependency-management' version '1.1.7'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id 'org.springframework.boot' version '2.6.4'
|
||||
}
|
||||
|
||||
group = 'ru.ulstu'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
jar {
|
||||
archivesBaseName = 'time-series-smoothing'
|
||||
}
|
||||
|
||||
group 'ru.ulstu'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = uri("http://repo.athene.tech/repository/maven-central/")
|
||||
allowInsecureProtocol(true)
|
||||
url "https://repo.athene.tech/repository/maven-central/"
|
||||
}
|
||||
maven {
|
||||
url "https://repo.athene.tech/repository/maven-releases/"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -30,19 +34,18 @@ dependencies {
|
||||
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-test'
|
||||
// web client
|
||||
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux'
|
||||
implementation group: 'org.slf4j', name: 'slf4j-api'
|
||||
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
|
||||
implementation group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity6'
|
||||
implementation group: 'org.slf4j', name: 'slf4j-api', version: versionSLF4J
|
||||
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.0.0'
|
||||
implementation group: 'org.javassist', name: 'javassist', version: '3.25.0-GA'
|
||||
implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: versionJetty
|
||||
implementation group: 'org.json', name: 'json', version: '20220320'
|
||||
|
||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind'
|
||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations'
|
||||
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310'
|
||||
|
||||
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.8.4'
|
||||
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
|
||||
|
||||
implementation group: 'org.webjars', name: 'jquery', version: '3.6.0'
|
||||
implementation group: 'org.webjars', name: 'bootstrap', version: '4.6.0'
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,7 +1,6 @@
|
||||
#Mon Dec 28 10:00:20 PST 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
|
@ -1,72 +0,0 @@
|
||||
package ru.ulstu;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class DateUtils {
|
||||
|
||||
public static Date clearTime(Date date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Calendar getCalendar(Date date) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static List<Month> getMonths() {
|
||||
return Arrays.asList(Month.values());
|
||||
}
|
||||
|
||||
public static Date instantToDate(Instant instant) {
|
||||
return Date.from(instant);
|
||||
}
|
||||
|
||||
public static Date localDateToDate(LocalDate localDate) {
|
||||
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
public static Date localDateTimeToDate(LocalDateTime localDate) {
|
||||
return Date.from(localDate.atZone(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
public static Date localTimeToDate(LocalTime localTime) {
|
||||
return Date.from(localTime.atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
public static Date addDays(Date date, int count) {
|
||||
Calendar cal = getCalendar(date);
|
||||
cal.add(Calendar.DAY_OF_MONTH, count);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static Date addYears(Date date, int count) {
|
||||
Calendar cal = getCalendar(date);
|
||||
cal.add(Calendar.YEAR, count);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
public static LocalDate convertToLocalDate(Date dateToConvert) {
|
||||
return dateToConvert.toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package ru.ulstu;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class HttpUtils {
|
||||
public static String getUserIp(HttpServletRequest request) {
|
||||
|
@ -0,0 +1,21 @@
|
||||
package ru.ulstu.configuration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class SwaggerConfiguration {
|
||||
private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi swaggerApi() {
|
||||
log.info("Creating Swagger API configuration bean");
|
||||
return GroupedOpenApi.builder()
|
||||
.group("timetable-api")
|
||||
.pathsToMatch(ApiConfiguration.API_1_0 + "**")
|
||||
.build();
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
|
||||
@Configuration
|
||||
|
@ -0,0 +1,14 @@
|
||||
package ru.ulstu.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@Configuration
|
||||
public class WebClientConfiguration {
|
||||
@Bean
|
||||
public WebClient webClient(WebClient.Builder webClientBuilder) {
|
||||
return webClientBuilder.build(); //contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
}
|
||||
}
|
40
src/main/java/ru/ulstu/controller/AnomalyController.java
Normal file
40
src/main/java/ru/ulstu/controller/AnomalyController.java
Normal file
@ -0,0 +1,40 @@
|
||||
package ru.ulstu.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.ulstu.configuration.ApiConfiguration;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.db.DbService;
|
||||
import ru.ulstu.db.model.TimeSeriesSet;
|
||||
import ru.ulstu.estimate.CompressionMetricService;
|
||||
import ru.ulstu.service.UtilService;
|
||||
import ru.ulstu.target.AnomalyDifferenceSmoothed;
|
||||
import ru.ulstu.target.Target;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(ApiConfiguration.API_1_0)
|
||||
public class AnomalyController {
|
||||
|
||||
private final DbService dbService;
|
||||
private final Target target;
|
||||
|
||||
public AnomalyController(CompressionMetricService compressionMetricService, DbService dbService, AnomalyDifferenceSmoothed anomalyDifferenceSmoothed) {
|
||||
this.dbService = dbService;
|
||||
this.target = anomalyDifferenceSmoothed;
|
||||
}
|
||||
|
||||
@GetMapping ("getAnomalyAtDifferenceSmothed")
|
||||
@Operation(description = "Получить аномальные значения")
|
||||
public TimeSeries getAnomalyAtDifferenceSmothed(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {
|
||||
var timeSeries = dbService.getTimeSeries(new TimeSeriesSet(setKey), timeSeriesKey);
|
||||
var timeSeriesResult = target.calculate(timeSeries);
|
||||
return timeSeriesResult;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package ru.ulstu.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.ulstu.configuration.ApiConfiguration;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.db.DbService;
|
||||
import ru.ulstu.db.model.TimeSeriesSet;
|
||||
import ru.ulstu.estimate.CompressionMetricService;
|
||||
import ru.ulstu.service.PrometheusService;
|
||||
import ru.ulstu.service.UtilService;
|
||||
import ru.ulstu.target.AnomalyDifferenceSmoothed;
|
||||
import ru.ulstu.target.Target;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(ApiConfiguration.API_1_0)
|
||||
public class CompressionMetricController {
|
||||
|
||||
private final UtilService utilService;
|
||||
private final DbService dbService;
|
||||
private final PrometheusService prometheusService;
|
||||
private final CompressionMetricService compressionMetricService;
|
||||
private final Target target;
|
||||
|
||||
public CompressionMetricController(UtilService utilService, DbService dbService, PrometheusService prometheusService, CompressionMetricService compressionMetricService, AnomalyDifferenceSmoothed anomalyDifferenceSmoothed) {
|
||||
this.utilService = utilService;
|
||||
this.dbService = dbService;
|
||||
this.prometheusService = prometheusService;
|
||||
this.compressionMetricService = compressionMetricService;
|
||||
this.target = anomalyDifferenceSmoothed;
|
||||
}
|
||||
|
||||
@GetMapping("getMetricAtAnomaly")
|
||||
@Operation(description = "Получить метрику сжатия")
|
||||
public ResponseEntity<TimeSeries> getMetricAtAnomaly(@RequestParam("setKey") String setKey, @RequestParam("timeSeriesKey") String timeSeriesKey) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {
|
||||
var timeSeries = dbService.getTimeSeries(new TimeSeriesSet(setKey), timeSeriesKey);
|
||||
var timeSeriesResult = compressionMetricService.getCompressionTimeSeries(timeSeries);
|
||||
return new ResponseEntity<>(timeSeriesResult, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("getMetricAtAnomalyOfRandom")
|
||||
@Operation(description = "Получить метрику сжатия")
|
||||
public ResponseEntity<TimeSeries> getMetricAtAnomalyOfRandom(@RequestParam("lenght") int len) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
var timeSeries = utilService.getRandomTimeSeries(len);
|
||||
var timeSeriesResult = compressionMetricService.getCompressionTimeSeries(timeSeries);
|
||||
return new ResponseEntity<>(timeSeriesResult, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("getMetricAtAnomalyOfPrometheus")
|
||||
@Operation(description = "Получить метрику сжатия")
|
||||
public ResponseEntity<TimeSeries> getMetricAtAnomalyOfPrometheus(@RequestParam("query") String query) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
var timeSeries = prometheusService.executionQueryRange(query);
|
||||
var timeSeriesResult = compressionMetricService.getCompressionTimeSeries(timeSeries);
|
||||
return new ResponseEntity<>(timeSeriesResult, HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import ru.ulstu.DateUtils;
|
||||
import ru.ulstu.datamodel.ChartForm;
|
||||
import ru.ulstu.datamodel.ModelingResult;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
@ -17,11 +16,8 @@ import ru.ulstu.statistic.StatisticService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
@ -58,73 +54,60 @@ public class IndexController {
|
||||
if (chartForm.getTimeSeriesMeta() != null
|
||||
&& chartForm.getTimeSeriesMeta().getKey() != null
|
||||
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()) {
|
||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()),
|
||||
null,
|
||||
chartForm.isNeedForecast(),
|
||||
model);
|
||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), null, model);
|
||||
}
|
||||
return "index";
|
||||
}
|
||||
|
||||
private void addChartToModel(TimeSeries timeSeries, String method, boolean needForecast, Model model) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||
if (needForecast) {
|
||||
int countForecastPoints = timeSeries.getLength() > 20 ? 10 : timeSeries.getLength() / 3;
|
||||
TimeSeries timeSeriesModel;
|
||||
ModelingResult modelingResult;
|
||||
if (method == null) {
|
||||
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
||||
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
||||
} else {
|
||||
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));
|
||||
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;
|
||||
TimeSeries timeSeriesModel;
|
||||
ModelingResult modelingResult;
|
||||
if (method == null) {
|
||||
timeSeriesModel = timeSeriesService.smoothTimeSeries(timeSeries).getTimeSeries();
|
||||
modelingResult = timeSeriesService.getForecast(timeSeries, countForecastPoints);
|
||||
} else {
|
||||
model.addAttribute("dates", getDatesForChart(timeSeries, new TimeSeries()));
|
||||
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 {
|
||||
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));
|
||||
}
|
||||
|
||||
private List<String> getDatesForChart(TimeSeries timeSeries, TimeSeries forecast) {
|
||||
return Stream.concat(timeSeries.getValues().stream(), forecast.getValues().stream().skip(1))
|
||||
.map(TimeSeriesValue::getDate)
|
||||
.sorted()
|
||||
.map(date -> {
|
||||
Date date1 = DateUtils.addYears(DateUtils.localDateTimeToDate(date), 10);
|
||||
LocalDateTime ldt = date1.toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDateTime();
|
||||
return ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));
|
||||
})
|
||||
.map(date -> date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
@ -149,10 +132,7 @@ public class IndexController {
|
||||
&& !chartForm.getTimeSeriesMeta().getKey().isEmpty()
|
||||
&& chartForm.getMethodClassName() != null
|
||||
&& !chartForm.getMethodClassName().equals("")) {
|
||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()),
|
||||
chartForm.getMethodClassName(),
|
||||
chartForm.isNeedForecast(),
|
||||
model);
|
||||
addChartToModel(dbService.getTimeSeries(chartForm.getSet(), chartForm.getTimeSeriesMeta().getKey()), chartForm.getMethodClassName(), model);
|
||||
}
|
||||
return "method";
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package ru.ulstu.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -22,6 +20,8 @@ import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.method.Method;
|
||||
import ru.ulstu.service.TimeSeriesService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -91,10 +91,4 @@ public class TimeSeriesController {
|
||||
public ResponseEntity<List<TimeSeries>> getGroupedTendencies(@RequestBody List<TimeSeries> timeSeriesList) {
|
||||
return new ResponseEntity<>(timeSeriesService.getGroupedTendencies(timeSeriesList), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("getMaxSmoothing")
|
||||
@Operation(description = "Получить максимальное сглаживание временного ряда")
|
||||
public ResponseEntity<ModelingResult> getMaxSmoothing(@RequestBody TimeSeries timeSeries) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
return new ResponseEntity<>(timeSeriesService.getMaxSmoothedTimeSeries(timeSeries), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,9 @@ import ru.ulstu.db.model.TimeSeriesSet;
|
||||
|
||||
public class ChartForm {
|
||||
private TimeSeriesSet set;
|
||||
private TimeSeriesMeta timeSeriesMeta = null;
|
||||
private TimeSeriesMeta timeSeriesMeta;
|
||||
private String methodClassName = null;
|
||||
|
||||
private boolean needForecast;
|
||||
|
||||
public TimeSeriesSet getSet() {
|
||||
return set;
|
||||
}
|
||||
@ -33,12 +31,4 @@ public class ChartForm {
|
||||
public void setMethodClassName(String methodClassName) {
|
||||
this.methodClassName = methodClassName;
|
||||
}
|
||||
|
||||
public boolean isNeedForecast() {
|
||||
return needForecast;
|
||||
}
|
||||
|
||||
public void setNeedForecast(boolean needForecast) {
|
||||
this.needForecast = needForecast;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package ru.ulstu.datamodel;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class ForecastParams {
|
||||
@NotNull
|
||||
private TimeSeries originalTimeSeries;
|
||||
|
@ -1,8 +1,9 @@
|
||||
package ru.ulstu.datamodel;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class SmoothingParams {
|
||||
@NotNull
|
||||
private TimeSeries originalTimeSeries;
|
||||
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class TimeSeries {
|
||||
@ -88,6 +89,20 @@ public class TimeSeries {
|
||||
throw new RuntimeException("Индекс выходит за границы временного ряда");
|
||||
}
|
||||
|
||||
public TimeSeriesValue getMax() {
|
||||
if ((values.size() > 0)) {
|
||||
return values.stream().max(Comparator.comparing(TimeSeriesValue::getValue)).get();
|
||||
}
|
||||
throw new RuntimeException("Временной ряд пустой");
|
||||
}
|
||||
|
||||
public TimeSeriesValue getMin() {
|
||||
if ((values.size() > 0)) {
|
||||
return values.stream().min(Comparator.comparing(TimeSeriesValue::getValue)).get();
|
||||
}
|
||||
throw new RuntimeException("Временной ряд пустой");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeSeries{" +
|
||||
|
@ -0,0 +1,93 @@
|
||||
package ru.ulstu.estimate;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.datamodel.Model;
|
||||
import ru.ulstu.datamodel.ModelingResult;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.method.MethodParamValue;
|
||||
import ru.ulstu.method.ftransform.FTransform;
|
||||
import ru.ulstu.score.ScoreMethod;
|
||||
import ru.ulstu.service.MethodParamBruteForce;
|
||||
import ru.ulstu.service.TimeSeriesService;
|
||||
import ru.ulstu.service.UtilService;
|
||||
import ru.ulstu.target.AnomalyDifferenceSmoothed;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CompressionMetricService {
|
||||
|
||||
private final int DEFAULT_THREAD_COUNT = 10;
|
||||
private final TimeSeriesService timeSeriesService;
|
||||
private final FTransform fTransform;
|
||||
private final MethodParamBruteForce methodParamBruteForce;
|
||||
private final UtilService utilService;
|
||||
private final ScoreMethod scoreMethod;
|
||||
|
||||
private final AnomalyDifferenceSmoothed anomalyDifferenceSmoothed;
|
||||
private final ExecutorService executors = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);
|
||||
|
||||
public CompressionMetricService(TimeSeriesService timeSeriesService, FTransform fTransform, MethodParamBruteForce methodParamBruteForce, UtilService utilService, ScoreMethod scoreMethod, AnomalyDifferenceSmoothed anomalyDifferenceSmoothed) {
|
||||
this.timeSeriesService = timeSeriesService;
|
||||
this.fTransform = fTransform;
|
||||
this.methodParamBruteForce = methodParamBruteForce;
|
||||
this.utilService = utilService;
|
||||
this.scoreMethod = scoreMethod;
|
||||
this.anomalyDifferenceSmoothed = anomalyDifferenceSmoothed;
|
||||
}
|
||||
|
||||
public TimeSeries getCompressionTimeSeries(TimeSeries ts) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
//ModelingResult modelingResult = timeSeriesService.smoothTimeSeries(ts, "FTransform");
|
||||
ModelingResult modelingResult = getCompressionTimeSeriesWithFTransform(ts);
|
||||
//var ts1 = fTransform.getForecast(ts, )
|
||||
var timeSeriesAnomalyResult = anomalyDifferenceSmoothed.calculate(modelingResult.getTimeSeries());
|
||||
var timeSeriesAnomaly = anomalyDifferenceSmoothed.calculate(ts);
|
||||
System.out.println(ts.getLength()+"\t"
|
||||
+timeSeriesAnomaly.getLength()+"\t"
|
||||
+Math.abs(timeSeriesAnomaly.getLength() - timeSeriesAnomalyResult.getLength())+"\t"
|
||||
+(double)modelingResult.getTimeSeries().getLength()/ts.getLength()+"\t"
|
||||
+modelingResult.getScore().getDoubleValue());
|
||||
System.out.println(timeSeriesAnomaly);
|
||||
System.out.println(timeSeriesAnomalyResult);
|
||||
System.out.println(utilService.getTimeSeriesToString(ts));
|
||||
System.out.println(utilService.getTimeSeriesToString(modelingResult.getTimeSeries()));
|
||||
return modelingResult.getTimeSeries();
|
||||
}
|
||||
|
||||
protected ModelingResult getCompressionTimeSeriesWithFTransform(TimeSeries timeSeries) throws ExecutionException, InterruptedException {
|
||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
||||
|
||||
Map<LocalDateTime, Double> tsValues = timeSeries.getValues().stream()
|
||||
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue,
|
||||
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
|
||||
|
||||
|
||||
List<List<MethodParamValue>> availableParametersValues = methodParamBruteForce.getAvailableParametersValues(timeSeries, fTransform.getAvailableParameters());
|
||||
for (List<MethodParamValue> parametersValues : availableParametersValues) {
|
||||
results.add(executors.submit(() -> {
|
||||
Model model = fTransform.getModel(timeSeries, parametersValues);
|
||||
return new ModelingResult(model.getTimeSeriesModel(),
|
||||
null,
|
||||
parametersValues,
|
||||
scoreMethod.getScore(tsValues, model.getTimeSeriesModel()), fTransform);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
for (Future<ModelingResult> futureModelingResult : results) {
|
||||
results2.add(futureModelingResult.get());
|
||||
}
|
||||
return results2.stream()
|
||||
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
}
|
11
src/main/java/ru/ulstu/http/HttpClientService.java
Normal file
11
src/main/java/ru/ulstu/http/HttpClientService.java
Normal file
@ -0,0 +1,11 @@
|
||||
package ru.ulstu.http;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class HttpClientService {
|
||||
|
||||
public void get(){
|
||||
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package ru.ulstu.http;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.core.publisher.Mono;
|
||||
import ru.ulstu.method.fuzzy.FuzzyRuleDataDto;
|
||||
import ru.ulstu.method.fuzzy.OutputValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
public class HttpService {
|
||||
private final WebClient client = getWebClient();
|
||||
private final static String USER_NAME = "admin";
|
||||
private final static String PASSWORD = "admin";
|
||||
|
||||
public WebClient getWebClient() {
|
||||
return WebClient.builder()
|
||||
.defaultHeader(HttpHeaders.AUTHORIZATION, "Basic " +
|
||||
Base64.getEncoder().encodeToString((USER_NAME + ":" + PASSWORD).getBytes()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public List<OutputValue> post(String url, FuzzyRuleDataDto requestBody) {
|
||||
List<OutputValue> result = new ArrayList<>();
|
||||
|
||||
try {
|
||||
OutputValue[] res = client
|
||||
.post()
|
||||
.uri(url)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(Mono.just(requestBody), FuzzyRuleDataDto.class)
|
||||
.retrieve()
|
||||
.bodyToMono(OutputValue[].class)
|
||||
.block();
|
||||
if (res != null && res.length > 0) {
|
||||
result = Arrays.stream(res).toList();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
66
src/main/java/ru/ulstu/http/WebClientService.java
Normal file
66
src/main/java/ru/ulstu/http/WebClientService.java
Normal file
@ -0,0 +1,66 @@
|
||||
package ru.ulstu.http;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class WebClientService {
|
||||
private final Logger log = LoggerFactory.getLogger(WebClientService.class);
|
||||
private final WebClient client;
|
||||
|
||||
public WebClientService(WebClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public JSONObject post(String url, JSONObject postData) {
|
||||
log.debug("Service call: {}", url);
|
||||
JSONObject response = null;
|
||||
try {
|
||||
response = new JSONObject(Optional.ofNullable(client
|
||||
.post()
|
||||
.uri(url)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(BodyInserters.fromValue(postData.toString()))
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.toFuture().get()).orElse("{response:\"empty\"}"));
|
||||
} catch (Exception e) {
|
||||
return new JSONObject("{response:\"empty\"}");
|
||||
}
|
||||
log.debug("Service response: {}", response);
|
||||
return response;
|
||||
}
|
||||
|
||||
public JSONArray get(String url) {
|
||||
log.debug("Service call: {}", url);
|
||||
try {
|
||||
String response = client
|
||||
.get()
|
||||
.uri(url)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.timeout(Duration.ofMinutes(1))
|
||||
.toFuture().get();
|
||||
if (response.startsWith("[")) {
|
||||
return new JSONArray(response);
|
||||
} else {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
jsonArray.put(0, new JSONObject(response));
|
||||
return jsonArray;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
package ru.ulstu.method.ftransform;
|
||||
|
||||
/**
|
||||
* Треугольная функция принадлежности
|
||||
* Базисная функция
|
||||
*/
|
||||
public class AComponent {
|
||||
private int start; // левая граница треугольника
|
||||
private int end; // правая граница треугольника
|
||||
private int top; // вершина треугольника
|
||||
private double start; // левая граница треугольника
|
||||
private double end; // правая граница треугольника
|
||||
private double top; // вершина треугольника
|
||||
|
||||
public int getStart() {
|
||||
public double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public AComponent() {
|
||||
}
|
||||
|
||||
public AComponent(int start, int top, int end) {
|
||||
public AComponent(double start, double top, double end) {
|
||||
this.start = start;
|
||||
this.top = top;
|
||||
this.end = end;
|
||||
@ -26,19 +26,23 @@ public class AComponent {
|
||||
}
|
||||
|
||||
|
||||
public int getEnd() {
|
||||
public double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(int end) {
|
||||
public void setEnd(double end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getTop() {
|
||||
public double getTop() {
|
||||
return top;
|
||||
}
|
||||
|
||||
public void setTop(int top) {
|
||||
public int getTopInt() {
|
||||
return (int) Math.round(top);
|
||||
}
|
||||
|
||||
public void setTop(double top) {
|
||||
this.top = top;
|
||||
}
|
||||
|
||||
@ -54,4 +58,9 @@ public class AComponent {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "start=" + start;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,19 @@ package ru.ulstu.method.ftransform;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.ulstu.datamodel.Model;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.method.Method;
|
||||
import ru.ulstu.method.MethodParamValue;
|
||||
import ru.ulstu.method.MethodParameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class FTransform extends Method {
|
||||
private final static int NUMBER_OF_FUZZY_VALUES = 3;
|
||||
|
||||
@Override
|
||||
protected FTransformModel getModelOfValidTimeSeries(TimeSeries ts,
|
||||
@ -29,8 +34,8 @@ public class FTransform extends Method {
|
||||
sum1 += membership * ts.getNumericValue(j);
|
||||
sum2 += membership;
|
||||
}
|
||||
piecewiseLinearTrend.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2);
|
||||
tsModel.addValue(ts.getValue(aComponent.getTop()), sum1 / sum2);
|
||||
piecewiseLinearTrend.addValue(ts.getValue(aComponent.getTopInt()), sum1 / sum2);
|
||||
tsModel.addValue(ts.getValue(aComponent.getTopInt()), sum1 / sum2);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
@ -41,27 +46,27 @@ public class FTransform extends Method {
|
||||
while (currentPoint < ts.getLength()) {
|
||||
int startPoint = (currentPoint == 0)
|
||||
? 0
|
||||
: piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop();
|
||||
AComponent bf = new AComponent(startPoint, currentPoint, (int) (currentPoint + Math.round(numberOfCoveredPoints / 2.0)));
|
||||
if (bf.getStart() < 0) {
|
||||
bf.setStart(0);
|
||||
: piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTopInt();
|
||||
AComponent aComponent = new AComponent(startPoint, currentPoint, (int) (currentPoint + Math.round(numberOfCoveredPoints / 2.0)));
|
||||
if (aComponent.getStart() < 0) {
|
||||
aComponent.setStart(0);
|
||||
}
|
||||
if (bf.getEnd() > ts.getLength() - 1) {
|
||||
bf.setEnd(ts.getLength() - 1);
|
||||
if (aComponent.getEnd() > ts.getLength() - 1) {
|
||||
aComponent.setEnd(ts.getLength() - 1);
|
||||
}
|
||||
|
||||
if (bf.getTop() > ts.getLength() - 1) {
|
||||
bf.setTop(ts.getLength() - 1);
|
||||
if (aComponent.getTop() > ts.getLength() - 1) {
|
||||
aComponent.setTop(ts.getLength() - 1);
|
||||
}
|
||||
|
||||
piecewiseLinearTrend.add(bf);
|
||||
piecewiseLinearTrend.add(aComponent);
|
||||
currentPoint += deltaForTriangle;
|
||||
}
|
||||
if (piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd() != piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop()) {
|
||||
AComponent bf = new AComponent(piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop(),
|
||||
AComponent aComponent = new AComponent(piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getTop(),
|
||||
piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd(),
|
||||
piecewiseLinearTrend.get(piecewiseLinearTrend.size() - 1).getEnd());
|
||||
piecewiseLinearTrend.add(bf);
|
||||
piecewiseLinearTrend.add(aComponent);
|
||||
}
|
||||
return piecewiseLinearTrend;
|
||||
}
|
||||
@ -69,6 +74,25 @@ public class FTransform extends Method {
|
||||
@Override
|
||||
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) {
|
||||
FTransformModel fTransformModel = (FTransformModel) model;
|
||||
double minValue = fTransformModel.getPiecewiseLinearTrend().getValues().stream().map(TimeSeriesValue::getValue).min(Double::compareTo).orElse(0.0);
|
||||
double maxValue = fTransformModel.getPiecewiseLinearTrend().getValues().stream().map(TimeSeriesValue::getValue).max(Double::compareTo).orElse(0.0);
|
||||
List<AComponent> fuzzyValues = new ArrayList<>();
|
||||
double diff = (maxValue - minValue) / NUMBER_OF_FUZZY_VALUES;
|
||||
for (int i = 0; i < NUMBER_OF_FUZZY_VALUES; i++) {
|
||||
fuzzyValues.add(new AComponent(minValue + i * diff, minValue + i * diff + diff / 2, minValue + i * diff + diff));
|
||||
}
|
||||
List<AComponent> fuzzyTimeSeries = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < model.getTimeSeriesModel().getLength(); i++) {
|
||||
for (AComponent fuzzyValue : fuzzyValues) {
|
||||
if (model.getTimeSeriesModel().getValue(i).getValue() >= fuzzyValue.getStart()
|
||||
&& model.getTimeSeriesModel().getValue(i).getValue() <= fuzzyValue.getEnd()) {
|
||||
fuzzyTimeSeries.add(fuzzyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int t = 1; t < forecast.getLength(); t++) {
|
||||
forecast.getValues().get(t).setValue(fTransformModel.getPiecewiseLinearTrend().getLastValue().getValue());
|
||||
}
|
||||
@ -80,6 +104,16 @@ public class FTransform extends Method {
|
||||
return FTransformModel.getAvailableParameters();
|
||||
}
|
||||
|
||||
// private AComponent findFuzzyValueByPrevious(List<AComponent> fuzzyTimeSeries, AComponent currentFuzzyValue) {
|
||||
// Map<AComponent, Integer> mostFrequentValues = new HashMap<>();
|
||||
// for (int i = 0; i < fuzzyTimeSeries.size() - 1; i++) {
|
||||
// if (fuzzyTimeSeries.get(i).equals(currentFuzzyValue)) {
|
||||
// mostFrequentValues.put(fuzzyTimeSeries.get(i + 1), mostFrequentValues.getOrDefault(fuzzyTimeSeries.get(i + 1), 0) + 1);
|
||||
// }
|
||||
// }
|
||||
// mostFrequentValues.entrySet().stream()
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "F - преобразование";
|
||||
|
@ -1,33 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy;
|
||||
|
||||
public class FuzzyRuleDataDto {
|
||||
private String[] fuzzyTerms;
|
||||
private int window = 3;
|
||||
private int horizon = 1;
|
||||
|
||||
public FuzzyRuleDataDto(String[] fuzzyTimeSeries, int window, int horizon) {
|
||||
this.fuzzyTerms = fuzzyTimeSeries;
|
||||
this.window = window;
|
||||
this.horizon = horizon;
|
||||
}
|
||||
|
||||
public String[] getFuzzyTerms() {
|
||||
return fuzzyTerms;
|
||||
}
|
||||
|
||||
public void setFuzzyTerms(String[] fuzzyTerms) {
|
||||
this.fuzzyTerms = fuzzyTerms;
|
||||
}
|
||||
|
||||
public int getWindow() {
|
||||
return window;
|
||||
}
|
||||
|
||||
public void setWindow(int window) {
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
public int getHorizon() {
|
||||
return horizon;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy;
|
||||
|
||||
public class OutputValue {
|
||||
private String variable;
|
||||
private String fuzzyTerm;
|
||||
private Double degree;
|
||||
|
||||
public OutputValue(String variable, String fuzzyTerm, Double degree) {
|
||||
this.variable = variable;
|
||||
this.fuzzyTerm = fuzzyTerm;
|
||||
this.degree = degree;
|
||||
}
|
||||
|
||||
public String getFuzzyTerm() {
|
||||
return fuzzyTerm;
|
||||
}
|
||||
|
||||
public void setFuzzyTerm(String fuzzyTerm) {
|
||||
this.fuzzyTerm = fuzzyTerm;
|
||||
}
|
||||
|
||||
public Double getDegree() {
|
||||
return degree;
|
||||
}
|
||||
|
||||
public void setDegree(Double degree) {
|
||||
this.degree = degree;
|
||||
}
|
||||
|
||||
public String getVariable() {
|
||||
return variable;
|
||||
}
|
||||
|
||||
public void setVariable(String variable) {
|
||||
this.variable = variable;
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.ulstu.datamodel.Model;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.http.HttpService;
|
||||
import ru.ulstu.method.Method;
|
||||
import ru.ulstu.method.MethodParamValue;
|
||||
import ru.ulstu.method.MethodParameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PlainFuzzy extends Method {
|
||||
private final HttpService httpService = new HttpService();
|
||||
|
||||
@Override
|
||||
public List<MethodParameter> getAvailableParameters() {
|
||||
return PlainFuzzyModel.getAvailableParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Model getModelOfValidTimeSeries(TimeSeries timeSeries, List<MethodParamValue> parameters) {
|
||||
PlainFuzzyModel model = new PlainFuzzyModel(timeSeries, parameters);
|
||||
List<Triangle> fuzzySets = generateFuzzySets(timeSeries, model.getNumberOfFuzzyTerms().getIntValue());
|
||||
model.setFuzzySets(fuzzySets);
|
||||
for (TimeSeriesValue tsVal : timeSeries.getValues()) {
|
||||
model.getTimeSeriesModel().addValue(new TimeSeriesValue(
|
||||
tsVal.getDate(),
|
||||
getMaxMembership(fuzzySets, tsVal).getTop()));
|
||||
model.getFuzzyTimeSeries().add(getMaxMembership(fuzzySets, tsVal));
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private List<Triangle> generateFuzzySets(TimeSeries timeSeries, Integer numberOfFuzzyTerms) {
|
||||
// Universum
|
||||
DoubleSummaryStatistics stat = timeSeries.getValues()
|
||||
.stream()
|
||||
.mapToDouble(TimeSeriesValue::getValue)
|
||||
.summaryStatistics();
|
||||
double min = stat.getMin();
|
||||
double max = stat.getMax();
|
||||
|
||||
// Generate fuzzy sets
|
||||
List<Triangle> fuzzySets = new ArrayList<>();
|
||||
double delta = ((max - min) / (numberOfFuzzyTerms - 1));
|
||||
|
||||
for (int i = 0; i < numberOfFuzzyTerms; i++) {
|
||||
fuzzySets.add(new Triangle(min + i * delta - delta,
|
||||
min + i * delta,
|
||||
min + i * delta + delta, i));
|
||||
}
|
||||
return fuzzySets;
|
||||
}
|
||||
|
||||
private Triangle getMaxMembership(List<Triangle> fuzzySets, TimeSeriesValue tsVal) {
|
||||
Triangle maxTriangle = fuzzySets.get(0);
|
||||
double membersip = 0;
|
||||
for (Triangle triangle : fuzzySets) {
|
||||
if (membersip < triangle.getValueAtPoint(tsVal.getValue())) {
|
||||
maxTriangle = triangle;
|
||||
membersip = triangle.getValueAtPoint(tsVal.getValue());
|
||||
}
|
||||
}
|
||||
return maxTriangle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimeSeries getForecastWithValidParams(Model model, TimeSeries forecast) throws ModelingException {
|
||||
PlainFuzzyModel pfm = ((PlainFuzzyModel) model);
|
||||
List<String> fuzzyTimeSeries = pfm.getFuzzyTimeSeries().stream().map(Triangle::getLabel).toList();
|
||||
List<OutputValue> result = httpService.post("http://plans.athene.tech/inferenceRest/get-inference-by-generated-rules",
|
||||
new FuzzyRuleDataDto(fuzzyTimeSeries.toArray(String[]::new), 2, forecast.getLength()));
|
||||
List<Double> forecastValues = result.stream().map(r -> pfm.getTopValueByLabel(r.getFuzzyTerm())).toList();
|
||||
List<TimeSeriesValue> values = forecast.getValues();
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
if (forecastValues.isEmpty()) {
|
||||
values.get(i).setValue(pfm.getTimeSeriesModel().getValues().getLast().getValue());
|
||||
} else {
|
||||
if (forecastValues.size() > i) {
|
||||
values.get(i).setValue(forecastValues.get(i));
|
||||
} else {
|
||||
values.get(i).setValue(forecastValues.getLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
return forecast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Нечеткая модель";
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy;
|
||||
|
||||
import ru.ulstu.datamodel.Model;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.method.MethodParamValue;
|
||||
import ru.ulstu.method.MethodParameter;
|
||||
import ru.ulstu.method.fuzzy.parameter.NumberOfFuzzyTerms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class PlainFuzzyModel extends Model {
|
||||
private final MethodParamValue numberOfFuzzyTerms = new MethodParamValue(NumberOfFuzzyTerms.getInstance(), 2);
|
||||
private final List<Triangle> fuzzyTimeSeries = new ArrayList<>();
|
||||
private List<Triangle> fuzzySets = new ArrayList<>();
|
||||
|
||||
protected PlainFuzzyModel(TimeSeries ts, List<MethodParamValue> parameters) {
|
||||
super(ts);
|
||||
for (MethodParamValue parameter : parameters) {
|
||||
if (parameter.getParameter() instanceof NumberOfFuzzyTerms) {
|
||||
numberOfFuzzyTerms.setValue(parameter.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MethodParameter> getAvailableParameters() {
|
||||
return Collections.singletonList(NumberOfFuzzyTerms.getInstance());
|
||||
}
|
||||
|
||||
public MethodParamValue getNumberOfFuzzyTerms() {
|
||||
return numberOfFuzzyTerms;
|
||||
}
|
||||
|
||||
public List<Triangle> getFuzzyTimeSeries() {
|
||||
return fuzzyTimeSeries;
|
||||
}
|
||||
|
||||
public void setFuzzySets(List<Triangle> fuzzySets) {
|
||||
this.fuzzySets = fuzzySets;
|
||||
}
|
||||
|
||||
public List<Triangle> getFuzzySets() {
|
||||
return fuzzySets;
|
||||
}
|
||||
|
||||
public double getTopValueByLabel(String label) {
|
||||
return fuzzySets
|
||||
.stream()
|
||||
.filter(fs -> fs.getLabel().equals(label))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new RuntimeException("Неизвестная нечеткая метка"))
|
||||
.getTop();
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy;
|
||||
|
||||
public class Triangle {
|
||||
private final static String FUZZY_LABEL_TEMPLATE = "X%s";
|
||||
private String label;
|
||||
private double start; // левая граница треугольника
|
||||
private double end; // правая граница треугольника
|
||||
private double top; // вершина треугольника
|
||||
|
||||
public double getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public Triangle(double start, double top, double end, int number) {
|
||||
this.start = start;
|
||||
this.top = top;
|
||||
this.end = end;
|
||||
this.label = String.format(FUZZY_LABEL_TEMPLATE, number);
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
|
||||
public double getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(int end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public double getTop() {
|
||||
return top;
|
||||
}
|
||||
|
||||
public void setTop(int top) {
|
||||
this.top = top;
|
||||
}
|
||||
|
||||
public double getValueAtPoint(double crispValue) {
|
||||
if (crispValue == this.getTop()) {
|
||||
return 1;
|
||||
} else if ((crispValue >= this.getEnd()) || (crispValue <= this.getStart())) {
|
||||
return 0;
|
||||
} else if (crispValue < this.getTop()) {
|
||||
return (crispValue - this.getStart()) / (this.getTop() - this.getStart());
|
||||
} else if (crispValue > this.getTop()) {
|
||||
return -(crispValue - this.getEnd()) / (this.getEnd() - this.getTop());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package ru.ulstu.method.fuzzy.parameter;
|
||||
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.method.MethodParameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NumberOfFuzzyTerms extends MethodParameter {
|
||||
private final static int MIN_NUMBER_OF_FUZZY_TERMS = 2;
|
||||
private final static int MIN_INCREASING_STEP_OF_NUMBER_OF_FUZZY_TERMS = 1;
|
||||
private final static int MAX_NUMBER_OF_FUZZY_TERMS = 7;
|
||||
|
||||
public NumberOfFuzzyTerms() {
|
||||
super("Number of fuzzy terms");
|
||||
}
|
||||
|
||||
public static NumberOfFuzzyTerms getInstance() {
|
||||
return new NumberOfFuzzyTerms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Number> getAvailableValues(TimeSeries timeSeries) {
|
||||
List<Number> values = new ArrayList<>();
|
||||
for (double i = MIN_NUMBER_OF_FUZZY_TERMS;
|
||||
i <= MAX_NUMBER_OF_FUZZY_TERMS;
|
||||
i += MIN_INCREASING_STEP_OF_NUMBER_OF_FUZZY_TERMS) {
|
||||
values.add(i);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
32
src/main/java/ru/ulstu/score/AnomalyCompressionScore.java
Normal file
32
src/main/java/ru/ulstu/score/AnomalyCompressionScore.java
Normal file
@ -0,0 +1,32 @@
|
||||
package ru.ulstu.score;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.target.AnomalyDifferenceSmoothed;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
@Component
|
||||
public class AnomalyCompressionScore extends ScoreMethod {
|
||||
|
||||
private final AnomalyDifferenceSmoothed anomalyDifferenceSmoothed;
|
||||
public AnomalyCompressionScore(AnomalyDifferenceSmoothed anomalyDifferenceSmoothed) {
|
||||
super("Smape, %");
|
||||
this.anomalyDifferenceSmoothed = anomalyDifferenceSmoothed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number evaluate(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
var timeSeriesAnomalyResult = anomalyDifferenceSmoothed.calculate(model);
|
||||
var timeSeriesAnomaly = anomalyDifferenceSmoothed.calculate(tsValues);
|
||||
// туду: добавить сравнение аномальных точек
|
||||
return (double)model.getLength()/tsValues.size() + Math.abs(timeSeriesAnomaly.getLength() - timeSeriesAnomalyResult.getLength());
|
||||
}
|
||||
}
|
@ -5,9 +5,11 @@ import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public abstract class ScoreMethod {
|
||||
private final String name;
|
||||
@ -16,11 +18,11 @@ public abstract class ScoreMethod {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Score getScore(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException {
|
||||
public Score getScore(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
return new Score(this, evaluate(tsValues, model));
|
||||
}
|
||||
|
||||
public abstract Number evaluate(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException;
|
||||
public abstract Number evaluate(Map<LocalDateTime, Double> tsValues, TimeSeries model) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -9,7 +9,6 @@ import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.method.Method;
|
||||
import ru.ulstu.method.MethodParamValue;
|
||||
import ru.ulstu.method.MethodParameter;
|
||||
import ru.ulstu.method.ftransform.FTransform;
|
||||
import ru.ulstu.score.ScoreMethod;
|
||||
import ru.ulstu.score.Smape;
|
||||
|
||||
@ -29,12 +28,11 @@ import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
class MethodParamBruteForce {
|
||||
public class MethodParamBruteForce {
|
||||
private final int DEFAULT_THREAD_COUNT = 50;
|
||||
private final List<Method> methods;
|
||||
private final ScoreMethod scoreMethod = new Smape();
|
||||
private final ExecutorService executors = Executors.newCachedThreadPool();
|
||||
;
|
||||
private final ExecutorService executors = Executors.newFixedThreadPool(DEFAULT_THREAD_COUNT);
|
||||
|
||||
public MethodParamBruteForce(List<Method> methods) {
|
||||
this.methods = methods;
|
||||
@ -75,7 +73,7 @@ class MethodParamBruteForce {
|
||||
for (Future<ModelingResult> futureModelingResult : futureModelingResults) {
|
||||
modelingResults.add(futureModelingResult.get());
|
||||
}
|
||||
System.gc();
|
||||
|
||||
return getBestResultForecast(modelingResults, timeSeries, countPoints);
|
||||
}
|
||||
|
||||
@ -160,38 +158,6 @@ class MethodParamBruteForce {
|
||||
for (Future<ModelingResult> futureModelingResult : results) {
|
||||
results2.add(futureModelingResult.get());
|
||||
}
|
||||
System.gc();
|
||||
return results2.stream()
|
||||
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public ModelingResult getMaxSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||
List<Future<ModelingResult>> results = new ArrayList<>();
|
||||
List<ModelingResult> results2 = new CopyOnWriteArrayList<>();
|
||||
|
||||
Map<LocalDateTime, Double> tsValues = timeSeries.getValues().stream()
|
||||
.collect(Collectors.toMap(TimeSeriesValue::getDate, TimeSeriesValue::getValue,
|
||||
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
|
||||
Method method = new FTransform();
|
||||
List<List<MethodParamValue>> availableParameterValues = getAvailableParametersValues(timeSeries, method.getAvailableParameters());
|
||||
List<MethodParamValue> parametersValue = availableParameterValues.get(availableParameterValues.size() - 1);
|
||||
Method methodInstance = method.getClass().getDeclaredConstructor().newInstance();
|
||||
if (methodInstance.canMakeModel(timeSeries, parametersValue)) {
|
||||
results.add(executors.submit(() -> {
|
||||
Model model = methodInstance.getModel(timeSeries, parametersValue);
|
||||
return new ModelingResult(model.getTimeSeriesModel(),
|
||||
null,
|
||||
parametersValue,
|
||||
scoreMethod.getScore(tsValues, model.getTimeSeriesModel()),
|
||||
methodInstance);
|
||||
}));
|
||||
|
||||
}
|
||||
for (Future<ModelingResult> futureModelingResult : results) {
|
||||
results2.add(futureModelingResult.get());
|
||||
}
|
||||
System.gc();
|
||||
return results2.stream()
|
||||
.min(Comparator.comparing(modelingResult -> modelingResult.getScore().getDoubleValue()))
|
||||
.orElse(null);
|
||||
@ -209,7 +175,7 @@ class MethodParamBruteForce {
|
||||
return getSmoothedTimeSeries(timeSeries, methods);
|
||||
}
|
||||
|
||||
private List<List<MethodParamValue>> getAvailableParametersValues(TimeSeries timeSeries, List<MethodParameter> availableParameters) {
|
||||
public List<List<MethodParamValue>> getAvailableParametersValues(TimeSeries timeSeries, List<MethodParameter> availableParameters) {
|
||||
List<List<MethodParamValue>> result = new ArrayList<>();
|
||||
Map<MethodParameter, Integer> parameterOffset = new TreeMap<>();
|
||||
Map<MethodParameter, List<Number>> parameterValues = new TreeMap<>();
|
||||
|
87
src/main/java/ru/ulstu/service/PrometheusService.java
Normal file
87
src/main/java/ru/ulstu/service/PrometheusService.java
Normal file
@ -0,0 +1,87 @@
|
||||
package ru.ulstu.service;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.http.WebClientService;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Service
|
||||
public class PrometheusService {
|
||||
|
||||
private static final String PROMETHEUS_API_URL = "http://prometheus.athene.tech/api/v1/";
|
||||
private final WebClientService httpService;
|
||||
|
||||
public PrometheusService(WebClientService httpService) {
|
||||
this.httpService = httpService;
|
||||
}
|
||||
|
||||
public TimeSeries executionQuery(String query){ // example: pve_cpu_usage_ratio{id="lxc/111"}[5h]
|
||||
var timeSeries = new TimeSeries();
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(PROMETHEUS_API_URL + "query")
|
||||
.queryParam("query",
|
||||
"pve_cpu_usage_ratio{id='lxc/111'}[1h]");
|
||||
|
||||
var response = httpService.get(PROMETHEUS_API_URL + "query?query=" + query);
|
||||
if (response.getJSONObject(0).getString("status").equals("success")){
|
||||
|
||||
}
|
||||
return timeSeries;
|
||||
}
|
||||
|
||||
public TimeSeries executionQueryPost(String query){ // example: pve_cpu_usage_ratio{id="lxc/111"}[5h]
|
||||
var timeSeries = new TimeSeries();
|
||||
var postData = new JSONObject();
|
||||
postData.put("query", query);
|
||||
var response = httpService.post(PROMETHEUS_API_URL + "query", postData);
|
||||
// if (response.getJSONObject(0).getString("status").equals("success")){
|
||||
//
|
||||
// }
|
||||
return timeSeries;
|
||||
}
|
||||
|
||||
public TimeSeries executionQueryRange(String query){
|
||||
int numberTimeSeries = 14;
|
||||
var nowDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
var timeSeries = new TimeSeries();
|
||||
var response = httpService.get(PROMETHEUS_API_URL + "query_range?query=" + query +
|
||||
"&start=" + nowDateTime.minusHours(10).minusMinutes(100).toString()+".004Z" +
|
||||
"&end=" + nowDateTime.minusHours(10).toString()+".004Z" +
|
||||
"&step=15s");
|
||||
var array = response.getJSONObject(0).getJSONObject("data").getJSONArray("result").getJSONObject(numberTimeSeries).getJSONArray("values").toList();
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
BigDecimal seconds = (BigDecimal)(((ArrayList) array.get(i)).get(0));
|
||||
Double value = Double.parseDouble((String)(((ArrayList) array.get(i)).get(1)));
|
||||
LocalDateTime dateTime =
|
||||
LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds.longValue()), ZoneId.systemDefault());
|
||||
timeSeries.addValue(new TimeSeriesValue(dateTime, value));
|
||||
}
|
||||
return timeSeries;
|
||||
}
|
||||
|
||||
public TimeSeries executionQueryRangePost(String query){
|
||||
var timeSeries = new TimeSeries();
|
||||
var postData = new JSONObject();
|
||||
postData.put("query", query);
|
||||
postData.put("start", "2023-04-06T00:00:00.004Z");
|
||||
postData.put("end", "2023-04-07T00:00:00.004Z");
|
||||
postData.put("step", "15s");
|
||||
|
||||
var response = httpService.post(PROMETHEUS_API_URL + "query_range", postData);
|
||||
// response.getJSONObject();
|
||||
// if (response.getJSONObject(0).getString("status").equals("success")){
|
||||
// var array = response.getJSONObject(0).getJSONObject("data").getJSONArray("result");
|
||||
// int a = 5;
|
||||
// }
|
||||
return timeSeries;
|
||||
}
|
||||
|
||||
}
|
@ -40,10 +40,6 @@ public class TimeSeriesService {
|
||||
return methodParamBruteForce.getSmoothedTimeSeries(timeSeries, methodClassName);
|
||||
}
|
||||
|
||||
public ModelingResult getMaxSmoothedTimeSeries(TimeSeries timeSeries) throws ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, ModelingException {
|
||||
return methodParamBruteForce.getMaxSmoothedTimeSeries(timeSeries);
|
||||
}
|
||||
|
||||
public List<Method> getAvailableMethods() {
|
||||
return methodParamBruteForce.getAvailableMethods();
|
||||
}
|
||||
@ -58,7 +54,7 @@ public class TimeSeriesService {
|
||||
|
||||
public TimeSeries getGroupedTendencies(TimeSeries timeSeries) {
|
||||
try {
|
||||
timeSeries = getMaxSmoothedTimeSeries(timeSeries).getTimeSeries();
|
||||
timeSeries = smoothTimeSeries(timeSeries, "FTransform").getTimeSeries();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -81,7 +77,7 @@ public class TimeSeriesService {
|
||||
|
||||
private boolean tsTendencyNotChanged(double diff, double prevDiff) {
|
||||
return (diff > 0 && prevDiff > 0)
|
||||
|| (diff < 0 && prevDiff < 0)
|
||||
|| (diff == 0 && prevDiff == 0);
|
||||
|| ((diff < 0 && prevDiff < 0)
|
||||
|| ((diff == 0 && prevDiff == 0)));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package ru.ulstu.service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.TimeSeriesUtils;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
@ -14,6 +16,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class UtilService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UtilService.class);
|
||||
private static final String DELIMITER = ";";
|
||||
|
||||
public TimeSeries getRandomTimeSeries(int length) {
|
||||
|
17
src/main/java/ru/ulstu/target/AnomalyDecompose.java
Normal file
17
src/main/java/ru/ulstu/target/AnomalyDecompose.java
Normal file
@ -0,0 +1,17 @@
|
||||
package ru.ulstu.target;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
|
||||
@Service
|
||||
public class AnomalyDecompose extends Target {
|
||||
public AnomalyDecompose() {
|
||||
super("Разложение");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeSeries calculate(TimeSeries model) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
46
src/main/java/ru/ulstu/target/AnomalyDifferenceSmoothed.java
Normal file
46
src/main/java/ru/ulstu/target/AnomalyDifferenceSmoothed.java
Normal file
@ -0,0 +1,46 @@
|
||||
package ru.ulstu.target;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.datamodel.ModelingResult;
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
import ru.ulstu.service.TimeSeriesService;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Service
|
||||
public class AnomalyDifferenceSmoothed extends Target {
|
||||
|
||||
private final TimeSeriesService timeSeriesService;
|
||||
|
||||
public AnomalyDifferenceSmoothed(TimeSeriesService timeSeriesService) {
|
||||
super("Модель сравнения со сглаженным ВР");
|
||||
this.timeSeriesService = timeSeriesService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeSeries calculate(TimeSeries timeSeries) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
TimeSeries residual = new TimeSeries();
|
||||
TimeSeries anomalyPoints = new TimeSeries();
|
||||
|
||||
TimeSeries timeSeriesSmooth = timeSeriesService.smoothTimeSeries(timeSeries, "AddTrendAddSeason").getTimeSeries();
|
||||
|
||||
for (int i = 0; i < timeSeries.getLength(); i++) {
|
||||
residual.addValue(new TimeSeriesValue(timeSeries.getValue(i).getDate(),
|
||||
Math.abs(timeSeries.getNumericValue(i) - timeSeriesSmooth.getNumericValue(i))));
|
||||
}
|
||||
|
||||
double diff = timeSeries.getMax().getValue()-timeSeries.getMin().getValue();
|
||||
|
||||
for (int i = 0; i < residual.getLength(); i++) {
|
||||
if (residual.getNumericValue(i)/diff > 0.05) {
|
||||
anomalyPoints.addValue(new TimeSeriesValue(residual.getValue(i).getDate(),
|
||||
timeSeries.getNumericValue(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return anomalyPoints;
|
||||
}
|
||||
}
|
14
src/main/java/ru/ulstu/target/AnomalyPredictive.java
Normal file
14
src/main/java/ru/ulstu/target/AnomalyPredictive.java
Normal file
@ -0,0 +1,14 @@
|
||||
package ru.ulstu.target;
|
||||
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
|
||||
public class AnomalyPredictive extends Target {
|
||||
public AnomalyPredictive() {
|
||||
super("Прогнозная модель, %");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeSeries calculate(TimeSeries model) {
|
||||
return null;
|
||||
}
|
||||
}
|
32
src/main/java/ru/ulstu/target/Target.java
Normal file
32
src/main/java/ru/ulstu/target/Target.java
Normal file
@ -0,0 +1,32 @@
|
||||
package ru.ulstu.target;
|
||||
|
||||
import ru.ulstu.datamodel.exception.ModelingException;
|
||||
import ru.ulstu.datamodel.ts.TimeSeries;
|
||||
import ru.ulstu.datamodel.ts.TimeSeriesValue;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public abstract class Target {
|
||||
private final String name;
|
||||
|
||||
public Target(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public abstract TimeSeries calculate(TimeSeries model) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException;
|
||||
|
||||
public TimeSeries calculate(Map<LocalDateTime, Double> values) throws ModelingException, ExecutionException, InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
TimeSeries model = new TimeSeries();
|
||||
for (var entry : values.entrySet()) {
|
||||
model.addValue(new TimeSeriesValue(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
return calculate(model);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ spring.main.banner-mode=off
|
||||
logging.level.tech.athene=DEBUG
|
||||
server.port=8080
|
||||
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
|
||||
spring.codec.max-in-memory-size=50MB
|
||||
joinfaces.primefaces.theme=afterwork
|
||||
joinfaces.primefaces.font-awesome=true
|
||||
time-series.db-path=time-series-db
|
||||
|
@ -1,9 +1,9 @@
|
||||
messages.app-name=Time Series Smoothing
|
||||
messages.menu.home=Main
|
||||
messages.time_series_forecast=Time series forecast
|
||||
messages.date=Date
|
||||
messages.value=Value
|
||||
messages.time_series_test_forecast=Test forecast
|
||||
messages.time_series_model=Model
|
||||
messages.time_series=Time series
|
||||
messages.time_series_forecast_short=Forecast
|
||||
messages.menu.home=На главную
|
||||
messages.time_series_forecast=Прогноз временного ряда
|
||||
messages.date=Дата
|
||||
messages.value=Уровень
|
||||
messages.time_series_test_forecast=Тестовый прогноз
|
||||
messages.time_series_model=Модель
|
||||
messages.time_series=Временной ряд
|
||||
messages.time_series_forecast_short=Прогноз
|
@ -123,11 +123,7 @@
|
||||
$('#select-ts').val([[*{timeSeriesMeta.key}]]);
|
||||
$('#select-ts').selectpicker('refresh');
|
||||
</script>
|
||||
<input id="need-forecast" type="hidden" th:field="*{needForecast}">
|
||||
<button th:if="*{timeSeriesMeta != null && !#strings.isEmpty(timeSeriesMeta.key)}" type="button"
|
||||
class="btn btn-primary" onclick="$('#need-forecast').val(true); form.submit();">
|
||||
Построить прогноз
|
||||
</button>
|
||||
|
||||
<h5 th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
||||
Результаты моделирования:
|
||||
</h5>
|
||||
|
@ -120,7 +120,7 @@
|
||||
|
||||
<select id="select-ts" class="selectpicker form-group" data-live-search="true"
|
||||
th:field="*{timeSeriesMeta}"
|
||||
data-width="90%" onchange="$('#need-forecast').val(false); form.submit();">
|
||||
data-width="90%" onchange="form.submit();">
|
||||
<option value="">Временной ряд</option>
|
||||
<option th:each="ts : ${listTimeSeries}"
|
||||
th:value="${ts.key}"
|
||||
@ -135,7 +135,7 @@
|
||||
|
||||
<select id="select-method" class="selectpicker form-group" data-live-search="true"
|
||||
th:field="*{methodClassName}"
|
||||
data-width="90%" onchange="$('#need-forecast').val(false); form.submit();">
|
||||
data-width="90%" onchange="form.submit();">
|
||||
<option value="">Метод прогнозирования</option>
|
||||
<option th:each="method : ${methods}"
|
||||
th:value="${method.key}"
|
||||
@ -145,13 +145,10 @@
|
||||
<script th:inline="javascript" th:if="*{methodClassName != null && methodClassName != ''}">
|
||||
$('#select-method').val([[*{methodClassName}]]);
|
||||
$('#select-method').selectpicker('refresh');
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<input id="need-forecast" type="hidden" th:field="*{needForecast}">
|
||||
<button th:if="*{methodClassName != null && methodClassName != ''}" type="button"
|
||||
class="btn btn-primary" onclick="$('#need-forecast').val(true); form.submit();">
|
||||
Построить прогноз
|
||||
</button>
|
||||
<div th:if="${forecastDescription != null && forecastDescription.timeSeriesMethod != null}">
|
||||
<p> Метод прогнозирования: <span th:text="${forecastDescription.timeSeriesMethod}"> </span>
|
||||
<p> Оценка: <span th:text="${forecastDescription.score.value}"> </span>
|
||||
|
@ -1,7 +0,0 @@
|
||||
2003-04-29T09:32:57.120554;0.00157
|
||||
2003-10-30T09:32:57.120554;0.00119
|
||||
2004-04-30T09:32:57.120554;0.000505021970694462
|
||||
2004-10-27T09:32:57.120554;0.00122503783903256
|
||||
2005-04-05T09:32:57.120554;0.00108379668432313
|
||||
2005-09-30T09:32:57.120554;0.00186974773746743
|
||||
2005-12-31T09:32:57.120554;0.00160839737199463
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент привлечения (соотношения собственных и заемных средств)","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.389759183
|
||||
2003-04-29T09:32:57.120554;0.403001187
|
||||
2003-07-30T09:32:57.120554;0.491382493
|
||||
2003-10-30T09:32:57.120554;0.43540681
|
||||
2004-01-01T09:32:57.120554;0.584191706
|
||||
2004-04-30T09:32:57.120554;0.635624474
|
||||
2004-07-29T09:32:57.120554;0.34954503
|
||||
2004-10-27T09:32:57.120554;0.496670762
|
||||
2005-01-01T09:32:57.120554;0.865462608
|
||||
2005-04-29T09:32:57.120554;2.015631486
|
||||
2005-06-30T09:32:57.120554;0.765889497
|
||||
2005-09-30T09:32:57.120554;0.603866019
|
||||
2005-12-31T09:32:57.120554;0.663070988
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент быстрой ликвидности","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;1.866521416
|
||||
2003-04-29T09:32:57.120554;1.312521108
|
||||
2003-07-30T09:32:57.120554;1.285475189
|
||||
2003-10-30T09:32:57.120554;1.130654615
|
||||
2004-01-01T09:32:57.120554;1.369348118
|
||||
2004-04-30T09:32:57.120554;1.634045786
|
||||
2004-07-29T09:32:57.120554;1.456659692
|
||||
2004-10-27T09:32:57.120554;1.694173821
|
||||
2005-01-01T09:32:57.120554;2.70768445
|
||||
2005-04-29T09:32:57.120554;7.100717469
|
||||
2005-06-30T09:32:57.120554;3.395716655
|
||||
2005-09-30T09:32:57.120554;1.613323605
|
||||
2005-12-31T09:32:57.120554;1.611867075
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент текущей ликвидности (общий коэффициент покрытия)","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.586771111175797
|
||||
2003-04-29T09:32:57.120554;0.343606035205365
|
||||
2003-07-30T09:32:57.120554;0.359502703447326
|
||||
2003-10-30T09:32:57.120554;0.187929277660206
|
||||
2004-01-01T09:32:57.120554;0.472922641735106
|
||||
2004-04-30T09:32:57.120554;0.635048328717729
|
||||
2004-07-29T09:32:57.120554;0.412477322619393
|
||||
2004-10-27T09:32:57.120554;-0.181247674929825
|
||||
2005-01-01T09:32:57.120554;0.926970037468583
|
||||
2005-04-29T09:32:57.120554;1.19972749523911
|
||||
2005-06-30T09:32:57.120554;0.910978749042943
|
||||
2005-09-30T09:32:57.120554;0.607577389445363
|
||||
2005-12-31T09:32:57.120554;0.644891997049848
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент финансовой независимости в части запасов","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.464244025721368
|
||||
2003-04-29T09:32:57.120554;0.238104006194206
|
||||
2003-07-30T09:32:57.120554;0.22208010974147
|
||||
2003-10-30T09:32:57.120554;0.115559089408091
|
||||
2004-01-01T09:32:57.120554;0.271164241921994
|
||||
2004-04-30T09:32:57.120554;0.388022043930572
|
||||
2004-07-29T09:32:57.120554;0.313497856925371
|
||||
2004-10-27T09:32:57.120554;-0.128112382837432
|
||||
2005-01-01T09:32:57.120554;0.630680746445687
|
||||
2005-04-29T09:32:57.120554;0.859169160805333
|
||||
2005-06-30T09:32:57.120554;0.705511353980947
|
||||
2005-09-30T09:32:57.120554;0.380161551500197
|
||||
2005-12-31T09:32:57.120554;0.379603884562761
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент финансовой независимости в части оборотных средств","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.565999794
|
||||
2003-04-29T09:32:57.120554;0.285731545
|
||||
2003-07-30T09:32:57.120554;0.281643961
|
||||
2003-10-30T09:32:57.120554;0.240160533
|
||||
2004-01-01T09:32:57.120554;0.309208419
|
||||
2004-04-30T09:32:57.120554;0.431034912
|
||||
2004-07-29T09:32:57.120554;0.430499733
|
||||
2004-10-27T09:32:57.120554;0.049138358
|
||||
2005-01-01T09:32:57.120554;0.865752552
|
||||
2005-04-29T09:32:57.120554;1.178519969
|
||||
2005-06-30T09:32:57.120554;0.964092382
|
||||
2005-09-30T09:32:57.120554;0.574686633
|
||||
2005-12-31T09:32:57.120554;0.519997576
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент финансовой независимости","size":1,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Gitea-cpuload-1080","size":1080,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Gitea-mem-1080","size":1080,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Jenkins-cpuload-1080","size":1080,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Jenkins-mem-1080","size":1080,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Onlyoffice-cpuload-1080","size":1080,"hasDateTime":true}
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
{"key":"Onlyoffice-mem-1080","size":1080,"hasDateTime":true}
|
@ -1,11 +0,0 @@
|
||||
2003-03-30T09:32:57.120554;4328.993
|
||||
2003-04-29T09:32:57.120554;1803.609
|
||||
2003-07-30T09:32:57.120554;2490.247
|
||||
2003-10-30T09:32:57.120554;4083.334
|
||||
2004-03-29T09:32:57.120554;3090.535
|
||||
2004-04-29T09:32:57.120554;3726.734
|
||||
2004-10-27T09:32:57.120554;3939.825
|
||||
2005-04-30T09:32:57.120554;2550.127
|
||||
2005-06-30T09:32:57.120554;3090.535
|
||||
2005-09-30T09:32:57.120554;5174.083
|
||||
2005-12-31T09:32:57.120554;7018.805
|
|
@ -1 +0,0 @@
|
||||
{"key":"Баланс. разделы I-II","size":1,"hasDateTime":true}
|
@ -1,12 +0,0 @@
|
||||
2003-03-30T09:32:57.120554;4328.993
|
||||
2003-04-29T09:32:57.120554;1803.605
|
||||
2003-07-30T09:32:57.120554;2490.247
|
||||
2003-10-30T09:32:57.120554;4083.339
|
||||
2004-04-30T09:32:57.120554;3726.734
|
||||
2004-07-29T09:32:57.120554;4435.276
|
||||
2004-10-27T09:32:57.120554;3939.825
|
||||
2005-03-29T09:32:57.120554;3090.535
|
||||
2005-04-29T09:32:57.120554;2550.127
|
||||
2005-06-30T09:32:57.120554;3118.025
|
||||
2005-10-28T09:32:57.120554;5174.083
|
||||
2005-12-31T09:32:57.120554;7018.8
|
|
@ -1 +0,0 @@
|
||||
{"key":"Баланс. разделы III-V","size":1,"hasDateTime":true}
|
@ -1,12 +0,0 @@
|
||||
2003-04-29T09:32:57.120554;1420.22
|
||||
2003-04-30T09:32:57.120554;2182.179
|
||||
2003-10-30T09:32:57.120554;2726.25
|
||||
2004-03-30T09:32:57.120554;4287.209
|
||||
2004-04-30T09:32:57.120554;515.966
|
||||
2004-07-29T09:32:57.120554;2114.85
|
||||
2004-10-27T09:32:57.120554;4091.256
|
||||
2005-03-29T09:32:57.120554;7521.68
|
||||
2005-04-05T09:32:57.120554;515.96
|
||||
2005-06-30T09:32:57.120554;3238.057
|
||||
2005-09-30T09:32:57.120554;4873.047
|
||||
2005-12-31T09:32:57.120554;6966.77
|
|
@ -1 +0,0 @@
|
||||
{"key":"Выручка(нетто) от продажи товаров, продукций, работ, услуг(за минусом НДС, акцизов и аналог-х обяз-х платежей)","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;77933
|
||||
2003-04-29T09:32:57.120554;491613
|
||||
2003-07-30T09:32:57.120554;394316
|
||||
2003-10-30T09:32:57.120554;938137
|
||||
2004-01-01T09:32:57.120554;1458523
|
||||
2004-04-30T09:32:57.120554;1009647
|
||||
2004-07-29T09:32:57.120554;642479
|
||||
2004-10-27T09:32:57.120554;441118
|
||||
2005-01-01T09:32:57.120554;520837
|
||||
2005-04-29T09:32:57.120554;247312
|
||||
2005-06-30T09:32:57.120554;354420
|
||||
2005-09-30T09:32:57.120554;1201533
|
||||
2005-12-31T09:32:57.120554;974712
|
|
@ -1 +0,0 @@
|
||||
{"key":"Денежные средства","size":1,"hasDateTime":true}
|
@ -1,42 +0,0 @@
|
||||
2006-01-31T09:32:57.120554;4813053
|
||||
2006-02-28T09:32:57.120554;9375274
|
||||
2006-03-31T09:32:57.120554;14264264
|
||||
2006-04-30T09:32:57.120554;4934206
|
||||
2006-05-31T09:32:57.120554;17230472
|
||||
2006-06-30T09:32:57.120554;11530903
|
||||
2006-07-31T09:32:57.120554;10117797
|
||||
2006-08-31T09:32:57.120554;9083848
|
||||
2006-09-30T09:32:57.120554;10018250
|
||||
2006-10-31T09:32:57.120554;7012682
|
||||
2006-11-30T09:32:57.120554;14591705
|
||||
2006-12-31T09:32:57.120554;11647228
|
||||
2007-01-31T09:32:57.120554;9228128
|
||||
2007-02-28T09:32:57.120554;5422348
|
||||
2007-03-31T09:32:57.120554;17747624
|
||||
2007-04-30T09:32:57.120554;12456484
|
||||
2007-05-31T09:32:57.120554;11043513
|
||||
2007-06-30T09:32:57.120554;8860235
|
||||
2007-07-31T09:32:57.120554;18113900
|
||||
2007-08-31T09:32:57.120554;8387753
|
||||
2007-09-30T09:32:57.120554;8915849
|
||||
2007-10-31T09:32:57.120554;15151157
|
||||
2007-11-30T09:32:57.120554;19618219
|
||||
2007-12-31T09:32:57.120554;20088549
|
||||
2008-01-31T09:32:57.120554;13072047
|
||||
2008-02-29T09:32:57.120554;14996141
|
||||
2008-03-31T09:32:57.120554;9674807
|
||||
2008-04-30T09:32:57.120554;27603244
|
||||
2008-05-31T09:32:57.120554;12069702
|
||||
2008-06-30T09:32:57.120554;23414948
|
||||
2008-07-31T09:32:57.120554;22675623
|
||||
2008-08-31T09:32:57.120554;13309220
|
||||
2008-09-30T09:32:57.120554;20702022
|
||||
2008-10-31T09:32:57.120554;35102946
|
||||
2008-11-30T09:32:57.120554;15960368
|
||||
2008-12-31T09:32:57.120554;23592993
|
||||
2009-01-31T09:32:57.120554;6752505
|
||||
2009-02-28T09:32:57.120554;14470005
|
||||
2009-03-31T09:32:57.120554;15305325
|
||||
2009-04-30T09:32:57.120554;25371516
|
||||
2009-05-31T09:32:57.120554;9497732
|
||||
2009-06-30T09:32:57.120554;28460356
|
|
@ -1 +0,0 @@
|
||||
{"key":"Запасы (сырье, материалы)","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;652723
|
||||
2003-04-29T09:32:57.120554;1193000
|
||||
2003-07-30T09:32:57.120554;1451850
|
||||
2003-10-30T09:32:57.120554;2232675
|
||||
2004-01-01T09:32:57.120554;2391186
|
||||
2004-04-30T09:32:57.120554;2183174
|
||||
2004-07-29T09:32:57.120554;3017875
|
||||
2004-10-27T09:32:57.120554;2365520
|
||||
2005-01-01T09:32:57.120554;1702493
|
||||
2005-04-29T09:32:57.120554;1384196
|
||||
2005-06-30T09:32:57.120554;1918643
|
||||
2005-09-30T09:32:57.120554;2710221
|
||||
2005-12-31T09:32:57.120554;3622864
|
|
@ -1 +0,0 @@
|
||||
{"key":"Запасы","size":1,"hasDateTime":true}
|
@ -1,42 +0,0 @@
|
||||
2006-01-31T09:32:57.120554;481.3053
|
||||
2006-02-28T09:32:57.120554;937.5274
|
||||
2006-03-31T09:32:57.120554;1426.4264
|
||||
2006-04-30T09:32:57.120554;493.4206
|
||||
2006-05-31T09:32:57.120554;1723.0472
|
||||
2006-06-30T09:32:57.120554;1153.0903
|
||||
2006-07-31T09:32:57.120554;1011.7797
|
||||
2006-08-31T09:32:57.120554;908.3848
|
||||
2006-09-30T09:32:57.120554;1001.825
|
||||
2006-10-31T09:32:57.120554;701.2682
|
||||
2006-11-30T09:32:57.120554;1459.1705
|
||||
2006-12-31T09:32:57.120554;1164.7228
|
||||
2007-01-31T09:32:57.120554;922.8128
|
||||
2007-02-28T09:32:57.120554;542.2348
|
||||
2007-03-31T09:32:57.120554;1774.7624
|
||||
2007-04-30T09:32:57.120554;1245.6484
|
||||
2007-05-31T09:32:57.120554;1104.3513
|
||||
2007-06-30T09:32:57.120554;886.0235
|
||||
2007-07-31T09:32:57.120554;1811.39
|
||||
2007-08-31T09:32:57.120554;838.7753
|
||||
2007-09-30T09:32:57.120554;891.5849
|
||||
2007-10-31T09:32:57.120554;1515.1157
|
||||
2007-11-30T09:32:57.120554;1961.8219
|
||||
2007-12-31T09:32:57.120554;2008.8549
|
||||
2008-01-31T09:32:57.120554;1307.2047
|
||||
2008-02-29T09:32:57.120554;1499.6141
|
||||
2008-03-31T09:32:57.120554;967.4807
|
||||
2008-04-30T09:32:57.120554;2760.3244
|
||||
2008-05-31T09:32:57.120554;1206.9702
|
||||
2008-06-30T09:32:57.120554;2341.4948
|
||||
2008-07-31T09:32:57.120554;2267.5623
|
||||
2008-08-31T09:32:57.120554;1330.922
|
||||
2008-09-30T09:32:57.120554;2070.2022
|
||||
2008-10-31T09:32:57.120554;3510.2946
|
||||
2008-11-30T09:32:57.120554;1596.0368
|
||||
2008-12-31T09:32:57.120554;2359.2993
|
||||
2009-01-31T09:32:57.120554;675.2505
|
||||
2009-02-28T09:32:57.120554;1447.0005
|
||||
2009-03-31T09:32:57.120554;1530.5325
|
||||
2009-04-30T09:32:57.120554;2537.1516
|
||||
2009-05-31T09:32:57.120554;949.7732
|
||||
2009-06-30T09:32:57.120554;2846.0356
|
|
@ -1 +0,0 @@
|
||||
{"key":"Заработная плата(переч.)","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;83948
|
||||
2003-04-29T09:32:57.120554;81996
|
||||
2003-07-30T09:32:57.120554;139990
|
||||
2003-10-30T09:32:57.120554;452417
|
||||
2004-01-01T09:32:57.120554;158657
|
||||
2004-04-30T09:32:57.120554;153687
|
||||
2004-07-29T09:32:57.120554;464579
|
||||
2004-10-27T09:32:57.120554;593193
|
||||
2005-01-01T09:32:57.120554;588223
|
||||
2005-04-29T09:32:57.120554;617262
|
||||
2005-06-30T09:32:57.120554;640612
|
||||
2005-09-30T09:32:57.120554;842585
|
||||
2005-12-31T09:32:57.120554;864084
|
|
@ -1 +0,0 @@
|
||||
{"key":"Итого. Внеоборотные активы","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;466947
|
||||
2003-04-29T09:32:57.120554;491918
|
||||
2003-07-30T09:32:57.120554;661934
|
||||
2003-10-30T09:32:57.120554;872002
|
||||
2004-01-01T09:32:57.120554;1289503
|
||||
2004-04-30T09:32:57.120554;1540108
|
||||
2004-07-29T09:32:57.120554;1709384
|
||||
2004-10-27T09:32:57.120554;164448
|
||||
2005-01-01T09:32:57.120554;2166383
|
||||
2005-04-29T09:32:57.120554;2277920
|
||||
2005-06-30T09:32:57.120554;2388455
|
||||
2005-09-30T09:32:57.120554;2489254
|
||||
2005-12-31T09:32:57.120554;3200440
|
|
@ -1 +0,0 @@
|
||||
{"key":"Итого. Капиталы и резервы","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;441996
|
||||
2003-04-29T09:32:57.120554;1311681
|
||||
2003-07-30T09:32:57.120554;1828313
|
||||
2003-10-30T09:32:57.120554;3211337
|
||||
2004-01-01T09:32:57.120554;3045490
|
||||
2004-04-30T09:32:57.120554;2186626
|
||||
2004-07-29T09:32:57.120554;2725892
|
||||
2004-10-27T09:32:57.120554;1975377
|
||||
2005-01-01T09:32:57.120554;924152
|
||||
2005-04-29T09:32:57.120554;272207
|
||||
2005-06-30T09:32:57.120554;729570
|
||||
2005-09-30T09:32:57.120554;2684829
|
||||
2005-12-31T09:32:57.120554;3818380
|
|
@ -1 +0,0 @@
|
||||
{"key":"Итого. Краткосрочные обязательства","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;824995
|
||||
2003-04-29T09:32:57.120554;1721609
|
||||
2003-07-30T09:32:57.120554;2350251
|
||||
2003-10-30T09:32:57.120554;3630913
|
||||
2004-01-01T09:32:57.120554;4170336
|
||||
2004-04-30T09:32:57.120554;3573047
|
||||
2004-07-29T09:32:57.120554;3970697
|
||||
2004-10-27T09:32:57.120554;3346632
|
||||
2005-01-01T09:32:57.120554;2502312
|
||||
2005-04-29T09:32:57.120554;1932865
|
||||
2005-06-30T09:32:57.120554;2477413
|
||||
2005-09-30T09:32:57.120554;4331498
|
||||
2005-12-31T09:32:57.120554;6154721
|
|
@ -1 +0,0 @@
|
||||
{"key":"Итого. Оборотные активы","size":1,"hasDateTime":true}
|
@ -1,42 +0,0 @@
|
||||
2006-01-31T09:32:57.120554;938967
|
||||
2006-02-28T09:32:57.120554;3057545
|
||||
2006-03-31T09:32:57.120554;2890457
|
||||
2006-04-30T09:32:57.120554;437691
|
||||
2006-05-31T09:32:57.120554;216889
|
||||
2006-06-30T09:32:57.120554;255382
|
||||
2006-07-31T09:32:57.120554;13349
|
||||
2006-08-31T09:32:57.120554;316052
|
||||
2006-09-30T09:32:57.120554;262875
|
||||
2006-10-31T09:32:57.120554;170217
|
||||
2006-11-30T09:32:57.120554;309241
|
||||
2006-12-31T09:32:57.120554;1068712
|
||||
2007-01-31T09:32:57.120554;1061865
|
||||
2007-02-28T09:32:57.120554;60035
|
||||
2007-03-31T09:32:57.120554;1008273
|
||||
2007-04-30T09:32:57.120554;846035
|
||||
2007-05-31T09:32:57.120554;455941
|
||||
2007-06-30T09:32:57.120554;431517
|
||||
2007-07-31T09:32:57.120554;453748
|
||||
2007-08-31T09:32:57.120554;397135
|
||||
2007-09-30T09:32:57.120554;537218
|
||||
2007-10-31T09:32:57.120554;537218
|
||||
2007-11-30T09:32:57.120554;79505
|
||||
2007-12-31T09:32:57.120554;755704
|
||||
2008-01-31T09:32:57.120554;2383399
|
||||
2008-02-29T09:32:57.120554;798226
|
||||
2008-03-31T09:32:57.120554;1190243
|
||||
2008-04-30T09:32:57.120554;900150
|
||||
2008-05-31T09:32:57.120554;910654
|
||||
2008-06-30T09:32:57.120554;362701
|
||||
2008-07-31T09:32:57.120554;108049
|
||||
2008-08-31T09:32:57.120554;399260
|
||||
2008-09-30T09:32:57.120554;393423
|
||||
2008-10-31T09:32:57.120554;832125
|
||||
2008-11-30T09:32:57.120554;588166
|
||||
2008-12-31T09:32:57.120554;1862681
|
||||
2009-01-31T09:32:57.120554;116297
|
||||
2009-02-28T09:32:57.120554;1414551
|
||||
2009-03-31T09:32:57.120554;874996
|
||||
2009-04-30T09:32:57.120554;1199351
|
||||
2009-05-31T09:32:57.120554;1179955
|
||||
2009-06-30T09:32:57.120554;489565
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коммунальные услуги","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.176320600186427
|
||||
2003-04-29T09:32:57.120554;0.374796158517201
|
||||
2003-07-30T09:32:57.120554;0.215672043025456
|
||||
2003-10-30T09:32:57.120554;0.292132840620589
|
||||
2004-01-01T09:32:57.120554;0.478912424601624
|
||||
2004-04-30T09:32:57.120554;0.461737398165027
|
||||
2004-07-29T09:32:57.120554;0.235694957833986
|
||||
2004-10-27T09:32:57.120554;0.22330825963854
|
||||
2005-01-01T09:32:57.120554;0.682611734866126
|
||||
2005-04-29T09:32:57.120554;1.31264809501593
|
||||
2005-06-30T09:32:57.120554;0.485793001356964
|
||||
2005-09-30T09:32:57.120554;0.447526825730801
|
||||
2005-12-31T09:32:57.120554;0.255268464636836
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент абсолютной ликвидности","size":1,"hasDateTime":true}
|
@ -1,7 +0,0 @@
|
||||
2003-04-29T09:32:57.120554;0.00157
|
||||
2003-10-30T09:32:57.120554;0.00119
|
||||
2004-04-30T09:32:57.120554;0.000505021970694462
|
||||
2004-10-27T09:32:57.120554;0.00122503783903256
|
||||
2005-04-05T09:32:57.120554;0.00108379668432313
|
||||
2005-09-30T09:32:57.120554;0.00186974773746743
|
||||
2005-12-31T09:32:57.120554;0.00160839737199463
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент оборачиваемости оборотного капитала","size":1,"hasDateTime":true}
|
@ -1,12 +0,0 @@
|
||||
2003-04-29T09:32:57.120554;0.00304150149802868
|
||||
2003-04-30T09:32:57.120554;0.00443606251448412
|
||||
2003-10-30T09:32:57.120554;0.00411861303392785
|
||||
2004-03-30T09:32:57.120554;0.00491651280616329
|
||||
2004-04-30T09:32:57.120554;0.000400127801176112
|
||||
2004-07-29T09:32:57.120554;0.0013731829196394
|
||||
2004-10-27T09:32:57.120554;0.002393409555723
|
||||
2005-03-29T09:32:57.120554;0.0457389569955244
|
||||
2005-04-05T09:32:57.120554;0.000238166566115041
|
||||
2005-06-30T09:32:57.120554;0.00142149724309897
|
||||
2005-09-30T09:32:57.120554;0.00204025070600032
|
||||
2005-12-31T09:32:57.120554;0.00279873809583112
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент оборачиваемости собственного капитала","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.586771111175797
|
||||
2003-04-29T09:32:57.120554;0.343606035205365
|
||||
2003-07-30T09:32:57.120554;0.359502703447326
|
||||
2003-10-30T09:32:57.120554;0.187929277660206
|
||||
2004-01-01T09:32:57.120554;0.472922641735106
|
||||
2004-04-30T09:32:57.120554;0.635048328717729
|
||||
2004-07-29T09:32:57.120554;0.412477322619393
|
||||
2004-10-27T09:32:57.120554;-0.181247674929825
|
||||
2005-01-01T09:32:57.120554;0.926970037468583
|
||||
2005-04-29T09:32:57.120554;1.19972749523911
|
||||
2005-06-30T09:32:57.120554;0.910978749042943
|
||||
2005-09-30T09:32:57.120554;0.607577389445363
|
||||
2005-12-31T09:32:57.120554;0.644891997049848
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент финансовой независимости в части запасов","size":1,"hasDateTime":true}
|
@ -1,13 +0,0 @@
|
||||
2003-01-01T09:32:57.120554;0.464244025721368
|
||||
2003-04-29T09:32:57.120554;0.238104006194206
|
||||
2003-07-30T09:32:57.120554;0.22208010974147
|
||||
2003-10-30T09:32:57.120554;0.115559089408091
|
||||
2004-01-01T09:32:57.120554;0.271164241921994
|
||||
2004-04-30T09:32:57.120554;0.388022043930572
|
||||
2004-07-29T09:32:57.120554;0.313497856925371
|
||||
2004-10-27T09:32:57.120554;-0.128112382837432
|
||||
2005-01-01T09:32:57.120554;0.630680746445687
|
||||
2005-04-29T09:32:57.120554;0.859169160805333
|
||||
2005-06-30T09:32:57.120554;0.705511353980947
|
||||
2005-09-30T09:32:57.120554;0.380161551500197
|
||||
2005-12-31T09:32:57.120554;0.379603884562761
|
|
@ -1 +0,0 @@
|
||||
{"key":"Коэффициент финансовой независимости в части оборотных средств","size":1,"hasDateTime":true}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user