Compare commits

...

6 Commits

Author SHA1 Message Date
93fc95d70e Merge pull request '23-fix-UI' (#24) from 23-fix-UI into master
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m2s
Reviewed-on: #24
2025-03-04 14:19:09 +04:00
83c9893efd #23 -- Show inference result
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m11s
2025-03-04 14:17:36 +04:00
a3e59c6461 #23 -- Add run project controller methods
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m48s
2025-03-04 13:50:37 +04:00
16aeb1e7e5 #23 -- Add run project models
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 9m6s
2025-03-04 12:45:06 +04:00
6c14b5942a #23 -- Fix buttons
Some checks failed
CI fuzzy controller / container-test-job (push) Failing after 1m39s
2025-03-04 11:38:03 +04:00
2a978bab5f #23 -- Fix inference
Some checks failed
CI fuzzy controller / container-test-job (push) Failing after 8s
2025-03-04 11:18:42 +04:00
12 changed files with 142 additions and 19 deletions

View File

@ -31,7 +31,7 @@ public class SecurityConfiguration {
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth ->
auth.requestMatchers("/").permitAll()
auth.requestMatchers("/", "get-inference").permitAll()
.requestMatchers(permittedUrls).permitAll()
.requestMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN)
.anyRequest().authenticated())

View File

@ -6,10 +6,12 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import ru.ulstu.fc.project.service.ProjectRulesService;
import ru.ulstu.fc.project.model.RunProjectForm;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.project.service.ProjectVariableService;
import ru.ulstu.fc.rule.service.FuzzyInferenceService;
import ru.ulstu.fc.user.model.UserRoleConstants;
@Controller
@ -18,20 +20,32 @@ import ru.ulstu.fc.user.model.UserRoleConstants;
@Secured({UserRoleConstants.ADMIN})
public class ProjectRunController {
private final ProjectService projectService;
private final ProjectRulesService projectRulesService;
private final FuzzyInferenceService fuzzyInferenceService;
private final ProjectVariableService projectVariableService;
public ProjectRunController(ProjectService projectService,
ProjectRulesService projectRulesService,
FuzzyInferenceService fuzzyInferenceService,
ProjectVariableService projectVariableService) {
this.projectService = projectService;
this.projectRulesService = projectRulesService;
this.fuzzyInferenceService = fuzzyInferenceService;
this.projectVariableService = projectVariableService;
}
@GetMapping("init/{projectId}")
public String getProjects(@PathVariable(value = "projectId") Integer projectId, Model model) {
model.addAttribute("project", projectService.getById(projectId));
model.addAttribute("runProjectForm", new RunProjectForm(projectId));
model.addAttribute("variables", projectVariableService.getInputByProjectId(projectId));
return "project/init";
}
@PostMapping("run")
public String run(RunProjectForm runProjectForm, Model model) {
model.addAttribute("projectId", runProjectForm.getProjectId());
model.addAttribute("response",
fuzzyInferenceService.getProjectFuzzyInference(
runProjectForm.getProjectId(),
runProjectForm.getVariableValues()));
return "project/result";
}
}

View File

@ -0,0 +1,32 @@
package ru.ulstu.fc.project.model;
import java.util.HashMap;
import java.util.Map;
public class RunProjectForm {
private Integer projectId;
private Map<String, Double> variableValues = new HashMap<>();
public RunProjectForm() {
}
public RunProjectForm(Integer projectId) {
this.projectId = projectId;
}
public Integer getProjectId() {
return projectId;
}
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
public Map<String, Double> getVariableValues() {
return variableValues;
}
public void setVariableValues(Map<String, Double> variableValues) {
this.variableValues = variableValues;
}
}

View File

@ -24,6 +24,7 @@ import ru.ulstu.fc.rule.model.ProjectInferenceData;
import ru.ulstu.fc.rule.model.Variable;
import ru.ulstu.fc.rule.model.dto.VariableValueDto;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@ -52,7 +53,7 @@ public class FuzzyInferenceService {
}
private List<String> getDemoRules() {
return List.of(
return Arrays.asList(
String.format(RULE_TEMPLATE, "возраст", "молодой", "доход", "высокий", "средний"),
String.format(RULE_TEMPLATE, "возраст", "средний", "доход", "высокий", "большой"),
String.format(RULE_TEMPLATE, "возраст", "старый", "доход", "средний", "средний")
@ -64,7 +65,7 @@ public class FuzzyInferenceService {
input.setName(variable.getName());
input.setDescription("");
variable.getFuzzyTerms().sort(Comparator.comparing(FuzzyTerm::getCrispValue));
input.setRange(0, variable.getFuzzyTerms().get(variable.getFuzzyTerms().size() - 1).getCrispValue());
input.setRange(0, variable.getFuzzyTerms().getLast().getCrispValue());
input.setEnabled(true);
input.setLockValueInRange(false);
double prev = 0;
@ -83,7 +84,7 @@ public class FuzzyInferenceService {
final OutputVariable output = new OutputVariable();
output.setName(variable.getName());
output.setDescription("");
output.setRange(0, variable.getFuzzyTerms().get(variable.getFuzzyTerms().size() - 1).getCrispValue());
output.setRange(0, variable.getFuzzyTerms().getLast().getCrispValue());
output.setEnabled(true);
output.setAggregation(new Maximum());
output.setDefuzzifier(new WeightedAverage());
@ -117,7 +118,6 @@ public class FuzzyInferenceService {
mamdani.setImplication(new AlgebraicProduct());
mamdani.setActivation(new General());
rules.forEach(r -> mamdani.addRule(Rule.parse(r, engine)));
mamdani.addRule(new Rule());
return mamdani;
}
@ -141,18 +141,18 @@ public class FuzzyInferenceService {
public List<OutputValue> getFuzzyInference(Map<String, Double> vals) {
return getFuzzyInference(getDemoRules(), vals,
List.of(new Variable("возраст", List.of(
Arrays.asList(new Variable("возраст", Arrays.asList(
new FuzzyTerm("молодой", 35.0),
new FuzzyTerm("средний", 60.0),
new FuzzyTerm("старый", 100.0))
),
new Variable("доход", List.of(
new Variable("доход", Arrays.asList(
new FuzzyTerm("небольшой", 35000.0),
new FuzzyTerm("средний", 100000.0),
new FuzzyTerm("высокий", 500000.0))
)
),
List.of(new Variable("кредит", List.of(
Arrays.asList(new Variable("кредит", Arrays.asList(
new FuzzyTerm("небольшой", 20000.0),
new FuzzyTerm("средний", 100000.0),
new FuzzyTerm("большой", 1000000.0))))
@ -188,4 +188,18 @@ public class FuzzyInferenceService {
inputVariables,
outputVariables);
}
public List<OutputValue> getProjectFuzzyInference(Integer projectId, Map<String, Double> variableValues) {
List<String> fuzzyRules = projectRulesService.getByProjectId(projectId)
.stream()
.map(FuzzyRule::getContent)
.toList();
List<Variable> inputVariables = projectVariableService.getInputByProjectId(projectId);
List<Variable> outputVariables = projectVariableService.getOutputByProjectId(projectId);
return getFuzzyInference(fuzzyRules,
variableValues,
inputVariables,
outputVariables);
}
}

View File

@ -0,0 +1,2 @@
org.apache.tomcat.level=INFO
org.apache.tomcat.util.net.level=WARNING

View File

@ -48,7 +48,7 @@
onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a th:href="@{'/variable/edit/' + ${projectId}+'/' + ${variableId}}" class="btn btn-outline-dark">Отмена</a>
<a th:href="@{'/variable/edit/' + ${projectId}+'/' + ${variableId}}" class="btn btn-outline-dark">Назад</a>
</form>
</div>
</html>

View File

@ -50,12 +50,15 @@
</div>
</div>
<input type="submit" class="btn btn-outline-success m-2" value="Получить результат вывода"/>
<div class="row" th:each="out : ${response}">
<div class="row" th:each="out : ${response}" th:if="${not #lists.isEmpty(response)}">
<div class="col-md-2"> Размер кредита:</div>
<div class="col-md-4" th:text="${out.fuzzyTerm}"></div>
<div class="col-md-3"> Степень принадлежности:</div>
<div class="col-md-1" th:text="${out.degree}"></div>
</div>
<div class="row" th:if="${response != null && #lists.isEmpty(response)}">
Нет результата
</div>
</form>
</div>
</html>

View File

@ -21,14 +21,16 @@
<label th:text="'Дата создания: ' + ${#dates.format(project.createDate, 'dd.MM.yyyy HH:mm')}"></label>
</div>
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
<a th:href="@{'/runProject/init/' + ${project.id}}" th:if="${project.id != null && project.id != 0}"
class="btn btn-outline-dark">Выполнить</a>
<button name="delete" type="submit" class="btn btn-outline-dark" onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a href="/project/list" class="btn btn-outline-dark">Отмена</a>
<a href="/project/list" class="btn btn-outline-dark">Назад</a>
</form>
<hr/>
<div class="row">
<div class="row" th:if="${project.id != null && project.id != 0}">
<div class="col col-md-6">
<h4> Список переменных</h4>
<div class="form-group">

View File

@ -0,0 +1,30 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}">
<head>
<title>Ввод переменных</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script></script>
</head>
<div class="container" layout:fragment="content">
<h3>Ввод переменных:</h3>
<form th:action="@{/runProject/run}" th:object="${runProjectForm}" method="post">
<input type="hidden" id="projectId" th:field="*{projectId}">
<div class="form-group" th:each="v : ${variables}">
<label th:text="${v.name}"> </label>
<select class='selectpicker inputVar m-2' data-live-search='true' data-width='70%'
th:field="*{variableValues[__${v.name}__]}">
<option th:each="t : ${v.fuzzyTerms}"
th:value="${t.crispValue}"
th:utext="${t.description}">
</option>
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-outline-dark">Выполнить</button>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Назад</a>
</div>
</form>
</div>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}">
<head>
<title>Результат</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script></script>
</head>
<div class="container" layout:fragment="content">
<h3>Результат нечеткого логического вывода:</h3>
<div class="row" th:each="out : ${response}" th:if="${not #lists.isEmpty(response)}">
<div class="col-md-2" th:text="${out.variable}"></div>
<div class="col-md-4" th:text="${out.fuzzyTerm}"></div>
<div class="col-md-3"> Степень принадлежности:</div>
<div class="col-md-1" th:text="${out.degree}"></div>
</div>
<div class="row" th:if="${response != null && #lists.isEmpty(response)}">
Нет результата
</div>
<div class="form-group">
<a th:href="@{'/runProject/init/' + ${projectId}}"
class="btn btn-outline-dark">Назад</a>
</div>
</div>
</html>

View File

@ -46,7 +46,7 @@
onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Отмена</a>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Назад</a>
</div>
<script type="text/javascript" src="/js/fuzzyRule.js"></script>
<script type="text/javascript">

View File

@ -29,10 +29,10 @@
onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Отмена</a>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Назад</a>
<hr/>
<div class="row">
<div class="row" th:if="${variableForm.id != null && variableForm.id != 0}">
<div class="col col-md-6">
<h4> Список термов</h4>
<div class="form-group">