diff --git a/pom.xml b/pom.xml
index 097eeb2..8762eb7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
dev.struchkov
autoresponder
- 3.0.0
+ 3.1.0
jar
Abstract Autoresponder
diff --git a/src/main/java/dev/struchkov/autoresponder/Responder.java b/src/main/java/dev/struchkov/autoresponder/Responder.java
index 444c720..010ed29 100644
--- a/src/main/java/dev/struchkov/autoresponder/Responder.java
+++ b/src/main/java/dev/struchkov/autoresponder/Responder.java
@@ -1,6 +1,7 @@
package dev.struchkov.autoresponder;
import dev.struchkov.autoresponder.compare.UnitPriorityComparator;
+import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.autoresponder.entity.Unit;
import dev.struchkov.autoresponder.util.Message;
import org.slf4j.Logger;
@@ -42,10 +43,10 @@ public final class Responder {
* @return Юнит, который нуждается в обработке в соответствии с запросом пользователя
*/
public static > Optional nextUnit(String message, Collection nextUnits) {
- isNotNull(nextUnits, message);
+ isNotNull(nextUnits);
final Set searchUnit = new HashSet<>();
- if (nextUnits != null) {
+ if (message != null && nextUnits != null) {
for (U unit : nextUnits) {
final String unitPhrase = unit.getPhrase();
if (
@@ -60,16 +61,16 @@ public final class Responder {
searchUnit.add(unit);
}
- if (percentageMatch(unit, splitWords(message)) >= unit.getMatchThreshold()) {
+ if (percentageMatch(unit, message) >= unit.getMatchThreshold()) {
searchUnit.add(unit);
}
}
+ }
- if (searchUnit.isEmpty()) {
- for (U nextUnit : nextUnits) {
- if ((nextUnit.getPattern() == null && (nextUnit.getKeyWords() == null || nextUnit.getKeyWords().isEmpty()))) {
- searchUnit.add(nextUnit);
- }
+ if (searchUnit.isEmpty()) {
+ for (U nextUnit : nextUnits) {
+ if (isNotPattern(nextUnit) && isNotKeyWords(nextUnit) && isNotPhrase(nextUnit)) {
+ searchUnit.add(nextUnit);
}
}
}
@@ -77,24 +78,51 @@ public final class Responder {
return searchUnit.stream().max(UNIT_PRIORITY_COMPARATOR);
}
+ private static > boolean isNotPhrase(U nextUnit) {
+ return nextUnit.getPhrase() == null;
+ }
+
+ private static > boolean isNotPattern(U nextUnit) {
+ return nextUnit.getPattern() == null;
+ }
+
+ private static > boolean isNotKeyWords(U nextUnit) {
+ return nextUnit.getKeyWords() == null || nextUnit.getKeyWords().isEmpty();
+ }
+
private static boolean patternReg(Pattern pattern, String message) {
isNotNull(pattern);
return message.matches(pattern.pattern());
}
- private static > Double percentageMatch(U unit, Set words) {
- final Set keyWords = unit.getKeyWords();
- if (keyWords != null && !keyWords.isEmpty()) {
- final Set temp = new HashSet<>(keyWords);
- temp.retainAll(words);
- log.trace(Message.UNIT_KEYWORDS, keyWords, keyWords.size());
- log.trace(Message.USER_MESSAGE_KEYWORDS, words);
- log.trace(Message.INTERSECTION, temp, temp.size());
- log.trace(Message.CROSSING_PERCENTAGE, (double) temp.size() / (double) keyWords.size() * 100.0, unit.getMatchThreshold());
- return (double) temp.size() / (double) keyWords.size() * 100.0;
+ private static > double percentageMatch(U unit, String message) {
+ final Set unitKeyWords = unit.getKeyWords();
+ if (unitKeyWords != null && !unitKeyWords.isEmpty()) {
+ final Set messageWords = splitWords(message);
+ final Set intersection = getIntersection(unitKeyWords, messageWords);
+ final double intersectionWeight = getIntersectionWeight(intersection);
+ log.debug(Message.UNIT_KEYWORDS, unitKeyWords, unitKeyWords.size());
+ log.debug(Message.USER_MESSAGE_KEYWORDS, messageWords);
+ log.debug(Message.INTERSECTION, intersection, intersectionWeight);
+ log.debug(Message.CROSSING_PERCENTAGE, intersectionWeight / (double) unitKeyWords.size() * 100.0, unit.getMatchThreshold());
+ return (double) intersection.size() / (double) unitKeyWords.size() * 100.0;
} else {
return 0.0;
}
}
+ private static double getIntersectionWeight(Set intersection) {
+ return intersection.stream().mapToInt(KeyWord::getImportant).sum();
+ }
+
+ private static Set getIntersection(Set unitKeyWords, Set messageWords) {
+ final Set intersection = new HashSet<>();
+ for (KeyWord unitKeyWord : unitKeyWords) {
+ if (messageWords.contains(unitKeyWord.getWord())) {
+ intersection.add(unitKeyWord);
+ }
+ }
+ return intersection;
+ }
+
}
diff --git a/src/main/java/dev/struchkov/autoresponder/entity/KeyWord.java b/src/main/java/dev/struchkov/autoresponder/entity/KeyWord.java
new file mode 100644
index 0000000..458f1d4
--- /dev/null
+++ b/src/main/java/dev/struchkov/autoresponder/entity/KeyWord.java
@@ -0,0 +1,37 @@
+package dev.struchkov.autoresponder.entity;
+
+import dev.struchkov.autoresponder.exception.AutoresponderException;
+
+/**
+ * Ключевое слово для юнитов.
+ */
+public class KeyWord {
+
+ private final Integer important;
+ private final String word;
+
+ private KeyWord(Integer important, String word) {
+ if (important < 0 || important > 10) {
+ throw new AutoresponderException("Вес слова должен быть значением от 0 до 100");
+ }
+ this.important = important;
+ this.word = word;
+ }
+
+ public static KeyWord of(Integer weight, String word) {
+ return new KeyWord(weight, word);
+ }
+
+ public static KeyWord of(String word) {
+ return new KeyWord(1, word);
+ }
+
+ public Integer getImportant() {
+ return important;
+ }
+
+ public String getWord() {
+ return word;
+ }
+
+}
diff --git a/src/main/java/dev/struchkov/autoresponder/entity/Unit.java b/src/main/java/dev/struchkov/autoresponder/entity/Unit.java
index 44f7dd5..9c7df84 100644
--- a/src/main/java/dev/struchkov/autoresponder/entity/Unit.java
+++ b/src/main/java/dev/struchkov/autoresponder/entity/Unit.java
@@ -15,7 +15,7 @@ public abstract class Unit> {
/**
* Ключевые слова.
*/
- protected Set keyWords = new HashSet<>();
+ protected Set keyWords = new HashSet<>();
/**
* Точная фраза.
@@ -42,12 +42,14 @@ public abstract class Unit> {
*/
protected Set nextUnits = new HashSet<>();
- protected Unit(Set keyWords,
- String phrase,
- Pattern pattern,
- Integer matchThreshold,
- Integer priority,
- Set nextUnits) {
+ protected Unit(
+ Set keyWords,
+ String phrase,
+ Pattern pattern,
+ Integer matchThreshold,
+ Integer priority,
+ Set nextUnits
+ ) {
this.keyWords = keyWords;
this.phrase = phrase;
this.pattern = pattern;
@@ -56,11 +58,11 @@ public abstract class Unit> {
this.nextUnits = nextUnits;
}
- public Set getKeyWords() {
+ public Set getKeyWords() {
return keyWords;
}
- public void setKeyWords(Set keyWords) {
+ public void setKeyWords(Set keyWords) {
this.keyWords = keyWords;
}
diff --git a/src/main/java/dev/struchkov/autoresponder/exception/AutoresponderException.java b/src/main/java/dev/struchkov/autoresponder/exception/AutoresponderException.java
new file mode 100644
index 0000000..7de3d97
--- /dev/null
+++ b/src/main/java/dev/struchkov/autoresponder/exception/AutoresponderException.java
@@ -0,0 +1,9 @@
+package dev.struchkov.autoresponder.exception;
+
+public class AutoresponderException extends RuntimeException {
+
+ public AutoresponderException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/main/java/dev/struchkov/autoresponder/util/Message.java b/src/main/java/dev/struchkov/autoresponder/util/Message.java
index 35392a5..96a34e3 100644
--- a/src/main/java/dev/struchkov/autoresponder/util/Message.java
+++ b/src/main/java/dev/struchkov/autoresponder/util/Message.java
@@ -9,7 +9,7 @@ public final class Message {
static final String UTILITY_CLASS = "Клас утилита";
public static final String UNIT_KEYWORDS = "Ключевые слова юнита: {} ({})";
- public static final String USER_MESSAGE_KEYWORDS = "Ключевые слова от пользователя: {}";
+ public static final String USER_MESSAGE_KEYWORDS = "Слова, которые прислал пользователь: {}";
public static final String INTERSECTION = "Пересечение: {} ({})";
public static final String CROSSING_PERCENTAGE = "Процент: {} Необходимо: {}";
diff --git a/src/main/java/dev/struchkov/autoresponder/util/Parser.java b/src/main/java/dev/struchkov/autoresponder/util/Parser.java
index 8209595..df966db 100644
--- a/src/main/java/dev/struchkov/autoresponder/util/Parser.java
+++ b/src/main/java/dev/struchkov/autoresponder/util/Parser.java
@@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
-import static dev.struchkov.autoresponder.util.Message.UTILITY_CLASS;
+import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
/**
* Разбивает строку на множество слов, удаляя предлоги.
@@ -18,10 +18,11 @@ public class Parser {
*/
private static final Set pretexts = Set.of(
"в", "без", "до", "из", "к", "на", "по", "о", "от", "перед", "при", "с", "у", "за", "над", "об",
- "под", "про", "для");
+ "под", "про", "для"
+ );
private Parser() {
- throw new IllegalStateException(UTILITY_CLASS);
+ utilityClass();
}
/**
diff --git a/src/test/java/dev/struchkov/autoresponder/test/TestUnit.java b/src/test/java/dev/struchkov/autoresponder/test/TestUnit.java
index b190b59..9e78d6c 100644
--- a/src/test/java/dev/struchkov/autoresponder/test/TestUnit.java
+++ b/src/test/java/dev/struchkov/autoresponder/test/TestUnit.java
@@ -1,108 +1,108 @@
-package dev.struchkov.autoresponder.test;
-
-import dev.struchkov.autoresponder.entity.Unit;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-public class TestUnit extends Unit {
-
- private String message;
-
- public TestUnit(Set keyWords,
- String phrase,
- Pattern pattern,
- Integer matchThreshold,
- Integer priority,
- Set nextUnits,
- String message) {
- super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits);
- this.message = message;
- }
-
- private TestUnit(Builder builder) {
- super(builder.keyWords, builder.phrase, builder.pattern, builder.matchThreshold, builder.priority, builder.nextUnits);
- message = builder.message;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public String getMessage() {
- return message;
- }
-
- @Override
- public String toString() {
- return "TestUnit{" +
- "keyWords=" + keyWords +
- ", phrase='" + phrase + '\'' +
- ", pattern=" + pattern +
- ", matchThreshold=" + matchThreshold +
- ", priority=" + priority +
- ", message='" + message + '\'' +
- '}';
- }
-
-
- public static final class Builder {
- private Set keyWords = new HashSet<>();
- private String phrase;
- private Pattern pattern;
- private Integer matchThreshold;
- private Integer priority;
- private Set nextUnits = new HashSet<>();
- private String message;
-
- public Builder keyWords(Set val) {
- keyWords = val;
- return this;
- }
-
- public Builder keyWord(String val) {
- keyWords.add(val);
- return this;
- }
-
- public Builder phrase(String val) {
- phrase = val;
- return this;
- }
-
- public Builder pattern(Pattern val) {
- pattern = val;
- return this;
- }
-
- public Builder matchThreshold(Integer val) {
- matchThreshold = val;
- return this;
- }
-
- public Builder priority(Integer val) {
- priority = val;
- return this;
- }
-
- public Builder nextUnits(Set val) {
- nextUnits = val;
- return this;
- }
-
- public Builder nextUnit(TestUnit val) {
- nextUnits.add(val);
- return this;
- }
-
- public Builder message(String val) {
- message = val;
- return this;
- }
-
- public TestUnit build() {
- return new TestUnit(this);
- }
- }
-}
+//package dev.struchkov.autoresponder.test;
+//
+//import dev.struchkov.autoresponder.entity.Unit;
+//
+//import java.util.HashSet;
+//import java.util.Set;
+//import java.util.regex.Pattern;
+//
+//public class TestUnit extends Unit {
+//
+// private String message;
+//
+// public TestUnit(Set keyWords,
+// String phrase,
+// Pattern pattern,
+// Integer matchThreshold,
+// Integer priority,
+// Set nextUnits,
+// String message) {
+// super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits);
+// this.message = message;
+// }
+//
+// private TestUnit(Builder builder) {
+// super(builder.keyWords, builder.phrase, builder.pattern, builder.matchThreshold, builder.priority, builder.nextUnits);
+// message = builder.message;
+// }
+//
+// public static Builder builder() {
+// return new Builder();
+// }
+//
+// public String getMessage() {
+// return message;
+// }
+//
+// @Override
+// public String toString() {
+// return "TestUnit{" +
+// "keyWords=" + keyWords +
+// ", phrase='" + phrase + '\'' +
+// ", pattern=" + pattern +
+// ", matchThreshold=" + matchThreshold +
+// ", priority=" + priority +
+// ", message='" + message + '\'' +
+// '}';
+// }
+//
+//
+// public static final class Builder {
+// private Set keyWords = new HashSet<>();
+// private String phrase;
+// private Pattern pattern;
+// private Integer matchThreshold;
+// private Integer priority;
+// private Set nextUnits = new HashSet<>();
+// private String message;
+//
+// public Builder keyWords(Set val) {
+// keyWords = val;
+// return this;
+// }
+//
+// public Builder keyWord(String val) {
+// keyWords.add(val);
+// return this;
+// }
+//
+// public Builder phrase(String val) {
+// phrase = val;
+// return this;
+// }
+//
+// public Builder pattern(Pattern val) {
+// pattern = val;
+// return this;
+// }
+//
+// public Builder matchThreshold(Integer val) {
+// matchThreshold = val;
+// return this;
+// }
+//
+// public Builder priority(Integer val) {
+// priority = val;
+// return this;
+// }
+//
+// public Builder nextUnits(Set val) {
+// nextUnits = val;
+// return this;
+// }
+//
+// public Builder nextUnit(TestUnit val) {
+// nextUnits.add(val);
+// return this;
+// }
+//
+// public Builder message(String val) {
+// message = val;
+// return this;
+// }
+//
+// public TestUnit build() {
+// return new TestUnit(this);
+// }
+// }
+//}