Compare commits

..

11 Commits

Author SHA1 Message Date
746da497de #5 -- Add rule only if variables are defined
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m1s
2025-02-21 11:45:38 +04:00
df451f01ce #5 -- Fix layout
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m45s
2025-02-21 11:40:49 +04:00
202d8cd0d3 #5 -- Fix validation
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m10s
2025-02-21 10:40:47 +04:00
c33680fd66 #5 -- Fix table identity strategy
Some checks failed
CI fuzzy controller / container-test-job (push) Failing after 11s
2025-02-21 10:40:03 +04:00
47059bc2de #5 -- Add rule edit link
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m4s
2025-02-20 18:53:39 +04:00
4449902185 #5 -- Validate edit
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 2m28s
2025-02-20 16:14:55 +04:00
972284fad3 #5 -- Fix save variables
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m11s
2025-02-20 13:52:14 +04:00
fb01034fc8 #5 -- Fix variables
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 57s
2025-02-19 17:44:51 +04:00
3723881909 #5 -- Add variables and terms to db
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m2s
2025-02-19 17:02:37 +04:00
11fc4e46d1 #5 -- Show and edit rules
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m47s
2025-02-19 14:33:29 +04:00
486981c0ff #5 -- Rule model as a string
All checks were successful
CI fuzzy controller / container-test-job (push) Successful in 1m3s
2025-02-18 17:54:30 +04:00
36 changed files with 628 additions and 354 deletions

View File

@ -1,3 +1,4 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
"java.configuration.updateBuildConfiguration": "interactive",
"java.compile.nullAnalysis.mode": "disabled"
}

View File

@ -4,7 +4,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

View File

@ -12,7 +12,7 @@ import java.io.Serializable;
@MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Version

View File

@ -12,6 +12,7 @@ import ru.ulstu.fc.project.model.Project;
import ru.ulstu.fc.project.model.ProjectForm;
import ru.ulstu.fc.project.service.ProjectRulesService;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.project.service.ProjectVariableService;
import ru.ulstu.fc.user.model.UserRoleConstants;
@Controller
@ -21,11 +22,14 @@ import ru.ulstu.fc.user.model.UserRoleConstants;
public class ProjectController {
private final ProjectService projectService;
private final ProjectRulesService projectRulesService;
private final ProjectVariableService projectVariableService;
public ProjectController(ProjectService projectService,
ProjectRulesService projectRulesService) {
ProjectRulesService projectRulesService,
ProjectVariableService projectVariableService) {
this.projectService = projectService;
this.projectRulesService = projectRulesService;
this.projectVariableService = projectVariableService;
}
@GetMapping("list")
@ -42,6 +46,7 @@ public class ProjectController {
: new Project()));
model.addAttribute("rules", projectRulesService.getByProjectId(id));
model.addAttribute("variables", projectVariableService.getByProjectId(id));
return "project/edit";
}

View File

@ -1,19 +1,20 @@
package ru.ulstu.fc.project.model;
import java.util.Date;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotEmpty;
import ru.ulstu.fc.core.model.BaseEntity;
import ru.ulstu.fc.user.model.User;
import java.util.Date;
@Entity
public class Project extends BaseEntity {
@NotEmpty(message = "Текст новости не может быть пустым")
private String name;
private Date createDate = new Date();
@ManyToOne
@ManyToOne(cascade = CascadeType.MERGE)
private User user;
public Project() {

View File

@ -1,12 +0,0 @@
package ru.ulstu.fc.project.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.fc.rule.model.Rule;
public interface RuleRepository extends JpaRepository<Rule, Integer> {
List<Rule> findByProjectId(Integer projectId);
}

View File

@ -1,21 +1,28 @@
package ru.ulstu.fc.project.service;
import java.util.Collections;
import java.util.List;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.project.repository.RuleRepository;
import ru.ulstu.fc.rule.model.Rule;
import ru.ulstu.fc.rule.repository.FuzzyRuleRepository;
import ru.ulstu.fc.rule.model.FuzzyRule;
@Service
public class ProjectRulesService {
private final RuleRepository ruleRepository;
private final FuzzyRuleRepository ruleRepository;
private final ProjectService projectService;
public ProjectRulesService(RuleRepository ruleRepository) {
public ProjectRulesService(FuzzyRuleRepository ruleRepository,
ProjectService projectService) {
this.ruleRepository = ruleRepository;
this.projectService = projectService;
}
public List<Rule> getByProjectId(Integer projectId) {
return ruleRepository.findByProjectId(projectId);
public List<FuzzyRule> getByProjectId(Integer projectId) {
if (projectId == null || projectId == 0) {
return Collections.emptyList();
}
return ruleRepository.findByProject(projectService.getById(projectId));
}
}

View File

@ -0,0 +1,28 @@
package ru.ulstu.fc.project.service;
import java.util.Collections;
import java.util.List;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.rule.repository.VariableRepository;
import ru.ulstu.fc.rule.model.Variable;
@Service
public class ProjectVariableService {
private final VariableRepository variableRepository;
private final ProjectService projectService;
public ProjectVariableService(VariableRepository variableRepository,
ProjectService projectService) {
this.variableRepository = variableRepository;
this.projectService = projectService;
}
public List<Variable> getByProjectId(Integer projectId) {
if (projectId == null || projectId == 0) {
return Collections.emptyList();
}
return variableRepository.findByProject(projectService.getById(projectId));
}
}

View File

@ -7,10 +7,9 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import ru.ulstu.fc.rule.model.Antecedent;
import ru.ulstu.fc.rule.model.InferenceForm;
import ru.ulstu.fc.rule.model.FuzzyTerm;
import ru.ulstu.fc.rule.model.Variable;
import ru.ulstu.fc.rule.model.VariableValue;
import ru.ulstu.fc.rule.service.FuzzyInferenceService;
import java.util.Arrays;
@ -45,21 +44,21 @@ public class InferenceMvcController {
return "index";
}
private List<VariableValue> getAgeValues() {
private List<FuzzyTerm> getAgeValues() {
Variable var = new Variable("Age");
var.getValues().addAll(Arrays.asList(
new VariableValue("молодой", 30.0),
new VariableValue("средний", 45.0),
new VariableValue("старый", 60.0)));
return var.getValues();
var.getFuzzyTerms().addAll(Arrays.asList(
new FuzzyTerm("молодой", 30.0),
new FuzzyTerm("средний", 45.0),
new FuzzyTerm("старый", 60.0)));
return var.getFuzzyTerms();
}
private List<VariableValue> getIncomeValues() {
private List<FuzzyTerm> getIncomeValues() {
Variable var = new Variable("Income");
var.getValues().addAll(Arrays.asList(
new VariableValue("небольшой", 20000.0),
new VariableValue("средний", 90000.0),
new VariableValue("высокий", 200000.0)));
return var.getValues();
var.getFuzzyTerms().addAll(Arrays.asList(
new FuzzyTerm("небольшой", 20000.0),
new FuzzyTerm("средний", 90000.0),
new FuzzyTerm("высокий", 200000.0)));
return var.getFuzzyTerms();
}
}

View File

@ -2,21 +2,22 @@ package ru.ulstu.fc.rule.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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.rule.model.Rule;
import ru.ulstu.fc.rule.model.RuleForm;
import ru.ulstu.fc.rule.service.RuleService;
import jakarta.validation.Valid;
import ru.ulstu.fc.rule.model.FuzzyRuleForm;
import ru.ulstu.fc.rule.service.FuzzyRuleService;
@Controller
@RequestMapping("rule")
public class RuleController {
private final RuleService ruleService;
private final FuzzyRuleService ruleService;
public RuleController(RuleService ruleService) {
public RuleController(FuzzyRuleService ruleService) {
this.ruleService = ruleService;
}
@ -24,25 +25,28 @@ public class RuleController {
public String edit(@PathVariable(value = "projectId") Integer projectId,
@PathVariable(value = "ruleId") Integer id, Model model) {
model.addAttribute("projectId", projectId);
model.addAttribute("rule",
new RuleForm((id != null && id != 0)
? ruleService.getById(id)
: new Rule()));
model.addAttribute("fuzzyRuleForm",
(id != null && id != 0)
? new FuzzyRuleForm(id, ruleService.getById(id))
: new FuzzyRuleForm(id, projectId));
return "rule/edit";
}
@PostMapping(value = "save", params = "save")
public String save(RuleForm ruleForm, Model model) {
model.addAttribute("rule", ruleService.save(ruleForm));
return "redirect:/project/edit/" + ruleForm.getProjectId();
public String save(@Valid FuzzyRuleForm fuzzyRuleForm, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("projectId", fuzzyRuleForm.getProjectId());
return "rule/edit";
}
ruleService.save(fuzzyRuleForm);
return "redirect:/project/edit/" + fuzzyRuleForm.getProjectId();
}
@PostMapping(value = "save", params = "delete")
public String delete(RuleForm ruleForm) {
if (ruleForm != null && ruleForm.getId() != null) {
ruleService.delete(ruleForm);
public String delete(FuzzyRuleForm fuzzyRuleForm) {
if (fuzzyRuleForm != null && fuzzyRuleForm.getId() != null) {
ruleService.delete(fuzzyRuleForm);
}
return "redirect:/project/edit/" + ruleForm.getProjectId();
return "redirect:/project/edit/" + fuzzyRuleForm.getProjectId();
}
}

View File

@ -0,0 +1,52 @@
package ru.ulstu.fc.rule.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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 jakarta.validation.Valid;
import ru.ulstu.fc.rule.model.VariableForm;
import ru.ulstu.fc.rule.service.VariableService;
@Controller
@RequestMapping("var")
public class VariableController {
private final VariableService variableService;
public VariableController(VariableService variableService) {
this.variableService = variableService;
}
@GetMapping("/edit/{projectId}/{varId}")
public String edit(@PathVariable(value = "projectId") Integer projectId,
@PathVariable(value = "varId") Integer id, Model model) {
model.addAttribute("projectId", projectId);
model.addAttribute("variableForm",
(id != null && id != 0)
? new VariableForm(id, variableService.getById(id))
: new VariableForm(id, projectId));
return "var/edit";
}
@PostMapping(value = "save", params = "save")
public String save(@Valid VariableForm variableForm, BindingResult result, Model model) {
if (result.hasErrors()) {
model.addAttribute("projectId", variableForm.getProjectId());
return "var/edit";
}
variableService.save(variableForm);
return "redirect:/project/edit/" + variableForm.getProjectId();
}
@PostMapping(value = "save", params = "delete")
public String delete(VariableForm variableForm) {
if (variableForm != null && variableForm.getId() != null) {
variableService.delete(variableForm);
}
return "redirect:/project/edit/" + variableForm.getProjectId();
}
}

View File

@ -1,25 +0,0 @@
package ru.ulstu.fc.rule.model;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import ru.ulstu.fc.core.model.BaseEntity;
@Entity
public class Antecedent extends BaseEntity {
@ManyToOne
private Variable variable;
private String value;
public Variable getVariable() {
return variable;
}
public void setVariable(Variable variable) {
this.variable = variable;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -1,29 +0,0 @@
package ru.ulstu.fc.rule.model;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import ru.ulstu.fc.core.model.BaseEntity;
@Entity
public class Consequent extends BaseEntity {
@ManyToOne
private Variable variable;
private String value;
public Variable getVariable() {
return variable;
}
public void setVariable(Variable variable) {
this.variable = variable;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,36 @@
package ru.ulstu.fc.rule.model;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import ru.ulstu.fc.core.model.BaseEntity;
import ru.ulstu.fc.project.model.Project;
@Entity
public class FuzzyRule extends BaseEntity {
@ManyToOne
@NotNull
private Project project;
@Size(min = 5, max = 250, message = "Длина от 5 до 250 символов")
private String content;
public FuzzyRule() {
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -0,0 +1,52 @@
package ru.ulstu.fc.rule.model;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class FuzzyRuleForm {
private Integer id;
@NotNull
private Integer projectId;
@Size(min = 5, max = 250, message = "Длина от 5 до 250 символов")
private String content;
public FuzzyRuleForm() {
}
public FuzzyRuleForm(Integer id, Integer projectId) {
this.id = id;
this.projectId = projectId;
}
public FuzzyRuleForm(Integer id, FuzzyRule fuzzyRule) {
this.id = fuzzyRule.getId();
this.projectId = fuzzyRule.getProject().getId();
this.content = fuzzyRule.getContent();
}
public Integer getProjectId() {
return projectId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -0,0 +1,34 @@
package ru.ulstu.fc.rule.model;
import jakarta.persistence.Entity;
import ru.ulstu.fc.core.model.BaseEntity;
@Entity
public class FuzzyTerm extends BaseEntity {
private String description;
private Double crispValue;
public FuzzyTerm() {
}
public FuzzyTerm(String description, Double value) {
this.description = description;
this.crispValue = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getCrispValue() {
return crispValue;
}
public void setCrispValue(Double crispValue) {
this.crispValue = crispValue;
}
}

View File

@ -1,47 +0,0 @@
package ru.ulstu.fc.rule.model;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import ru.ulstu.fc.core.model.BaseEntity;
import ru.ulstu.fc.project.model.Project;
@Entity
public class Rule extends BaseEntity {
@ManyToOne
private Project project;
@OneToMany
private List<Antecedent> antecedents; //TODO: AND / OR?
@ManyToOne
private Consequent consequent;
public Rule() {
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public List<Antecedent> getAntecedents() {
return antecedents;
}
public void setAntecedents(List<Antecedent> antecedents) {
this.antecedents = antecedents;
}
public Consequent getConsequent() {
return consequent;
}
public void setConsequent(Consequent consequent) {
this.consequent = consequent;
}
}

View File

@ -1,32 +0,0 @@
package ru.ulstu.fc.rule.model;
public class RuleForm {
private Integer id;
private Integer projectId;
public RuleForm() {
}
public RuleForm(Rule rule) {
this.projectId = (rule == null || rule.getProject() == null)
? null
: rule.getProject().getId();
}
public Integer getProjectId() {
return projectId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
}

View File

@ -3,33 +3,73 @@ package ru.ulstu.fc.rule.model;
import java.util.ArrayList;
import java.util.List;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import ru.ulstu.fc.core.model.BaseEntity;
import ru.ulstu.fc.project.model.Project;
@Entity
public class Variable extends BaseEntity {
@Size(min = 3, max = 250, message = "Длина должна быть от 3 до 250")
private String name;
@OneToMany
private List<VariableValue> values = new ArrayList<>();
@ManyToOne
@NotNull
private Project project;
private boolean input = true;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "variable_id", unique = true)
private List<FuzzyTerm> fuzzyTerms = new ArrayList<>();
public Variable() {
}
public Variable(String name, List<VariableValue> values) {
this.name = name;
this.values = values;
}
public Variable(String name) {
this.name = name;
}
public Variable(String name, List<FuzzyTerm> fuzzyTerms) {
this.name = name;
this.fuzzyTerms = fuzzyTerms;
}
public String getName() {
return name;
}
public List<VariableValue> getValues() {
return values;
public void setName(String name) {
this.name = name;
}
public List<FuzzyTerm> getFuzzyTerms() {
return fuzzyTerms;
}
public void setFuzzyTerms(List<FuzzyTerm> fuzzyTerms) {
this.fuzzyTerms = fuzzyTerms;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public boolean isInput() {
return input;
}
public void setInput(boolean input) {
this.input = input;
}
}

View File

@ -0,0 +1,61 @@
package ru.ulstu.fc.rule.model;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
public class VariableForm {
private Integer id;
@NotNull
private Integer projectId;
@Size(min = 3, max = 250, message = "Длина должна быть от 3 до 250")
private String name;
private boolean input = true;
public VariableForm() {
}
public VariableForm(Integer id, Integer projectId) {
this.id = id;
this.projectId = projectId;
}
public VariableForm(Integer id, Variable variable) {
this.id = id;
this.projectId = variable.getProject().getId();
this.name = variable.getName();
this.input = variable.isInput();
}
public Integer getProjectId() {
return projectId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isInput() {
return input;
}
public void setInput(boolean input) {
this.input = input;
}
}

View File

@ -1,34 +0,0 @@
package ru.ulstu.fc.rule.model;
import jakarta.persistence.Entity;
import ru.ulstu.fc.core.model.BaseEntity;
@Entity
public class VariableValue extends BaseEntity {
private String fuzzyTerm;
private Double value;
public VariableValue() {
}
public VariableValue(String fuzzyTerm, Double value) {
this.fuzzyTerm = fuzzyTerm;
this.value = value;
}
public String getFuzzyTerm() {
return fuzzyTerm;
}
public void setFuzzyTerm(String fuzzyTerm) {
this.fuzzyTerm = fuzzyTerm;
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
}

View File

@ -0,0 +1,13 @@
package ru.ulstu.fc.rule.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.fc.project.model.Project;
import ru.ulstu.fc.rule.model.FuzzyRule;
public interface FuzzyRuleRepository extends JpaRepository<FuzzyRule, Integer> {
List<FuzzyRule> findByProject(Project project);
}

View File

@ -0,0 +1,13 @@
package ru.ulstu.fc.rule.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.fc.project.model.Project;
import ru.ulstu.fc.rule.model.Variable;
public interface VariableRepository extends JpaRepository<Variable, Integer> {
List<Variable> findByProject(Project project);
}

View File

@ -15,8 +15,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.rule.model.OutputValue;
import ru.ulstu.fc.rule.model.FuzzyTerm;
import ru.ulstu.fc.rule.model.Variable;
import ru.ulstu.fc.rule.model.VariableValue;
import java.util.List;
import java.util.Map;
@ -45,15 +45,15 @@ public class FuzzyInferenceService {
final InputVariable input = new InputVariable();
input.setName(variable.getName());
input.setDescription("");
input.setRange(0, variable.getValues().get(variable.getValues().size() - 1).getValue());
input.setRange(0, variable.getFuzzyTerms().get(variable.getFuzzyTerms().size() - 1).getCrispValue());
input.setEnabled(true);
input.setLockValueInRange(false);
double prev = 0;
for (int i = 0; i < variable.getValues().size(); i++) {
Triangle term = new Triangle(variable.getValues().get(i).getFuzzyTerm(),
for (int i = 0; i < variable.getFuzzyTerms().size(); i++) {
Triangle term = new Triangle(variable.getFuzzyTerms().get(i).getDescription(),
prev,
variable.getValues().get(i).getValue(),
variable.getValues().get(i).getValue() + variable.getValues().get(i).getValue() - prev);
variable.getFuzzyTerms().get(i).getCrispValue(),
variable.getFuzzyTerms().get(i).getCrispValue() + variable.getFuzzyTerms().get(i).getCrispValue() - prev);
prev = term.getVertexB();
input.addTerm(term);
}
@ -64,19 +64,19 @@ public class FuzzyInferenceService {
final OutputVariable output = new OutputVariable();
output.setName(variable.getName());
output.setDescription("");
output.setRange(0, variable.getValues().get(variable.getValues().size() - 1).getValue());
output.setRange(0, variable.getFuzzyTerms().get(variable.getFuzzyTerms().size() - 1).getCrispValue());
output.setEnabled(true);
output.setAggregation(new Maximum());
output.setDefuzzifier(new WeightedAverage());
output.setDefaultValue(Double.NaN);
output.setLockValueInRange(false);
double prev = 0;
for (int i = 0; i < variable.getValues().size(); i++) {
for (int i = 0; i < variable.getFuzzyTerms().size(); i++) {
Triangle term = new Triangle(
variable.getValues().get(i).getFuzzyTerm(),
variable.getFuzzyTerms().get(i).getDescription(),
prev,
variable.getValues().get(i).getValue(),
variable.getValues().get(i).getValue() + variable.getValues().get(i).getValue() - prev);
variable.getFuzzyTerms().get(i).getCrispValue(),
variable.getFuzzyTerms().get(i).getCrispValue() + variable.getFuzzyTerms().get(i).getCrispValue() - prev);
prev = term.getVertexB();
output.addTerm(term);
}
@ -98,6 +98,7 @@ 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;
}
@ -130,20 +131,20 @@ public class FuzzyInferenceService {
public List<OutputValue> getFuzzyInference(Map<String, Double> vals) {
return getFuzzyInference(getDemoRules(), vals,
List.of(new Variable("возраст", List.of(
new VariableValue("молодой", 35.0),
new VariableValue("средний", 60.0),
new VariableValue("старый", 100.0))
new FuzzyTerm("молодой", 35.0),
new FuzzyTerm("средний", 60.0),
new FuzzyTerm("старый", 100.0))
),
new Variable("доход", List.of(
new VariableValue("небольшой", 35000.0),
new VariableValue("средний", 100000.0),
new VariableValue("высокий", 500000.0))
new FuzzyTerm("небольшой", 35000.0),
new FuzzyTerm("средний", 100000.0),
new FuzzyTerm("высокий", 500000.0))
)
),
new Variable("кредит", List.of(
new VariableValue("небольшой", 20000.0),
new VariableValue("средний", 100000.0),
new VariableValue("большой", 1000000.0)))
new FuzzyTerm("небольшой", 20000.0),
new FuzzyTerm("средний", 100000.0),
new FuzzyTerm("большой", 1000000.0)))
);
}

View File

@ -0,0 +1,42 @@
package ru.ulstu.fc.rule.service;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.rule.repository.FuzzyRuleRepository;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.rule.model.FuzzyRule;
import ru.ulstu.fc.rule.model.FuzzyRuleForm;
@Service
public class FuzzyRuleService {
private final FuzzyRuleRepository ruleRepository;
private final ProjectService projectService;
public FuzzyRuleService(FuzzyRuleRepository ruleRepository, ProjectService projectService) {
this.ruleRepository = ruleRepository;
this.projectService = projectService;
}
public FuzzyRule getById(Integer id) {
return ruleRepository
.findById(id)
.orElseThrow(() -> new RuntimeException("Rule not found by id"));
}
public Object save(FuzzyRuleForm ruleForm) {
FuzzyRule rule;
if (ruleForm.getId() == null || ruleForm.getId() == 0) {
rule = new FuzzyRule();
} else {
rule = getById(ruleForm.getId());
}
rule.setProject(projectService.getById(ruleForm.getProjectId()));
rule.setContent(ruleForm.getContent());
return ruleRepository.save(rule);
}
public void delete(FuzzyRuleForm ruleForm) {
getById(ruleForm.getId());
ruleRepository.deleteById(ruleForm.getId());
}
}

View File

@ -1,43 +0,0 @@
package ru.ulstu.fc.rule.service;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.project.repository.RuleRepository;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.rule.model.Rule;
import ru.ulstu.fc.rule.model.RuleForm;
@Service
public class RuleService {
private final RuleRepository ruleRepository;
private final ProjectService projectService;
public RuleService(RuleRepository ruleRepository, ProjectService projectService) {
this.ruleRepository = ruleRepository;
this.projectService = projectService;
}
public Rule getById(Integer id) {
return ruleRepository
.findById(id)
.orElseThrow(() -> new RuntimeException("Rule not found by id"));
}
public Object save(RuleForm ruleForm) {
if (ruleForm.getId() == null) {
Rule rule = new Rule();
rule.setProject(projectService.getById(ruleForm.getProjectId()));
// rule.set...
return ruleRepository.save(rule);
}
Rule dbRule = getById(ruleForm.getId());
dbRule.setProject(projectService.getById(ruleForm.getProjectId()));
// dbRule.set ...
return ruleRepository.save(dbRule);
}
public void delete(RuleForm ruleForm) {
getById(ruleForm.getId());
ruleRepository.deleteById(ruleForm.getId());
}
}

View File

@ -0,0 +1,43 @@
package ru.ulstu.fc.rule.service;
import org.springframework.stereotype.Service;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.rule.model.Variable;
import ru.ulstu.fc.rule.model.VariableForm;
import ru.ulstu.fc.rule.repository.VariableRepository;
@Service
public class VariableService {
private final VariableRepository variableRepository;
private final ProjectService projectService;
public VariableService(VariableRepository variableRepository, ProjectService projectService) {
this.variableRepository = variableRepository;
this.projectService = projectService;
}
public Variable getById(Integer id) {
return variableRepository
.findById(id)
.orElseThrow(() -> new RuntimeException("Variable not found by id"));
}
public Variable save(VariableForm variableForm) {
Variable variable;
if (variableForm.getId() == null || variableForm.getId() == 0) {
variable = new Variable();
} else {
variable = getById(variableForm.getId());
}
variable.setProject(projectService.getById(variableForm.getProjectId()));
variable.setName(variableForm.getName());
variable.setInput(variableForm.isInput());
return variableRepository.save(variable);
}
public void delete(VariableForm ruleForm) {
getById(ruleForm.getId());
variableRepository.deleteById(ruleForm.getId());
}
}

View File

@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;

View File

@ -1,21 +1,20 @@
package ru.ulstu.fc.user.model;
import java.util.HashSet;
import java.util.Set;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import ru.ulstu.fc.config.Constants;
import ru.ulstu.fc.core.model.BaseEntity;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "is_users")
public class User extends BaseEntity {

View File

@ -1,19 +1,18 @@
package ru.ulstu.fc.user.service;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.StringUtils;
public final class IpAddressResolver {
private static final String CLIENT_IP_HEADER = "Client-IP";
private static final String FORWARDED_FOR_HEADER = "X-Forwarded-For";
//private static final String CLIENT_IP_HEADER = "Client-IP";
//private static final String FORWARDED_FOR_HEADER = "X-Forwarded-For";
public static String getRemoteAddr(HttpServletRequest request) {
String headerClientIp = request.getHeader("");
String headerXForwardedFor = request.getHeader(HttpServletRequest.FORM_AUTH);
if (StringUtils.isEmpty(request.getRemoteAddr()) && !StringUtils.isEmpty(headerClientIp)) {
if (request.getRemoteAddr().isEmpty() && !headerClientIp.isEmpty()) {
return headerClientIp;
}
if (!StringUtils.isEmpty(headerXForwardedFor)) {
if (!headerXForwardedFor.isEmpty()) {
return headerXForwardedFor;
}
return request.getRemoteAddr();

View File

@ -1,21 +1,21 @@
package ru.ulstu.fc.user.service;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import ru.ulstu.fc.config.Constants;
import java.io.IOException;
@Component
public class UserSessionLoginHandler extends SavedRequestAwareAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
public class UserSessionLoginHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private final Logger log = LoggerFactory.getLogger(UserSessionLoginHandler.class);
private final UserSessionService userSessionService;

View File

@ -1,21 +1,21 @@
package ru.ulstu.fc.user.service;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;
import ru.ulstu.fc.config.Constants;
import java.io.IOException;
@Component
public class UserSessionLogoutHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
public class UserSessionLogoutHandler extends SimpleUrlLogoutSuccessHandler {
private final Logger log = LoggerFactory.getLogger(UserSessionLogoutHandler.class);
private final UserSessionService userSessionService;

View File

@ -29,7 +29,7 @@
data-width="90%">
<option th:each="ageValue : ${ageValues}"
th:value="${ageValue.value}"
th:utext="${ageValue.fuzzyTerm}">
th:utext="${ageValue.description}">
</option>
</select>
</div>
@ -44,7 +44,7 @@
data-width="90%">
<option th:each="incomeValue : ${incomeValues}"
th:value="${incomeValue.value}"
th:utext="${incomeValue.fuzzyTerm}">
th:utext="${incomeValue.description}">
</option>
</select>
</div>

View File

@ -1,10 +1,10 @@
<!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}">
<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"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<div class="container" layout:fragment="content">
<h3>Редактирование проекта:</h3>
@ -12,14 +12,8 @@
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="name">Название</label>
<input th:field="*{name}"
id="name"
type="text"
required
class="form-control"
placeholder="Название">
<p th:if="${#fields.hasErrors('name')}"
th:class="${#fields.hasErrors('name')}? error">
<input th:field="*{name}" id="name" type="text" required class="form-control" placeholder="Название">
<p th:if="${#fields.hasErrors('name')}" th:class="${#fields.hasErrors('name')}? error">
Не может быть пустым
</p>
</div>
@ -27,22 +21,38 @@
<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>
<button name="delete"
type="submit"
class="btn btn-outline-dark"
onclick="return confirm('Удалить запись?')">
<button name="delete" type="submit" class="btn btn-outline-dark" onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a href="/project/list" class="btn btn-outline-dark">Отмена</a>
</form>
<hr/>
<h4> Список правил</h4>
<div class="row" th:each="r, iter : ${rules}">
<div class="col col-md-12">
<span class="badge badge-light" th:text="${iter} + ' Если'"></span>
<hr />
<div class="row">
<div class="col col-md-6">
<h4> Список переменных</h4>
<div class="form-group">
<div class="row" th:each="v, iter : ${variables}">
<div class="col col-md-12">
<a th:href="@{'/var/edit/' + ${projectId}+'/'+${v.id}}">
<span class="badge badge-light" th:text="${iter.index+1} + '. ' + ${v.name}"></span>
</a>
</div>
</div>
</div>
<a th:href="@{'/var/edit/' + ${projectId}+'/0'}" class="btn btn-outline-dark">Добавить преременную</a>
</div>
<div class="col col-md-2 offset-md-3">
<div class="col col-md-6">
<h4> Список правил</h4>
<div class="form-group">
<div class="row" th:each="r, iter : ${rules}">
<div class="col col-md-12">
<a th:href="@{'/rule/edit/' + ${projectId}+'/'+${r.id}}">
<span class="badge badge-light" th:text="${iter.index+1} + '. ' + ${r.content}"></span>
</a>
</div>
</div>
<!-- <div class="col col-md-2 offset-md-3">
<span class="badge badge-primary">Переменная</span>
</div>
<div class="col col-md-2">
@ -66,8 +76,11 @@
</div>
<div class="col col-md-1">
<span class="badge badge-danger">И / ИЛИ</span>
</div>-->
</div>
<a th:href="@{'/rule/edit/' + ${projectId}+'/0'}" th:if="${not #lists.isEmpty(variables)}"
class="btn btn-outline-dark">Добавить правило</a>
</div>
</div>
<a th:href="@{'/rule/edit/' + ${projectId}+'/0'}" class="btn btn-outline-dark">Добавить правило</a>
</div>
</html>

View File

@ -8,12 +8,21 @@
</head>
<div class="container" layout:fragment="content">
<h3>Редактирование правила:</h3>
<form th:action="@{/rule/save}" th:object="${rule}" method="post">
<input type="hidden" th:field="${projectId}">
<form th:action="@{/rule/save}" th:object="${fuzzyRuleForm}" method="post">
<input type="hidden" th:field="*{projectId}">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="name">Название</label>
<label for="content">Правило</label>
<input th:field="*{content}"
id="content"
type="text"
required
class="form-control"
placeholder="Правило">
<p th:if="${#fields.hasErrors('content')}"
th:class="${#fields.hasErrors('content')}? error">
Не может быть пустым
</p>
</div>
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>

View File

@ -0,0 +1,46 @@
<!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"/>
</head>
<div class="container" layout:fragment="content">
<h3>Редактирование переменной:</h3>
<form th:action="@{/var/save}" th:object="${variableForm}" method="post">
<input type="hidden" th:field="*{projectId}">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="name">Переменная</label>
<input th:field="*{name}"
id="name"
type="text"
required
class="form-control"
placeholder="Переменная">
<p th:if="${#fields.hasErrors('name')}"
th:class="${#fields.hasErrors('name')} ? error">
Не может быть пустым
</p>
</div>
<div class="form-group">
<input th:field="*{input}"
id="input"
type="checkbox">
<label for="input">Является входной переменной</label>
</div>
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
<button name="delete"
type="submit"
class="btn btn-outline-dark"
th:if="*{id != 0}"
onclick="return confirm('Удалить запись?')">
Удалить
</button>
<a th:href="@{'/project/edit/' + ${projectId}}" class="btn btn-outline-dark">Отмена</a>
</form>
</div>
</html>