diff --git a/pom.xml b/pom.xml index 158fbb0..9909887 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.sadtech.autoresponder autoresponder - 1.5.0-RELEASE + 1.6.0-RELEASE jar @@ -23,14 +23,14 @@ - 1.2.17 + 1.7.26 - log4j - log4j - ${log4j} + org.slf4j + slf4j-api + ${slf4j.ver} diff --git a/src/main/java/org/sadtech/autoresponder/Autoresponder.java b/src/main/java/org/sadtech/autoresponder/Autoresponder.java index 1dc1ace..a269541 100644 --- a/src/main/java/org/sadtech/autoresponder/Autoresponder.java +++ b/src/main/java/org/sadtech/autoresponder/Autoresponder.java @@ -1,11 +1,13 @@ package org.sadtech.autoresponder; -import org.apache.log4j.Logger; import org.sadtech.autoresponder.compare.UnitPriorityComparator; -import org.sadtech.autoresponder.entity.UnitPointer; import org.sadtech.autoresponder.entity.Unit; +import org.sadtech.autoresponder.entity.UnitPointer; +import org.sadtech.autoresponder.exception.NotFoundUnitException; import org.sadtech.autoresponder.service.UnitPointerService; import org.sadtech.autoresponder.util.Parser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Optional; @@ -13,79 +15,76 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +/* + Отвечает за функционирование автоответчика + */ public class Autoresponder { - private static final Logger log = Logger.getLogger(Autoresponder.class); + private static final Logger log = LoggerFactory.getLogger(Autoresponder.class); + private static final UnitPriorityComparator UNIT_PRIORITY_COMPARATOR = new UnitPriorityComparator(); - private Set menuUnits; - private UnitPointerService unitPointerService; + private final Set startUnits; + private Unit defaultUnit; + private final UnitPointerService unitPointerService; - public Autoresponder(UnitPointerService unitPointerService) { + public Autoresponder(UnitPointerService unitPointerService, Set startUnits) { + this.startUnits = startUnits; this.unitPointerService = unitPointerService; } - public void setMenuUnits(Set menuUnits) { - this.menuUnits = menuUnits; - } - public UnitPointerService getUnitPointerService() { return unitPointerService; } - public void setUnitPointerService(UnitPointerService unitPointerService) { - this.unitPointerService = unitPointerService; + public void setDefaultUnit(Unit defaultUnit) { + this.defaultUnit = defaultUnit; } - public Unit answer(Integer idPerson, String message) { - UnitPointer unitPointer = checkAndAddPerson(idPerson); + public Unit answer(Integer personId, String message) { + UnitPointer unitPointer = checkAndAddPerson(personId); Unit unit; - if (unitPointer.getUnit() == null) { - unit = nextUnit(menuUnits, message); - } else { - if (unitPointer.getUnit().getNextUnits() == null) { - unit = nextUnit(menuUnits, message); + try { + if (unitPointer.getUnit() == null || unitPointer.getUnit().getNextUnits() == null) { + unit = nextUnit(startUnits, message); // выбирает unit из startUnits, если пользователь обращается впервые } else { unit = nextUnit(unitPointer.getUnit().getNextUnits(), message); } + unitPointerService.edit(personId, unit); + } catch (NotFoundUnitException e) { + unit = defaultUnit; } - if (unit != null) { - unitPointer.setUnit(unit); - } - return unit; - } - - private UnitPointer checkAndAddPerson(Integer idPerson) { - UnitPointer unitPointer; - if (unitPointerService.check(idPerson)) { - unitPointer = unitPointerService.getByEntityId(idPerson); - } else { - unitPointer = new UnitPointer(idPerson); - unitPointerService.add(unitPointer); - } - return unitPointer; + return Optional.ofNullable(unit).orElseThrow(NotFoundUnitException::new); } private Unit nextUnit(Set nextUnits, String message) { - if (nextUnits.size() > 0) { - UnitPriorityComparator unitPriorityComparator = new UnitPriorityComparator(); - Optional patternUnits = nextUnits.stream().filter(nextUnit -> nextUnit.getPattern() != null).filter(nextUnit -> patternReg(nextUnit, message)).max(unitPriorityComparator); + Optional unit = nextUnits.stream() + .filter(nextUnit -> nextUnit.getPattern() != null) + .filter(nextUnit -> patternReg(nextUnit, message)) + .max(UNIT_PRIORITY_COMPARATOR); - if (!patternUnits.isPresent()) { - patternUnits = nextUnits.stream() - .filter(nextUnit -> textPercentageMatch(nextUnit, Parser.parse(message)) >= nextUnit.getMatchThreshold()) - .max(unitPriorityComparator); - } - - if (!patternUnits.isPresent()) { - patternUnits = nextUnits.stream() - .filter(nextUnit -> (nextUnit.getPattern() == null && nextUnit.getKeyWords() == null)) - .max(unitPriorityComparator); - } - - return patternUnits.orElse(null); - } else { - return null; + if (!unit.isPresent()) { + unit = nextUnits.stream() + .filter(nextUnit -> textPercentageMatch(nextUnit, Parser.parse(message)) >= nextUnit.getMatchThreshold()) + .max(UNIT_PRIORITY_COMPARATOR); } + + if (!unit.isPresent()) { + unit = nextUnits.stream() + .filter(nextUnit -> (nextUnit.getPattern() == null && nextUnit.getKeyWords() == null)) + .max(UNIT_PRIORITY_COMPARATOR); + } + return unit.orElseThrow(NotFoundUnitException::new); + } + + private UnitPointer checkAndAddPerson(Integer personId) { + UnitPointer unitPointer; + if (unitPointerService.check(personId)) { + unitPointer = unitPointerService.getByEntityId(personId); + } else { + unitPointer = new UnitPointer(personId); + unitPointerService.add(unitPointer); + } + return unitPointer; } private boolean patternReg(Unit unit, String message) { @@ -98,7 +97,6 @@ public class Autoresponder { if (unit.getKeyWords() != null) { Set temp = new HashSet<>(unit.getKeyWords()); temp.retainAll(words); - log.info("Юнит: " + unit.getClass().getSimpleName()); log.info("Ключевые слова юнита: " + unit.getKeyWords() + " (" + unit.getKeyWords().size() + ")"); log.info("Ключевые слова от пользователя: " + words); log.info("Пересечение: " + temp + " (" + temp.size() + ")"); diff --git a/src/main/java/org/sadtech/autoresponder/entity/Unit.java b/src/main/java/org/sadtech/autoresponder/entity/Unit.java index 66e01b0..3880082 100644 --- a/src/main/java/org/sadtech/autoresponder/entity/Unit.java +++ b/src/main/java/org/sadtech/autoresponder/entity/Unit.java @@ -1,51 +1,56 @@ package org.sadtech.autoresponder.entity; +import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; +/* + Абстрактный класс, предпологающий какие-то действия + */ public abstract class Unit { private Set keyWords; private Pattern pattern; - private Integer matchThreshold; - private Integer priority; + private Integer matchThreshold = 10; + private Integer priority = 10; private Set nextUnits; - public Unit() { - priority = 10; - matchThreshold = 10; - } - - public Unit(Set keyWords, Pattern pattern, Integer matchThreshold, Integer priority, Set nextUnits) { - this.keyWords = keyWords; - this.pattern = pattern; - this.matchThreshold = matchThreshold; - this.priority = priority; - this.nextUnits = nextUnits; - } - - public void setKeyWord(String keyWord) { - if (keyWords == null) { - keyWords = new HashSet<>(); + public void setKeyWord(String... keyWord) { + if (this.keyWords == null) { + this.keyWords = new HashSet<>(); } - keyWords.add(keyWord); + this.keyWords.addAll(Arrays.asList(keyWord)); } - public void setNextUnit(Unit unit) { - if (nextUnits == null) { - nextUnits = new HashSet<>(); + public void setKeyWords(Set keyWords) { + if (this.keyWords == null) { + this.keyWords = new HashSet<>(); } - nextUnits.add(unit); + this.keyWords.addAll(keyWords); } public Set getKeyWords() { return keyWords; } - public void setKeyWords(Set keyWords) { - this.keyWords = keyWords; + public void setNextUnit(Unit... unit) { + if (nextUnits == null) { + nextUnits = new HashSet<>(); + } + nextUnits.addAll(Arrays.asList(unit)); + } + + public void setNextUnits(Set nextUnits) { + if (nextUnits == null) { + nextUnits = new HashSet<>(); + } + this.nextUnits.addAll(nextUnits); + } + + public Set getNextUnits() { + return nextUnits; } public Integer getMatchThreshold() { @@ -64,14 +69,6 @@ public abstract class Unit { this.priority = priority; } - public Set getNextUnits() { - return nextUnits; - } - - public void setNextUnits(Set nextUnits) { - this.nextUnits = nextUnits; - } - public Pattern getPattern() { return pattern; } @@ -83,7 +80,7 @@ public abstract class Unit { @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof Unit)) return false; Unit unit = (Unit) o; return Objects.equals(keyWords, unit.keyWords) && Objects.equals(pattern, unit.pattern) && diff --git a/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java b/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java index 37b40b9..271c5c4 100644 --- a/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java +++ b/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java @@ -2,6 +2,9 @@ package org.sadtech.autoresponder.entity; import java.util.Objects; +/* + Сохраняет юнит, на котором остановился пользователь. + */ public class UnitPointer { private Integer entityId; @@ -45,4 +48,12 @@ public class UnitPointer { public int hashCode() { return Objects.hash(entityId, unit); } + + @Override + public String toString() { + return "UnitPointer{" + + "entityId=" + entityId + + ", unit=" + unit + + '}'; + } } diff --git a/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java b/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java new file mode 100644 index 0000000..bb8be59 --- /dev/null +++ b/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java @@ -0,0 +1,4 @@ +package org.sadtech.autoresponder.exception; + +public class NotFoundUnitException extends RuntimeException { +} diff --git a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java index dd40da0..576bf75 100644 --- a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java +++ b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java @@ -8,6 +8,8 @@ public interface UnitPointerRepository { Integer add(UnitPointer unitPointer); + void edit(UnitPointer unitPointer); + void remove(Integer entityId); void addAll(Map unitPointerMap); diff --git a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java index 0d2c3f1..5534c55 100644 --- a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java +++ b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java @@ -15,6 +15,11 @@ public class UnitPointerRepositoryMap implements UnitPointerRepository { return unitPointer.getEntityId(); } + @Override + public void edit(UnitPointer unitPointer) { + unitPointerMap.get(unitPointer.getEntityId()).setUnit(unitPointer.getUnit()); + } + @Override public void remove(Integer entityId) { unitPointerMap.remove(entityId); diff --git a/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java b/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java index e819854..b174eea 100644 --- a/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java +++ b/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java @@ -1,5 +1,6 @@ package org.sadtech.autoresponder.service; +import org.sadtech.autoresponder.entity.Unit; import org.sadtech.autoresponder.entity.UnitPointer; public interface UnitPointerService { @@ -10,4 +11,6 @@ public interface UnitPointerService { UnitPointer getByEntityId(Integer entityId); + void edit(Integer personId, Unit unit); + } diff --git a/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java b/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java index ca6f9ad..05bea40 100644 --- a/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java +++ b/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java @@ -1,13 +1,15 @@ package org.sadtech.autoresponder.service; -import org.apache.log4j.Logger; +import org.sadtech.autoresponder.entity.Unit; import org.sadtech.autoresponder.entity.UnitPointer; import org.sadtech.autoresponder.repository.UnitPointerRepository; import org.sadtech.autoresponder.repository.UnitPointerRepositoryMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class UnitPointerServiceImpl implements UnitPointerService { - private static final Logger log = Logger.getLogger(UnitPointerServiceImpl.class); + private static final Logger log = LoggerFactory.getLogger(UnitPointerServiceImpl.class); private UnitPointerRepository unitPointerRepository; @@ -24,6 +26,13 @@ public class UnitPointerServiceImpl implements UnitPointerService { return unitPointerRepository.findByEntityId(entityId); } + @Override + public void edit(Integer personId, Unit unit) { + if (check(personId)) { + unitPointerRepository.edit(new UnitPointer(personId, unit)); + } + } + @Override public void add(UnitPointer unitPointer) { unitPointerRepository.add(unitPointer); diff --git a/src/main/java/org/sadtech/autoresponder/util/Parser.java b/src/main/java/org/sadtech/autoresponder/util/Parser.java index 91ffdc1..4466194 100644 --- a/src/main/java/org/sadtech/autoresponder/util/Parser.java +++ b/src/main/java/org/sadtech/autoresponder/util/Parser.java @@ -4,9 +4,19 @@ import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +/* + Возвращает Set слов из текста + */ public class Parser { + private static final Set pretexts = Stream + .of("в", "без", "до", "из", "к", "на", "по", "о", "от", "перед", "при", "с", "у", "за", "над", "об", + "под", "про", "для") + .collect(Collectors.toSet()); + private Parser() { throw new IllegalStateException("Utility Class"); } @@ -18,6 +28,7 @@ public class Parser { while (m.find()) { words.add(m.group().toLowerCase()); } + words.removeAll(pretexts); return words; }