From 414806aa1f55467b253d4ffc0a27a12e37ef563f Mon Sep 17 00:00:00 2001 From: jenzur Date: Sat, 20 Apr 2019 00:17:18 +0200 Subject: [PATCH] cleaning up code, added multi sentence support, build out caches, did other stuff i forgot --- .../main/java/FunctionLayer/Datahandler.java | 285 +++++-- .../java/FunctionLayer/DistanceObject.java | 37 - .../java/FunctionLayer/MYSQLDatahandler.java | 733 ------------------ .../FunctionLayer/MessageResponseHandler.java | 39 +- .../StanfordParser/SimilarityMatrix.java | 114 --- .../misc/SentimentAnalyzerTest.java | 73 -- .../SentimentSimilarityCacheObsolete.java | 66 -- .../misc/WordNetSimalarityObsolete.java | 152 ---- .../misc/WordNetSimalarityTestObsolete.java | 74 -- .../main/java/FunctionLayer/misc/notes.java | 58 -- .../PresentationLayer/DiscordHandler.java | 20 +- .../target/ArtificialAutism-1.0.jar | Bin 39904 -> 56472 bytes 12 files changed, 262 insertions(+), 1389 deletions(-) delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/DistanceObject.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SimilarityMatrix.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentAnalyzerTest.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentSimilarityCacheObsolete.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityObsolete.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityTestObsolete.java delete mode 100644 ArtificialAutism/src/main/java/FunctionLayer/misc/notes.java diff --git a/ArtificialAutism/src/main/java/FunctionLayer/Datahandler.java b/ArtificialAutism/src/main/java/FunctionLayer/Datahandler.java index bfb4376a..3f4ce460 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/Datahandler.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/Datahandler.java @@ -21,15 +21,20 @@ import edu.stanford.nlp.trees.GrammaticalStructureFactory; import edu.stanford.nlp.trees.TreebankLanguagePack; import java.io.IOException; import java.sql.SQLException; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import static java.util.Collections.reverseOrder; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import static java.util.Map.Entry.comparingByValue; import java.util.Properties; import java.util.Random; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; @@ -40,6 +45,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; +import static java.util.stream.Collectors.toList; /** * @@ -55,6 +61,7 @@ public class Datahandler { private static Annotation strAnnoSentiment; private static Annotation strAnnoJMWE; private static CoreDocument coreDoc; + private static ConcurrentMap> sentenceRelationMap; private volatile boolean refreshMatrixFromDB; private static volatile int secondaryIterator = 0; private static volatile Double preRelationCounters = 0.0; @@ -64,7 +71,8 @@ public class Datahandler { private static ConcurrentMap pipelineSentimentAnnotationCache; private static ConcurrentMap jmweAnnotationCache; private static ConcurrentMap coreDocumentAnnotationCache; - private static ConcurrentMap conversationMatchMap; + private static ConcurrentMap conversationMatchMap; + private static ConcurrentMap conversationUserMatchMap; private LinkedHashMap> lHMSMX = new LinkedHashMap(); private final Stopwatch stopwatch; private final Stopwatch stopwatch1; @@ -99,6 +107,8 @@ public class Datahandler { this.pipelineSentimentAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); this.coreDocumentAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); this.conversationMatchMap = new MapMaker().concurrencyLevel(2).makeMap(); + this.sentenceRelationMap = new MapMaker().concurrencyLevel(2).makeMap(); + this.conversationUserMatchMap = new MapMaker().concurrencyLevel(2).makeMap(); } public void shiftReduceParserInitiate() { @@ -217,18 +227,15 @@ public class Datahandler { } public void addHLstatsMessages() { - ConcurrentMap hlStatsMessages = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap hlStatsMessages = new MapMaker().concurrencyLevel(2).makeMap(); ConcurrentMap strCacheLocal = stringCache; - int hardcap = 10; //55000 - int ij = 0; - for (String str : DataMapper.getHLstatsMessages().values()) { - hlStatsMessages.put(ij, str); - ij++; - if (ij > hardcap) { - break; + Collection strs = DataMapper.getHLstatsMessages().values(); + for (String str : strs) { + if (hlStatsMessages.get(str) == null) { + hlStatsMessages.put(str, hlStatsMessages.size()); } } - hlStatsMessages.values().parallelStream().forEach(str -> { + hlStatsMessages.keySet().parallelStream().forEach(str -> { if (!str.startsWith("!")) { String orElse = strCacheLocal.values().parallelStream().filter(e -> e.equals(str)).findAny().orElse(null); if (orElse == null) { @@ -384,6 +391,13 @@ public class Datahandler { } } + /** + * sentenceRelationMap only catches prior strF or already computed results + * from same operation, so alot of times its null if msg from other channel + * + * @param strmap + * @return + */ public ConcurrentMap removeNonSensicalStrings(ConcurrentMap strmap) { ConcurrentMap strmapreturn = new MapMaker().concurrencyLevel(2).makeMap(); int relationCap = 20; @@ -393,49 +407,72 @@ public class Datahandler { ConcurrentMap localPipelineSentimentAnnotation = getMultiplePipelineSentimentAnnotation(strmap.values()); ConcurrentMap localCoreDocumentMap = getMultipleCoreDocuments(strmap.values()); for (String str : strmap.values()) { - ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap> strsmaps = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str1 : strCacheLocal.values()) { - HashMap HM1 = new HashMap(); - HM1.put(str, str1); - if (!str.equals(str1) && !strsmaps.values().contains(HM1)) { - SimilarityMatrix SMX = new SimilarityMatrix(str, str1); - Callable worker; - if (stringCache.size() < 150) { - worker = new SentimentAnalyzerTest(str, str1, SMX, - localJMWEMap.get(str), localJMWEMap.get(str1), localPipelineAnnotation.get(str), - localPipelineAnnotation.get(str1), localPipelineSentimentAnnotation.get(str), - localPipelineSentimentAnnotation.get(str1), localCoreDocumentMap.get(str), localCoreDocumentMap.get(str1)); - } else { - worker = new SentimentAnalyzerTest(str, str1, SMX, - localJMWEMap.get(str), jmweAnnotationCache.get(str1), localPipelineAnnotation.get(str), - pipelineAnnotationCache.get(str1), localPipelineSentimentAnnotation.get(str), - pipelineSentimentAnnotationCache.get(str1), localCoreDocumentMap.get(str), coreDocumentAnnotationCache.get(str1)); - } - HashMap HM = new HashMap(); - HM.put(SMX.getPrimaryString(), SMX.getSecondaryString()); - strsmaps.put(strsmaps.size() + 1, HM); - futures.put(futures.size() + 1, executor.submit(worker)); - } - } int positiveRelationCounter = 0; - for (Future future : futures.values()) { - try { - SimilarityMatrix getSMX = future.get(5, TimeUnit.SECONDS); - Double scoreRelationNewMsgToRecentMsg = getSMX.getDistance(); + int negativeRelationCounter = 0; + ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap getMap = sentenceRelationMap.get(str); + if (getMap == null) { + ConcurrentMap mapUdate = new MapMaker().concurrencyLevel(2).makeMap(); + for (String str1 : strCacheLocal.values()) { + if (!str.equals(str1)) { + SimilarityMatrix SMX = new SimilarityMatrix(str, str1); + Callable worker; + if (stringCache.size() < 150) { + worker = new SentimentAnalyzerTest(str, str1, SMX, + localJMWEMap.get(str), localJMWEMap.get(str1), localPipelineAnnotation.get(str), + localPipelineAnnotation.get(str1), localPipelineSentimentAnnotation.get(str), + localPipelineSentimentAnnotation.get(str1), localCoreDocumentMap.get(str), localCoreDocumentMap.get(str1)); + futures.put(futures.size() + 1, executor.submit(worker)); + } else { + worker = new SentimentAnalyzerTest(str, str1, SMX, + localJMWEMap.get(str), jmweAnnotationCache.get(str1), localPipelineAnnotation.get(str), + pipelineAnnotationCache.get(str1), localPipelineSentimentAnnotation.get(str), + pipelineSentimentAnnotationCache.get(str1), localCoreDocumentMap.get(str), coreDocumentAnnotationCache.get(str1)); + } + futures.put(futures.size() + 1, executor.submit(worker)); + } + } + for (Future future : futures.values()) { + try { + SimilarityMatrix getSMX = future.get(5, TimeUnit.SECONDS); + Double scoreRelationNewMsgToRecentMsg = getSMX.getDistance(); + System.out.println("strmapreturn size: " + strmapreturn.size() + "\nscoreRelationNewMsgToRecentMsg: " + + scoreRelationNewMsgToRecentMsg + "\n"); + mapUdate.put(getSMX.getSecondaryString(), getSMX.getDistance()); + if (scoreRelationNewMsgToRecentMsg >= 5000.0) { + positiveRelationCounter++; + if (positiveRelationCounter > relationCap) { + strmapreturn.put(strmapreturn.size() + 1, str); + break; + } + } else if (scoreRelationNewMsgToRecentMsg <= -5000.0) { + negativeRelationCounter++; + if (negativeRelationCounter > relationCap * 2) { + break; + } + } + } catch (InterruptedException | ExecutionException | TimeoutException ex) { + Logger.getLogger(Datahandler.class.getName()).log(Level.SEVERE, null, ex); + } + } + sentenceRelationMap.put(str, mapUdate); + } else { + for (Entry mapValues : getMap.entrySet()) { + Double scoreRelationNewMsgToRecentMsg = mapValues.getValue(); + System.out.println("strmapreturn size: " + strmapreturn.size() + "\nscoreRelationNewMsgToRecentMsg: " + + scoreRelationNewMsgToRecentMsg + "\n"); if (scoreRelationNewMsgToRecentMsg >= 5000.0) { - System.out.println("scoreRelationNewMsgToRecentMsg: " + scoreRelationNewMsgToRecentMsg + "\n"); positiveRelationCounter++; if (positiveRelationCounter > relationCap) { strmapreturn.put(strmapreturn.size() + 1, str); + break; } - if (positiveRelationCounter > relationCap) { - System.out.println("strmapreturn size: " + strmapreturn.size() + "\n"); + } else if (scoreRelationNewMsgToRecentMsg <= -5000.0) { + negativeRelationCounter++; + if (negativeRelationCounter > relationCap * 2) { break; } } - } catch (InterruptedException | ExecutionException | TimeoutException ex) { - Logger.getLogger(Datahandler.class.getName()).log(Level.SEVERE, null, ex); } } } @@ -481,24 +518,37 @@ public class Datahandler { } } + /** + * + * @param str is strF aka user message, + * @param MostRecent String most recently responded with + * @return + * @throws CustomError + */ public synchronized String getResponseMsg(String str, String MostRecent) throws CustomError { str = str.trim(); if (str.startsWith("<@")) { str = str.substring(str.indexOf("> ") + 2); } - SimilarityMatrix SMXreturn = new SimilarityMatrix("", ""); ConcurrentMap strCache = stringCache; ConcurrentMap> futureslocal = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap futurereturn = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap futureAndCacheCombineMap = new MapMaker().concurrencyLevel(2).makeMap(); String strF = str; getSingularAnnotation(strF); + if (!conversationMatchMap.keySet().contains(MostRecent) && !MostRecent.isEmpty()) { + conversationMatchMap.put(MostRecent, conversationMatchMap.size()); + } + if (!conversationUserMatchMap.keySet().contains(strF)) { + conversationUserMatchMap.put(strF, conversationUserMatchMap.size()); + } + ConcurrentMap getPrimary = sentenceRelationMap.get(strF); strCache.values().parallelStream().forEach((str1) -> { if (!strF.equals(str1)) { boolean present = false; - for (String strCons : conversationMatchMap.values()) { - if (strCons.equals(str1)) { + if (getPrimary != null) { + Double getSecondary = getPrimary.get(str1); + if (getSecondary != null) { present = true; - break; } } if (!present) { @@ -511,44 +561,128 @@ public class Datahandler { } } }); - futureslocal.values().parallelStream().forEach((future) -> { + futureslocal.values().forEach((future) -> { SimilarityMatrix SMX = new SimilarityMatrix("", ""); try { SMX = future.get(5, TimeUnit.SECONDS); - futurereturn.put(futurereturn.size() + 1, SMX); + futureAndCacheCombineMap.put(futureAndCacheCombineMap.size(), SMX); } catch (InterruptedException | ExecutionException | TimeoutException ex) { System.out.println("ex getResponsemsg: " + ex.getMessage() + "\n"); } }); - preRelationCounters = 0.0; - preRelationUserCounters = 0.0; - conversationMatchMap.put(conversationMatchMap.size() + 1, MostRecent); - Double scoreRelationNewMsgToRecentMsg = 0.0; - for (String conversationStr : conversationMatchMap.values()) { - scoreRelationNewMsgToRecentMsg += getScoreRelationNewMsgToRecentMsg(strF, conversationStr); + if (getPrimary != null) { + for (Entry cacheResults : getPrimary.entrySet()) { + SimilarityMatrix SMX = new SimilarityMatrix(strF, cacheResults.getKey()); + SMX.setDistance(cacheResults.getValue()); + futureAndCacheCombineMap.put(futureAndCacheCombineMap.size(), SMX); + } } + futureAndCacheCombineMap.values().parallelStream().forEach((SMX) -> { + if (sentenceRelationMap.get(strF) == null) { + ConcurrentMap localMap = new MapMaker().concurrencyLevel(2).makeMap(); + localMap.put(SMX.getSecondaryString(), SMX.getDistance()); + sentenceRelationMap.put(SMX.getPrimaryString(), localMap); + } else { + ConcurrentMap getPrimaryLocal = sentenceRelationMap.get(strF); + Double doubleValue = getPrimaryLocal.get(SMX.getSecondaryString()); + if (doubleValue == null) { + getPrimaryLocal.put(SMX.getSecondaryString(), SMX.getDistance()); + sentenceRelationMap.put(SMX.getPrimaryString(), getPrimaryLocal); + } + } + }); + preRelationCounters = -100.0; + preRelationUserCounters = -100.0; + Double scoreRelationNewMsgToRecentMsg = 0.0; + Double scoreRelationOldUserMsg = 0.0; + ConcurrentMap getPrimaryLocal = new MapMaker().concurrencyLevel(2).makeMap(); + for (String conversationStr : conversationMatchMap.keySet()) { + getPrimaryLocal = sentenceRelationMap.get(strF); + Double getSecondary = getPrimaryLocal.get(conversationStr); + if (getSecondary == null) { + getSecondary = getScoreRelationStrF(strF, conversationStr); + getPrimaryLocal.put(conversationStr, getSecondary); + sentenceRelationMap.put(strF, getPrimaryLocal); + } + scoreRelationNewMsgToRecentMsg += getSecondary; + System.out.println("scoreRelationNewMsgToRecentMsg: " + scoreRelationNewMsgToRecentMsg + "\n"); + } + for (String conversationUserStr : conversationUserMatchMap.keySet()) { + if (!strF.equals(conversationUserStr)) { + getPrimaryLocal = sentenceRelationMap.get(strF); + Double getSecondary = getPrimaryLocal.get(conversationUserStr); + if (getSecondary == null) { + getSecondary = getScoreRelationStrF(strF, conversationUserStr); + getPrimaryLocal.put(conversationUserStr, getSecondary); + sentenceRelationMap.put(strF, getPrimaryLocal); + } + scoreRelationOldUserMsg += getSecondary; + } + } + boolean userReponseRelated = scoreRelationOldUserMsg >= 250; boolean relatedReponse = scoreRelationNewMsgToRecentMsg >= 250; + if (!userReponseRelated) { + conversationUserMatchMap = new MapMaker().concurrencyLevel(2).makeMap(); + } if (!relatedReponse) { conversationMatchMap = new MapMaker().concurrencyLevel(2).makeMap(); } - for (SimilarityMatrix SMX : futurereturn.values()) { + ConcurrentMap> concurrentRelationsMap = new MapMaker().concurrencyLevel(2).makeMap(); + ConcurrentMap preRelationUserCountersMap = new MapMaker().concurrencyLevel(2).makeMap(); + for (SimilarityMatrix SMX : futureAndCacheCombineMap.values()) { Double scoreRelation = 500.0; Double scoreRelationLastUserMsg = SMX.getDistance(); if (relatedReponse) { - for (String conversationStr : conversationMatchMap.values()) { - scoreRelation += getScoreRelationNewMsgToRecentMsg(SMX.getSecondaryString(), conversationStr); + for (String conversationStr : conversationMatchMap.keySet()) { + Double relationNewMsg = 0.0; + ConcurrentMap getMap = sentenceRelationMap.get(conversationStr); + if (getMap != null) { + Double getdoubleValue = getMap.get(conversationStr); + if (getdoubleValue == null) { + getdoubleValue = getScoreRelationNewMsgToRecentMsg(SMX.getSecondaryString(), conversationStr); + getMap.put(conversationStr, getdoubleValue); + sentenceRelationMap.put(SMX.getSecondaryString(), getMap); + } + relationNewMsg += getdoubleValue; + } else { + relationNewMsg = getScoreRelationNewMsgToRecentMsg(SMX.getSecondaryString(), conversationStr); + ConcurrentMap localInnerMap = new MapMaker().concurrencyLevel(2).makeMap(); + localInnerMap.put(conversationStr, relationNewMsg); + sentenceRelationMap.put(SMX.getSecondaryString(), localInnerMap); + } + if (userReponseRelated) { + relationNewMsg += scoreRelationOldUserMsg / conversationUserMatchMap.size(); + } + scoreRelation += relationNewMsg; } } Double totalRelation = scoreRelation + scoreRelationLastUserMsg; - if (totalRelation > preRelationCounters + preRelationUserCounters && scoreRelationLastUserMsg > preRelationUserCounters) { - SMXreturn = SMX; + if (totalRelation > preRelationCounters + preRelationUserCounters && scoreRelationLastUserMsg + (preRelationUserCounters / 10) + > preRelationUserCounters) { + Entry localEntry = new AbstractMap.SimpleEntry(totalRelation, SMX); + concurrentRelationsMap.put(concurrentRelationsMap.size(), localEntry); + preRelationUserCountersMap.put(preRelationUserCountersMap.size(), preRelationUserCounters); preRelationCounters = scoreRelation; preRelationUserCounters = scoreRelationLastUserMsg; } } - System.out.println("Reached end: secondary: " + SMXreturn.getSecondaryString() + "\nPrimarY: " + SMXreturn.getPrimaryString() - + "\nScore: " + SMXreturn.getDistance()); - return SMXreturn.getSecondaryString(); + StringBuilder SB = new StringBuilder(); + int iterator = concurrentRelationsMap.size() - 1; + System.out.println("iterator: " + iterator + "\n"); + while (iterator > -1) { + Double preRelationUserCounterDouble = preRelationUserCountersMap.get(iterator); + Entry getRelation = concurrentRelationsMap.get(iterator); + Double result = preRelationUserCounterDouble + preRelationUserCounters; + SB.append(getRelation.getValue().getSecondaryString()).append(" "); + iterator--; + System.out.println("result: " + result + "\ngetRelation.getKey(): " + getRelation.getKey() + "\npreRelationUserCounters: " + + preRelationUserCounters + "\npreRelationUserCounterDouble: " + preRelationUserCounterDouble + "\n"); + if (getRelation.getKey() * 2 < result) { + break; + } + } + System.out.println("Reached end: SB: " + SB.toString() + "\n: "); + return SB.toString(); } public void getSingularAnnotation(String str) { @@ -621,6 +755,26 @@ public class Datahandler { return 0.0; } + private Double getScoreRelationStrF(String str, String mostRecentMsg) { + SimilarityMatrix SMX = new SimilarityMatrix(str, mostRecentMsg); + Callable worker = new SentimentAnalyzerTest(str, mostRecentMsg, SMX, + strAnnoJMWE, jmweAnnotationCache.get(mostRecentMsg), strAnno, + pipelineAnnotationCache.get(mostRecentMsg), strAnnoSentiment, + pipelineSentimentAnnotationCache.get(mostRecentMsg), coreDoc, coreDocumentAnnotationCache.get(mostRecentMsg)); + SimilarityMatrix callSMX = null; + try { + callSMX = worker.call(); + } catch (Exception ex) { + Logger.getLogger(Datahandler.class + .getName()).log(Level.SEVERE, null, ex); + } + if (callSMX != null) { + double smxDistance = callSMX.getDistance(); + return smxDistance; + } + return 0.0; + } + public String mostSimilar(String toBeCompared, ConcurrentMap concurrentStrings, String MostRecent) { similar = ""; minDistance = 6.0; @@ -825,6 +979,7 @@ public class Datahandler { if (stringCache.isEmpty()) { return str; } + Collection values = stringCache.values(); str.values().parallelStream().forEach(str1 -> { boolean tooclosematch = false; diff --git a/ArtificialAutism/src/main/java/FunctionLayer/DistanceObject.java b/ArtificialAutism/src/main/java/FunctionLayer/DistanceObject.java deleted file mode 100644 index a21282bc..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/DistanceObject.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer; - -/** - * - * @author install1 - */ -public class DistanceObject { - - private Integer distance; - private String sentence; - - public DistanceObject() { - } - - public Integer getDistance() { - return distance; - } - - public void setDistance(Integer distance) { - this.distance = distance; - } - - public String getSentence() { - return sentence; - } - - - public DistanceObject(Integer distance, String sentence) { - this.distance = distance; - this.sentence = sentence; - } -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java b/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java deleted file mode 100644 index e2f0253f..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/MYSQLDatahandler.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer; - -import DataLayer.DataMapper; -import FunctionLayer.StanfordParser.SentimentAnalyzerTest; -import com.google.common.base.Stopwatch; -import com.google.common.collect.MapMaker; -import edu.stanford.nlp.ie.AbstractSequenceClassifier; -import edu.stanford.nlp.ie.crf.CRFClassifier; -import edu.stanford.nlp.ling.CoreLabel; -import edu.stanford.nlp.ling.HasWord; -import edu.stanford.nlp.ling.TaggedWord; -import edu.stanford.nlp.ling.Word; -import edu.stanford.nlp.parser.lexparser.LexicalizedParser; -import edu.stanford.nlp.parser.shiftreduce.ShiftReduceParser; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.StanfordCoreNLP; -import edu.stanford.nlp.process.DocumentPreprocessor; -import edu.stanford.nlp.tagger.maxent.MaxentTagger; -import edu.stanford.nlp.trees.GrammaticalStructureFactory; -import edu.stanford.nlp.trees.Tree; -import edu.stanford.nlp.trees.TreebankLanguagePack; -import java.io.IOException; -import java.io.StringReader; -import java.sql.SQLException; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Random; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author install1 - */ -public class MYSQLDatahandler { - - public static final long EXPIRE_TIME_IN_SECONDS = TimeUnit.SECONDS.convert(6, TimeUnit.MINUTES); - public static final long EXPIRE_TIME_IN_SECONDS1 = TimeUnit.SECONDS.convert(10, TimeUnit.HOURS); - public static MYSQLDatahandler instance = new MYSQLDatahandler(); - private volatile boolean refreshMatrixFromDB; - private static int secondaryIterator = 0; - private final ConcurrentMap stringCache; - private static ConcurrentMap pipelineAnnotationCache; - private static ConcurrentMap pipelineSentimentAnnotationCache; - private static ConcurrentMap jmweAnnotationCache; - private LinkedHashMap> lHMSMX = new LinkedHashMap(); - private final Stopwatch stopwatch; - private final Stopwatch stopwatch1; - private ForkJoinPool executor; - private static String shiftReduceParserPath = "edu/stanford/nlp/models/srparser/englishSR.ser.gz"; - private static String sentimentModel = "edu/stanford/nlp/models/sentiment/sentiment.ser.gz"; - private static String lexParserEnglishRNN = "edu/stanford/nlp/models/lexparser/englishRNN.ser.gz"; - private static String taggerPath = "edu/stanford/nlp/models/pos-tagger/english-left3words/english-left3words-distsim.tagger"; - private static String nerModel = "edu/stanford/nlp/models/ner/english.all.3class.distsim.crf.ser.gz"; - private static String jmweIndexData = "/home/javatests/lib/mweindex_wordnet3.0_semcor1.6.data"; // ./lib/mweindex_wordnet3.0_semcor1.6.data - private static String jmweIndexDataLocalTest = "E:/java8/Projects/mweindex_wordnet3.0_semcor1.6.data"; - private static MaxentTagger tagger; - private static ShiftReduceParser model; - private static String[] options = {"-maxLength", "100"}; - private static Properties props = new Properties(); - private static Properties propsSentiment = new Properties(); - private static Properties propsJMWE = new Properties(); - private static GrammaticalStructureFactory gsf; - private static LexicalizedParser lp; - private static TreebankLanguagePack tlp; - private static AbstractSequenceClassifier classifier; - // set up Stanford CoreNLP pipeline - private static StanfordCoreNLP pipeline; - private static StanfordCoreNLP pipelineSentiment; - private static StanfordCoreNLP pipelineJMWE; - - public MYSQLDatahandler() { - this.stopwatch = Stopwatch.createUnstarted(); - this.stopwatch1 = Stopwatch.createStarted(); - this.stringCache = new MapMaker().concurrencyLevel(2).makeMap(); - //cant sadly just have one annotation for every pipelines, one pipeline per annotation is required - this.jmweAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); - this.pipelineAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); - this.pipelineSentimentAnnotationCache = new MapMaker().concurrencyLevel(2).makeMap(); - } - - public void shiftReduceParserInitiate() { - try { - classifier = CRFClassifier.getClassifierNoExceptions(nerModel); - } catch (ClassCastException ex) { - Logger.getLogger(MYSQLDatahandler.class.getName()).log(Level.SEVERE, null, ex); - } - model = ShiftReduceParser.loadModel(shiftReduceParserPath, options); - tagger = new MaxentTagger(taggerPath); - lp = LexicalizedParser.loadModel(lexParserEnglishRNN, options); - tlp = lp.getOp().langpack(); - gsf = tlp.grammaticalStructureFactory(); - // set up pipeline properties - props.setProperty("parse.model", shiftReduceParserPath); - props.setProperty("parse.maxlen", "100"); - props.setProperty("parse.binaryTrees", "true"); - props.setProperty("annotators", "tokenize,ssplit,pos,lemma,parse"); - propsSentiment.setProperty("parse.model", lexParserEnglishRNN); - propsSentiment.setProperty("ner.model", nerModel); - propsSentiment.setProperty("sentiment.model", sentimentModel); - propsSentiment.setProperty("parse.maxlen", "100"); - propsSentiment.setProperty("annotators", "tokenize,ssplit,pos,parse,depparse,sentiment"); //coref too expensive memorywise - propsJMWE.setProperty("customAnnotatorClass.jmwe", "edu.stanford.nlp.pipeline.JMWEAnnotator"); - propsJMWE.setProperty("customAnnotatorClass.jmwe.verbose", "false"); - propsJMWE.setProperty("customAnnotatorClass.jmwe.underscoreReplacement", "-"); - propsJMWE.setProperty("customAnnotatorClass.jmwe.indexData", jmweIndexData); //jmweIndexDataLocalTest jmweIndexData - propsJMWE.setProperty("customAnnotatorClass.jmwe.detector", "Exhaustive"); - //"Consecutive", "Exhaustive", "ProperNouns", "Complex" and "CompositeConsecutiveProperNouns" - propsJMWE.setProperty("annotators", "tokenize, ssplit, pos, lemma, jmwe"); - // set up pipeline - pipeline = new StanfordCoreNLP(props); - pipelineSentiment = new StanfordCoreNLP(propsSentiment); - pipelineJMWE = new StanfordCoreNLP(propsJMWE); - } - - public static AbstractSequenceClassifier getClassifier() { - return classifier; - } - - public static void setClassifier(AbstractSequenceClassifier classifier) { - MYSQLDatahandler.classifier = classifier; - } - - public void updateStringCache() { - try { - checkIfUpdateStrings(); - } catch (CustomError ex) { - Logger.getLogger(MYSQLDatahandler.class.getName()).log(Level.SEVERE, null, ex); - } - } - - public void instantiateExecutor() { - this.executor = new ForkJoinPool(Runtime.getRuntime().availableProcessors(), - ForkJoinPool.defaultForkJoinWorkerThreadFactory, - null, false); //true - } - - public static GrammaticalStructureFactory getGsf() { - return gsf; - } - - public static StanfordCoreNLP getPipeline() { - return pipeline; - } - - public static StanfordCoreNLP getPipelineSentiment() { - return pipelineSentiment; - } - - public static MaxentTagger getTagger() { - return tagger; - } - - public static ShiftReduceParser getModel() { - return model; - } - - private Map getCache() throws SQLException, IOException, CustomError { - return DataMapper.getAllStrings(); - } - - public int getlHMSMXSize() { - return lHMSMX.size(); - } - - public int getstringCacheSize() { - return stringCache.size(); - } - - public void initiateMYSQL() throws SQLException, IOException { - try { - DataMapper.createTables(); - stringCache.putAll(getCache()); - addHLstatsMessages(); - lHMSMX = DataMapper.getAllRelationScores(); - } catch (CustomError ex) { - Logger.getLogger(MYSQLDatahandler.class - .getName()).log(Level.SEVERE, null, ex); - } - } - - private void addHLstatsMessages() { - ConcurrentMap hlStatsMessages = DataMapper.getHLstatsMessages(); - ConcurrentMap strCacheLocal = stringCache; - int hardcap = 300; - int counter = 0; - for (String str : hlStatsMessages.values()) { - if (!str.startsWith("!")) { - boolean present = false; - for (String str1 : strCacheLocal.values()) { - if (str.equals(str1)) { - present = true; - break; - } - } - if (!present) { - MessageResponseHandler.getMessage(str); - } - } - if (counter >= hardcap) { - break; - } - counter++; - } - } - - public void instantiateAnnotationMap() { - for (String str : stringCache.values()) { - System.out.println("str annotation jmwe: " + str + "\n"); - Annotation strAnno = new Annotation(str); - pipelineJMWE.annotate(strAnno); - jmweAnnotationCache.put(str, strAnno); - } - for (String str : stringCache.values()) { - System.out.println("str annotation pipeline: " + str + "\n"); - Annotation strAnno = new Annotation(str); - pipeline.annotate(strAnno); - pipelineAnnotationCache.put(str, strAnno); - } - for (String str : stringCache.values()) { - System.out.println("str annotation pipelinesentiment: " + str + "\n"); - Annotation strAnno = new Annotation(str); - pipelineSentiment.annotate(strAnno); - pipelineSentimentAnnotationCache.put(str, strAnno); - } - } - - public synchronized void checkIfUpdateMatrixes() { - refreshMatrixFromDB = false; - int counter = 0; - if (stopwatch1.elapsed(TimeUnit.SECONDS) >= EXPIRE_TIME_IN_SECONDS1) { - refreshMatrixFromDB = true; - lHMSMX = DataMapper.getAllRelationScores(); - stopwatch1.reset(); - } - //requiring atleast 10 entries ensures no issues in case of empty stringcache - if (stringCache.values().size() > 10 && !refreshMatrixFromDB) { - ConcurrentMap stringCachelocal = stringCache; - int selectUpdate = -1; - LinkedHashMap> LHMSMXLocal = lHMSMX; - int ij2 = 0; - for (String str : stringCachelocal.values()) { - boolean updatepresent = false; - for (String strlocal : LHMSMXLocal.keySet()) { - if (strlocal.equals(str)) { - updatepresent = true; - break; - } - } - if (!updatepresent) { - selectUpdate = ij2; - break; - } - ij2++; - } - if (selectUpdate == -1 || selectUpdate + 1 == stringCachelocal.size()) { - int valueSize = stringCachelocal.size(); - if (secondaryIterator + 1 >= valueSize) { - secondaryIterator = 0; - } - selectUpdate = secondaryIterator; - secondaryIterator++; - } - ConcurrentMap strIndexNavigator = new MapMaker().concurrencyLevel(2).makeMap(); - String get = stringCachelocal.getOrDefault(selectUpdate, null); - if (get == null) { - get = stringCachelocal.get(new Random().nextInt(stringCachelocal.size() - 1)); - } - strIndexNavigator.put(0, get); - ConcurrentMap matrixUpdateList = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); - strIndexNavigator.values().forEach((str) -> { - stringCachelocal.values().stream().filter((str1) -> (!str.equals(str1))).forEachOrdered((str1) -> { - boolean present = false; - LinkedHashMap orDefault = lHMSMX.getOrDefault(str, null); - if (orDefault != null) { - for (String strkey : orDefault.keySet()) { - if (strkey.equals(str1)) { - present = true; - break; - } - } - } - if (!present) { - orDefault = lHMSMX.getOrDefault(str1, null); - if (orDefault != null) { - for (String strkey : orDefault.keySet()) { - if (strkey.equals(str)) { - present = true; - break; - } - } - } - } - if (!present) { - LinkedHashMap orDefault1 = lHMSMX.getOrDefault(str, null); - if (orDefault1 == null) { - orDefault1 = new LinkedHashMap(); - } - orDefault1.put(str1, 0.0); - lHMSMX.put(str, orDefault1); - SimilarityMatrix SMX = new SimilarityMatrix(str, str1); - Callable worker = new SentimentAnalyzerTest(str, str1, SMX, jmweAnnotationCache.get(str), - jmweAnnotationCache.get(str1), pipelineAnnotationCache.get(str), pipelineAnnotationCache.get(str1), - pipelineSentimentAnnotationCache.get(str), pipelineSentimentAnnotationCache.get(str1)); - futures.put(futures.size() + 1, executor.submit(worker)); - } - }); - }); - System.out.println("finished worker assignment, futures size: " + futures.size() + "\n"); - for (Future future : futures.values()) { - SimilarityMatrix SMX = new SimilarityMatrix("", ""); - try { - SMX = future.get(20, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException ex) { - Logger.getLogger(MYSQLDatahandler.class.getName()).log(Level.SEVERE, null, ex); - SMX = null; - } - System.out.println("counter: " + counter + "\nSMX: " + SMX == null ? "SMX null\n" : "SMX not null\n"); - counter++; - if (SMX != null) { - LinkedHashMap getFuture = lHMSMX.getOrDefault(SMX.getPrimaryString(), null); - getFuture.put(SMX.getSecondaryString(), SMX.getDistance()); - lHMSMX.put(SMX.getPrimaryString(), getFuture); - matrixUpdateList.put(matrixUpdateList.size() + 1, SMX); - } - } - try { - if (!matrixUpdateList.isEmpty()) { - DataMapper.insertSementicMatrixes(matrixUpdateList); - System.out.println("finished datamapper semetic insert"); - } - } catch (CustomError ex) { - Logger.getLogger(MYSQLDatahandler.class - .getName()).log(Level.SEVERE, null, ex); - } - } - } - - public synchronized void checkIfUpdateStrings() throws CustomError { - if (stopwatch.elapsed(TimeUnit.SECONDS) >= EXPIRE_TIME_IN_SECONDS || !stopwatch.isRunning()) { - ConcurrentMap str = MessageResponseHandler.getStr(); - str = cutContent(str); - str = filterContent(str); - str = removeSlacks(str); - str = verifyCalculationFitness(str); - try { - DataMapper.InsertMYSQLStrings(str); - } catch (CustomError ex) { - Logger.getLogger(MYSQLDatahandler.class - .getName()).log(Level.SEVERE, null, ex); - } - MessageResponseHandler.setStr(new MapMaker().concurrencyLevel(2).makeMap()); - int j = stringCache.size() + 1; - for (String str1 : str.values()) { - stringCache.put(j, str1); - j++; - Annotation strAnno = new Annotation(str1); - pipelineJMWE.annotate(strAnno); - jmweAnnotationCache.put(str1, strAnno); - strAnno = new Annotation(str1); - pipeline.annotate(strAnno); - pipelineAnnotationCache.put(str1, strAnno); - strAnno = new Annotation(str1); - pipelineSentiment.annotate(strAnno); - pipelineSentimentAnnotationCache.put(str1, strAnno); - } - if (!stopwatch.isRunning()) { - stopwatch.start(); - } else { - stopwatch.reset(); - } - } - } - - public synchronized String getResponseMsg(String str) throws CustomError { - str = str.trim(); - if (str.startsWith("<@")) { - str = str.substring(str.indexOf("> ") + 2); - } - final LinkedHashMap> LHMSMXLocal = lHMSMX; - ConcurrentMap strArrs = stringCache; - double Score = -10000; - SimilarityMatrix SMXreturn = new SimilarityMatrix("", ""); - System.out.println("pre mostSimilarSTR \n"); - String mostSimilarSTR = mostSimilar(str, strArrs); - if (mostSimilarSTR != null) { - System.out.println("mostSimilarSTR; " + mostSimilarSTR + "\n"); - LinkedHashMap orDefault = LHMSMXLocal.getOrDefault(mostSimilarSTR, null); - if (orDefault != null) { - for (Entry entrySet : orDefault.entrySet()) { - double smxDistance = entrySet.getValue(); - if (smxDistance > Score) { - Score = smxDistance; - SMXreturn = new SimilarityMatrix(mostSimilarSTR, entrySet.getKey(), smxDistance); - } - } - } - for (Entry> values1 : LHMSMXLocal.entrySet()) { - LinkedHashMap value = values1.getValue(); - for (Entry keystr : value.entrySet()) { - if (keystr.getKey().equals(mostSimilarSTR)) { - double smxDistance = keystr.getValue(); - if (smxDistance > Score) { - Score = smxDistance; - SMXreturn = new SimilarityMatrix(values1.getKey(), keystr.getKey(), smxDistance); - } - } - } - } - if (!SMXreturn.getPrimaryString().isEmpty()) { - if (SMXreturn.getPrimaryString().equals(mostSimilarSTR)) { - return SMXreturn.getSecondaryString(); - } else { - return SMXreturn.getPrimaryString(); - } - } - } - System.out.println("none within 8 range"); - ConcurrentMap strCache = stringCache; - ConcurrentMap> futureslocal = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str1 : strCache.values()) { - if (!str.equals(str1)) { - SimilarityMatrix SMX = new SimilarityMatrix(str, str1); - Callable worker = new SentimentAnalyzerTest(str, str1, SMX, - jmweAnnotationCache.get(str), jmweAnnotationCache.get(str1), pipelineAnnotationCache.get(str), - pipelineAnnotationCache.get(str1), pipelineSentimentAnnotationCache.get(str), - pipelineSentimentAnnotationCache.get(str1)); - futureslocal.put(futureslocal.size() + 1, executor.submit(worker)); - } - } - int index = 0; - for (Future future : futureslocal.values()) { - SimilarityMatrix SMX = new SimilarityMatrix("", ""); - try { - SMX = future.get(20, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException ex) { - System.out.println("ex getResponsemsg: " + ex.getMessage() + "\n"); - SMX = null; - } - if (SMX != null) { - double distance = SMX.getDistance(); - System.out.println("index: " + index + "\nfutures size: " + futureslocal.values().size() + "\nScore: " + SMX.getDistance() + "\nSecondary: " - + SMX.getSecondaryString() + "\nPrimary: " + SMX.getPrimaryString() + "\n"); - if (distance > Score) { - Score = distance; - SMXreturn = SMX; - } - } - index++; - } - System.out.println("Reached end: secondary: " + SMXreturn.getSecondaryString() + "\nPrimarY: " + SMXreturn.getPrimaryString() - + "\nScore: " + SMXreturn.getDistance()); - return SMXreturn.getSecondaryString(); - } - - public String mostSimilar(String toBeCompared, ConcurrentMap concurrentStrings) { - int minDistance = 8; - String similar = ""; - ConcurrentMap>> futures = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str : concurrentStrings.values()) { - Callable> worker = new LevenshteinDistance(toBeCompared, str); - futures.put(futures.size() + 1, executor.submit(worker)); - } - for (Future> future : futures.values()) { - try { - Entry futureEntry = future.get(); - int distance = futureEntry.getValue(); - if (distance < minDistance) { - System.out.println("distance: " + distance + "\n"); - minDistance = distance; - similar = futureEntry.getKey(); - } - } catch (NullPointerException | InterruptedException | ExecutionException ex) { - System.out.println("failed future\n"); - } - } - return similar; - } - - public static ConcurrentMap cutContent(ConcurrentMap str) { - ConcurrentMap returnlist = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str1 : str.values()) { - int iend = str1.indexOf("content: "); - if (iend != -1) { - String trs = str1.substring(iend + 9); - returnlist.put(returnlist.size() + 1, trs.substring(0, trs.length() - 1)); - } - } - return returnlist; - } - - public static ConcurrentMap filterContent(ConcurrentMap str) { - ConcurrentMap strlistreturn = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str1 : str.values()) { - if (str1.isEmpty() || str1.length() < 3) { - continue; - } - str1 = str1.trim(); - if (str1.contains("PM*")) { - str1 = str1.substring(str1.indexOf("PM*") + 5); - } - if (str1.contains("AM*")) { - str1 = str1.substring(str1.indexOf("AM*") + 5); - } - for (Character c : str1.toCharArray()) { - if (c == '?' || c == '°') { - str1 = str1.replace("?", " <:wlenny:514861023002624001> "); - str1 = str1.replace("°", " <:wlenny:514861023002624001> "); - } - } - if (str1.contains("(Counter-Terrorist)")) { - str1 = str1.replace("(Counter-Terrorist)", " "); - } - if (str1.contains("(Terrorist)")) { - str1 = str1.replace("(Terrorist)", " "); - } - if (str1.contains("(Spectator)")) { - str1 = str1.replace("(Spectator)", " "); - } - if (str1.contains("*DEAD*")) { - str1 = str1.replace("*DEAD*", " "); - } - if (str1.contains("{red}")) { - str1 = str1.replace("{red}", " "); - } - if (str1.contains("{orange}")) { - str1 = str1.replace("{orange}", " "); - } - if (str1.contains("{yellow}")) { - str1 = str1.replace("{yellow}", " "); - } - if (str1.contains("{green}")) { - str1 = str1.replace("{green}", " "); - } - if (str1.contains("{lightblue}")) { - str1 = str1.replace("{lightblue}", " "); - } - if (str1.contains("{blue}")) { - str1 = str1.replace("{blue}", " "); - } - if (str1.contains("{purple}")) { - str1 = str1.replace("{purple}", " "); - } - if (str1.contains("{white}")) { - str1 = str1.replace("{white}", " "); - } - if (str1.contains("{fullblue}")) { - str1 = str1.replace("{fullblue}", " "); - } - if (str1.contains("{cyan}")) { - str1 = str1.replace("{cyan}", " "); - } - if (str1.contains("{lime}")) { - str1 = str1.replace("{lime}", " "); - } - if (str1.contains("{deeppink}")) { - str1 = str1.replace("{deeppink}", " "); - } - if (str1.contains("{slategray}")) { - str1 = str1.replace("{slategray}", " "); - } - if (str1.contains("{dodgerblue}")) { - str1 = str1.replace("{dodgerblue}", " "); - } - if (str1.contains("{black}")) { - str1 = str1.replace("{black}", " "); - } - if (str1.contains("{orangered}")) { - str1 = str1.replace("{orangered}", " "); - } - if (str1.contains("{darkorchid}")) { - str1 = str1.replace("{darkorchid}", " "); - } - if (str1.contains("{pink}")) { - str1 = str1.replace("{pink}", " "); - } - if (str1.contains("{lightyellow}")) { - str1 = str1.replace("{lightyellow}", " "); - } - if (str1.contains("{chocolate}")) { - str1 = str1.replace("{chocolate}", " "); - } - if (str1.contains("{beige}")) { - str1 = str1.replace("{beige}", " "); - } - if (str1.contains("{azure}")) { - str1 = str1.replace("{azure}", " "); - } - if (str1.contains("{yellowgreen}")) { - str1 = str1.replace("{yellowgreen}", " "); - } - str1 = str1.trim(); - if (str1.length() > 2 && (!str1.startsWith("!"))) { - strlistreturn.put(strlistreturn.size() + 1, str1); - } - } - return strlistreturn; - } - - private ConcurrentMap removeSlacks(ConcurrentMap str) { - ShiftReduceParser model = getModel(); - MaxentTagger tagger = getTagger(); - List taggedWords; - ConcurrentMap strreturn = new MapMaker().concurrencyLevel(2).makeMap(); - for (String str1 : str.values()) { - int counter = 0; - ConcurrentMap TGWList = new MapMaker().concurrencyLevel(2).makeMap(); - DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(str1)); - for (List sentence : tokenizer) { - List tagged1 = tagger.tagSentence(sentence); - Tree tree = model.apply(tagged1); - taggedWords = tree.taggedYield(); - for (TaggedWord TGW : taggedWords) { - if (!TGWList.values().contains(TGW.tag()) && !TGW.tag().equals(":") && !TGW.word().equals(TGW.tag())) { - TGWList.put(TGWList.size() + 1, TGW.tag()); - counter++; - } - if (counter > 3) { - int addCounter = 0; - ConcurrentMap wordList = new MapMaker().concurrencyLevel(2).makeMap(); - for (Word lab : tree.yieldWords()) { - if (lab != null && lab.word() != null) { - //System.out.println("lab: " + lab + " \n"); - if (!wordList.values().contains(lab) && lab.value() != null && !lab.value().equals(":")) { - wordList.put(wordList.size() + 1, lab); - addCounter++; - } - } - } - if (addCounter > 3) { - addCounter = 0; - ConcurrentMap HWlist = new MapMaker().concurrencyLevel(2).makeMap(); - for (HasWord HW : tree.yieldHasWord()) { - if (HW != null && HW.word() != null && !HWlist.values().contains(HW)) { - addCounter++; - HWlist.put(HWlist.size() + 1, HW); - } - } - if (addCounter > 3) { - boolean tooclosematch = false; - Collection values = stringCache.values(); - for (String strVals : values) { - LevenshteinDistance leven = new LevenshteinDistance(strVals, str1); - double Distance = leven.computeLevenshteinDistance(); - int maxpermittedDistance = 2; - if (Distance < maxpermittedDistance) { - tooclosematch = true; - break; - } - } - if (!tooclosematch) { - strreturn.put(strreturn.size() + 1, str1); - } - } - } - break; - } - } - if (counter > 3) { - break; - } - } - } - return strreturn; - } - - private ConcurrentMap verifyCalculationFitness(ConcurrentMap strmap) { - ConcurrentMap returnmap = new MapMaker().concurrencyLevel(2).makeMap(); - ConcurrentMap allStrings = stringCache; - int intervalAprove = allStrings.values().size() / 10; - for (String str : strmap.values()) { - int counter = 0; - boolean calculationIssues = false; - ConcurrentMap> futures = new MapMaker().concurrencyLevel(2).makeMap(); - int ij2 = 0; - if (allStrings.isEmpty()) { - allStrings = strmap; - } - for (String strValues : allStrings.values()) { - if (ij2 > intervalAprove) { - break; - } - Callable worker = new SentimentAnalyzerTest(str, strValues, new SimilarityMatrix(str, strValues), - jmweAnnotationCache.get(str), jmweAnnotationCache.get(strValues), pipelineAnnotationCache.get(str), - pipelineAnnotationCache.get(strValues), pipelineSentimentAnnotationCache.get(str), - pipelineSentimentAnnotationCache.get(strValues)); - futures.put(futures.size() + 1, executor.submit(worker)); - ij2++; - } - for (Future future : futures.values()) { - try { - SimilarityMatrix get = future.get(20, TimeUnit.SECONDS); - if (get == null) { - System.out.println("counter timeouts: " + counter + "\n"); - counter++; - if (counter >= 10) { - calculationIssues = true; - break; - } - } - } catch (InterruptedException | ExecutionException | TimeoutException ex) { - System.out.println("counter timeouts: " + counter + "\n"); - counter++; - if (counter >= 10) { - calculationIssues = true; - break; - } - } - } - if (!calculationIssues) { - returnmap.put(returnmap.size() + 1, str); - } - } - return returnmap; - } -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/MessageResponseHandler.java b/ArtificialAutism/src/main/java/FunctionLayer/MessageResponseHandler.java index bca6469e..1c18b0f5 100644 --- a/ArtificialAutism/src/main/java/FunctionLayer/MessageResponseHandler.java +++ b/ArtificialAutism/src/main/java/FunctionLayer/MessageResponseHandler.java @@ -52,20 +52,45 @@ public class MessageResponseHandler { } } String getResponseMsg = Datahandler.instance.getResponseMsg(strreturn, mostRecentMsg); - getResponseMsg = checkPersonPresnetInSentence(personName, getResponseMsg); + getResponseMsg = checkPersonPresentInSentence(personName, getResponseMsg, strreturn); return getResponseMsg; } - private static String checkPersonPresnetInSentence(String personName, String responseMsg) { + private static String checkPersonPresentInSentence(String personName, String responseMsg, String userLastMessage) { + //check if userlastmsg contains person as refference + //check if first person is author or their person of mention String strreturn = responseMsg; CoreDocument pipelineCoreDcoument = new CoreDocument(responseMsg); + CoreDocument pipelineCoreDcoumentLastMsg = new CoreDocument(userLastMessage); Datahandler.getPipeline().annotate(pipelineCoreDcoument); - for (CoreEntityMention em : pipelineCoreDcoument.entityMentions()) { - String entityType = em.entityType(); - if (entityType.equals("PERSON")) { - String replace = strreturn.replaceFirst(em.text(), personName); - return replace; + Datahandler.getPipeline().annotate(pipelineCoreDcoumentLastMsg); + try { + for (CoreEntityMention em : pipelineCoreDcoument.entityMentions()) { + String entityType = em.entityType(); + if (entityType.equals("PERSON")) { + try { + String str = strreturn; + String emText = em.text(); + if (!emText.equals(personName)) { + for (CoreEntityMention emLastMsg : pipelineCoreDcoumentLastMsg.entityMentions()) { + if (!emText.equals(emLastMsg.text())) { + str = strreturn.replaceFirst(emText, emLastMsg.text()); + } + } + try { + str = str.replace(str.substring(str.lastIndexOf(emText), str.length()), personName); + } catch (Exception e) { + System.out.println("failed replacing: " + e.getLocalizedMessage() + "\n"); + } + return str; + } + } catch (Exception e) { + System.out.println("failed person replacement: " + e.getLocalizedMessage() + "\n"); + } + } } + } catch (Exception e) { + System.out.println("SCUFFED JAYZ: " + e.getLocalizedMessage() + "\n"); } return responseMsg; } diff --git a/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SimilarityMatrix.java b/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SimilarityMatrix.java deleted file mode 100644 index e2dc8f90..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/StanfordParser/SimilarityMatrix.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer.StanfordParser; - -import edu.cmu.lti.lexical_db.ILexicalDatabase; -import edu.cmu.lti.lexical_db.NictWordNet; -import edu.cmu.lti.ws4j.RelatednessCalculator; -import edu.cmu.lti.ws4j.impl.HirstStOnge; -import edu.cmu.lti.ws4j.impl.JiangConrath; -import edu.cmu.lti.ws4j.impl.LeacockChodorow; -import edu.cmu.lti.ws4j.impl.Lesk; -import edu.cmu.lti.ws4j.impl.Lin; -import edu.cmu.lti.ws4j.impl.Path; -import edu.cmu.lti.ws4j.impl.Resnik; -import edu.cmu.lti.ws4j.impl.WuPalmer; -import edu.cmu.lti.ws4j.util.WS4JConfiguration; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author install1 - */ -public class SimilarityMatrix { - - private String PrimaryString; - private String SecondaryString; - private double distance; - - public double getDistance() { - return distance; - } - - public void setDistance(double distance) { - this.distance = distance; - } - - public SimilarityMatrix(String str1, String str2) { - this.PrimaryString = str1; - this.SecondaryString = str2; - } - - public SimilarityMatrix(String str1, String str2, double result) { - this.PrimaryString = str1; - this.SecondaryString = str2; - this.distance = result; - } - -/** - * @deprecated - * @return ws4j distance caluclation add infinitum absurdum - */ - public double getDistanceCalculations() { - ILexicalDatabase db = new NictWordNet(); - WS4JConfiguration.getInstance().setMFS(true); - RelatednessCalculator rc1 = new WuPalmer(db); - RelatednessCalculator rc2 = new Resnik(db); - RelatednessCalculator rc3 = new JiangConrath(db); - RelatednessCalculator rc4 = new Lin(db); - RelatednessCalculator rc5 = new LeacockChodorow(db); - RelatednessCalculator rc6 = new Path(db); - RelatednessCalculator rc7 = new Lesk(db); - RelatednessCalculator rc8 = new HirstStOnge(db); - double maxScore = -1D; - List RCList = new ArrayList(); - RCList.add(rc1); - RCList.add(rc2); - RCList.add(rc3); - RCList.add(rc4); - RCList.add(rc5); - RCList.add(rc6); - RCList.add(rc7); - RCList.add(rc8); - for (RelatednessCalculator rc : RCList) { - double s = rc.calcRelatednessOfWords(PrimaryString, SecondaryString); - s /= 1000; - if (s > 0.000000) { - System.out.println("s: " + s + "\n" + " PrimaryString: " + PrimaryString + "\n" + " SecondaryString: " + SecondaryString + "\n" - + " rc: " + rc.toString() + "\n"); - } - String str = String.format("%.12f", s); - if (str.contains(",")) { - str = str.substring(0, str.indexOf(",")); - } - int strend = str.length() > 6 ? 6 : str.length(); - str = str.substring(0, strend); - double score = Double.valueOf(str); - if (score > maxScore) { - maxScore = score; - } - } - return maxScore == -1D ? 0.00 : maxScore; - } - - public String getPrimaryString() { - return PrimaryString; - } - - public void setPrimaryString(String PrimaryString) { - this.PrimaryString = PrimaryString; - } - - public String getSecondaryString() { - return SecondaryString; - } - - public void setSecondaryString(String SecondaryString) { - this.SecondaryString = SecondaryString; - } - -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentAnalyzerTest.java b/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentAnalyzerTest.java deleted file mode 100644 index 43540a9a..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentAnalyzerTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package FunctionLayer.misc; - -import edu.stanford.nlp.ling.HasWord; -import edu.stanford.nlp.ling.IndexedWord; -import edu.stanford.nlp.ling.TaggedWord; -import edu.stanford.nlp.ling.Word; -import edu.stanford.nlp.parser.lexparser.LexicalizedParser; -import edu.stanford.nlp.process.DocumentPreprocessor; -import edu.stanford.nlp.process.Tokenizer; -import edu.stanford.nlp.trees.GrammaticalStructure; -import edu.stanford.nlp.trees.GrammaticalStructureFactory; -import edu.stanford.nlp.trees.Tree; -import edu.stanford.nlp.trees.TreebankLanguagePack; -import edu.stanford.nlp.trees.TypedDependency; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -/** - * - * @author install1 - */ -public class SentimentAnalyzerTest { - - public static SentimentAnalyzerTest instance = new SentimentAnalyzerTest(); - public static String grammar = "edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz"; - public static String[] options = {"-maxLength", "80", "-retainTmpSubcategories"}; - - public static LexicalizedParser initiateLexicalizedParser() { - LexicalizedParser lp = LexicalizedParser.loadModel(grammar, options); - return lp; - } - - public static TreebankLanguagePack initiateTreebankLanguagePack(LexicalizedParser lp) { - TreebankLanguagePack tlp = lp.getOp().langpack(); - return tlp; - } - - public double sentimentanalyzing(String str, String str1, double sreturn, LexicalizedParser lp, TreebankLanguagePack tlp) { - Iterable> sentences; - Tokenizer toke - = tlp.getTokenizerFactory().getTokenizer(new StringReader(str)); - List sentence = toke.tokenize(); - String[] sent3 = {str1}; - String[] tag3 = {"PRP", "MD", "VB", "PRP", "."}; // Parser gets second "can" wrong without help - List sentence2 = new ArrayList<>(); - for (int i = 0; i < sent3.length; i++) { - sentence2.add(new TaggedWord(sent3[i], tag3[i])); - } - //parse.pennPrint(); - List> tmp - = new ArrayList<>(); - tmp.add(sentence2); - tmp.add(sentence); - sentences = tmp; - for (List sentence1 : sentences) { - Tree parse1 = lp.parse(sentence1); - GrammaticalStructureFactory gsf = tlp.grammaticalStructureFactory(); - GrammaticalStructure gs = gsf.newGrammaticalStructure(parse1); - double score = parse1.score(); - if (score > sreturn) { - //System.out.println("\n score : " + score + "\n"); - sreturn = score; - } - } - return sreturn; - } -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentSimilarityCacheObsolete.java b/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentSimilarityCacheObsolete.java deleted file mode 100644 index ed17b40a..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/misc/SentimentSimilarityCacheObsolete.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer.misc; - -import DataLayer.DataMapper; -import FunctionLayer.CustomError; -import FunctionLayer.SimilarityMatrix; -import static FunctionLayer.MYSQLDatahandler.EXPIRE_TIME_IN_SECONDS; -import com.google.common.base.Stopwatch; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.MapMaker; -import com.google.common.collect.Multimap; -import java.io.IOException; -import java.sql.SQLException; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -/** - * - * @author install1 - */ -public class SentimentSimilarityCacheObsolete { - - public static final long EXPIRE_TIME_IN_SECONDS = TimeUnit.SECONDS.convert(5, TimeUnit.HOURS); - private static ConcurrentMap> SimilarityMatrixCache; - private static Stopwatch stopwatch; - - public SentimentSimilarityCacheObsolete(ConcurrentMap StringCache, Stopwatch stopwatch) { - this.stopwatch = Stopwatch.createUnstarted(); - this.SimilarityMatrixCache = new MapMaker().concurrencyLevel(2).makeMap(); - } - - public void clearConCurrentMaps() { - SimilarityMatrixCache.clear(); - } - - private Multimap getCache() throws SQLException, IOException, CustomError { - List matrixlist; - matrixlist = DataMapper.getAllSementicMatrixes(); - Multimap LHM = ArrayListMultimap.create(); - for (int i = 0; i < matrixlist.size(); i++) { - LHM.put(matrixlist.get(i).getPrimaryString(), matrixlist.get(i)); - } - return LHM; - } - - public static String getResponseStr(String strreturn) { - String str = ""; - if (stopwatch.elapsed(TimeUnit.SECONDS) >= EXPIRE_TIME_IN_SECONDS || !stopwatch.isRunning()) { - - if (!stopwatch.isRunning()) { - stopwatch.start(); - } else { - stopwatch.reset(); - } - } - return str; - } - -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityObsolete.java b/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityObsolete.java deleted file mode 100644 index 4ac816fb..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityObsolete.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. -https://github.com/DonatoMeoli/WS4J - */ -package FunctionLayer.misc; - -import edu.cmu.lti.jawjaw.pobj.POS; -import edu.cmu.lti.lexical_db.ILexicalDatabase; -import edu.cmu.lti.lexical_db.NictWordNet; -import edu.cmu.lti.lexical_db.data.Concept; -import edu.cmu.lti.ws4j.Relatedness; -import edu.cmu.lti.ws4j.RelatednessCalculator; -import edu.cmu.lti.ws4j.impl.HirstStOnge; -import edu.cmu.lti.ws4j.impl.JiangConrath; -import edu.cmu.lti.ws4j.impl.LeacockChodorow; -import edu.cmu.lti.ws4j.impl.Lesk; -import edu.cmu.lti.ws4j.impl.Lin; -import edu.cmu.lti.ws4j.impl.Path; -import edu.cmu.lti.ws4j.impl.Resnik; -import edu.cmu.lti.ws4j.impl.WuPalmer; - -/** - * - * @author install1 - * https://www.programcreek.com/java-api-examples/?api=edu.cmu.lti.ws4j.RelatednessCalculator - * https://stackoverflow.com/questions/36300485/how-to-resolve-the-difference-between-the-values-attained-in-the-web-api-and-the - */ -public class WordNetSimalarityObsolete { - - private static ILexicalDatabase db = new NictWordNet(); - private static RelatednessCalculator rc1 = new WuPalmer(db); - private static RelatednessCalculator rc2 = new Resnik(db); - private static RelatednessCalculator rc3 = new JiangConrath(db); - private static RelatednessCalculator rc4 = new Lin(db); - private static RelatednessCalculator rc5 = new LeacockChodorow(db); - private static RelatednessCalculator rc6 = new Path(db); - private static RelatednessCalculator rc7 = new Lesk(db); - private static RelatednessCalculator rc8 = new HirstStOnge(db); - - public static double SentenceMatcherSimilarityMatrix(String[] words1, String[] words2, double maxScore) { - { - double[][] s1 = getSimilarityMatrix(words1, words2, rc1); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s1[i][j] < maxScore && s1[i][j] > 0.0) { - System.out.print(s1[i][j] + "\t"); - System.out.println("WuPalmer"); - maxScore = s1[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc2); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("Resnik"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc3); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("JiangConrath"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc4); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("Lin"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc5); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.print(s2[i][j] + "\t"); - System.out.println("LeacockChodrow"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc6); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("Path"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc7); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("Lesk"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - { - double[][] s2 = getSimilarityMatrix(words1, words2, rc8); - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (s2[i][j] < maxScore && s2[i][j] > 0.0) { - System.out.println("HirstStOnge"); - System.out.print(s2[i][j] + "\t"); - maxScore = s2[i][j]; - } - } - } - } - return maxScore; - } - - public static double[][] getSimilarityMatrix(String[] words1, String[] words2, RelatednessCalculator rc) { - double[][] result = new double[words1.length][words2.length]; - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - double score = rc.calcRelatednessOfWords(words1[i], words2[j]); - result[i][j] = score; - } - } - return result; - } -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityTestObsolete.java b/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityTestObsolete.java deleted file mode 100644 index fef5146c..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/misc/WordNetSimalarityTestObsolete.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer.misc; - -import edu.cmu.lti.lexical_db.ILexicalDatabase; -import edu.cmu.lti.lexical_db.NictWordNet; -import edu.cmu.lti.ws4j.RelatednessCalculator; -import edu.cmu.lti.ws4j.impl.HirstStOnge; -import edu.cmu.lti.ws4j.impl.JiangConrath; -import edu.cmu.lti.ws4j.impl.LeacockChodorow; -import edu.cmu.lti.ws4j.impl.Lesk; -import edu.cmu.lti.ws4j.impl.Lin; -import edu.cmu.lti.ws4j.impl.Path; -import edu.cmu.lti.ws4j.impl.Resnik; -import edu.cmu.lti.ws4j.impl.WuPalmer; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author install1 - * http://ws4jdemo.appspot.com/?mode=s&s1=something+like+a+sentence&s2=should+not+be+like+the+first+one - */ -public class WordNetSimalarityTestObsolete { - - private static ILexicalDatabase db = new NictWordNet(); - private static RelatednessCalculator rc1 = new WuPalmer(db); - private static RelatednessCalculator rc2 = new Resnik(db); - private static RelatednessCalculator rc3 = new JiangConrath(db); - private static RelatednessCalculator rc4 = new Lin(db); - private static RelatednessCalculator rc5 = new LeacockChodorow(db); - private static RelatednessCalculator rc6 = new Path(db); - private static RelatednessCalculator rc7 = new Lesk(db); - private static RelatednessCalculator rc8 = new HirstStOnge(db); - - public static double SentenceMatcherSimilarityMatrix(String[] words1, String[] words2, double maxScore) { - boolean initial = maxScore == 0.0; - List RCList = new ArrayList(); - RCList.add(rc1); - RCList.add(rc2); - RCList.add(rc3); - RCList.add(rc4); - RCList.add(rc5); - RCList.add(rc6); - RCList.add(rc7); - RCList.add(rc8); - for (int h = 0; h < RCList.size(); h++) { - double s1 = getSimilarityMatrix(words1, words2, RCList.get(h), maxScore, initial); - System.out.println("s1: " + String.format("%.0f", s1) + " \nmaxScore: " + maxScore); - if (s1 > 0.01 && (s1 < maxScore || initial)) { - maxScore = s1; - } - } - return maxScore; - } - - public static double getSimilarityMatrix(String[] words1, String[] words2, RelatednessCalculator rc, double maxScore, boolean initial) { - double rtndouble = 0.01; - for (int i = 0; i < words1.length; i++) { - for (int j = 0; j < words2.length; j++) { - if (maxScore > rtndouble / words2.length || initial) { - rtndouble += (rc.calcRelatednessOfWords(words1[i], words2[j])); - //System.out.println("RelatednessCalculator: " + rc.toString()); - } else { - return rtndouble; - } - } - } - return rtndouble; - } -} diff --git a/ArtificialAutism/src/main/java/FunctionLayer/misc/notes.java b/ArtificialAutism/src/main/java/FunctionLayer/misc/notes.java deleted file mode 100644 index 963d9383..00000000 --- a/ArtificialAutism/src/main/java/FunctionLayer/misc/notes.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package FunctionLayer.misc; - -/** - * - * @author install1 - */ -public class notes { - /* - - /* - ILexicalDatabase db = new NictWordNet(); - RelatednessCalculator lesk = new Lesk(db); - POS posWord1 = POS.n; - POS posWord2 = POS.n; - double maxScore = 0; - WS4JConfiguration.getInstance().setMFS(true); - List synsets1 = (List) db.getAllConcepts(strreturn, posWord1.name()); - for (int i = 0; i < allStringValuesPresent.size(); i++) { - List synsets2 = (List) db.getAllConcepts(allStringValuesPresent.get(i), posWord2.name()); - for (Concept synset1 : synsets1) { - for (Concept synset2 : synsets2) { - Relatedness relatedness = lesk.calcRelatednessOfSynset(synset1, synset2); - double score = relatedness.getScore(); - if (score > maxScore) { - maxScore = score; - index = i; - } - } - } - - } - - private static RelatednessCalculator[] rcs; - - static { - WS4JConfiguration.getInstance().setMemoryDB(false); - WS4JConfiguration.getInstance().setMFS(true); - ILexicalDatabase db = new MITWordNet(); - rcs = new RelatednessCalculator[]{ - new HirstStOnge(db), new LeacockChodorow(db), new Lesk(db), new WuPalmer(db), - new Resnik(db), new JiangConrath(db), new Lin(db), new Path(db) - }; - } - https://github.com/DonatoMeoli/WS4J - https://www.programcreek.com/2014/01/calculate-words-similarity-using-wordnet-in-java/ - */ - /* - //available options of metrics - private static RelatednessCalculator[] rcs = { new HirstStOnge(db), - new LeacockChodorow(db), new Lesk(db), new WuPalmer(db), - new Resnik(db), new JiangConrath(db), new Lin(db), new Path(db) }; - */ -} diff --git a/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java b/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java index 2dd7fb3f..be1292b8 100644 --- a/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java +++ b/ArtificialAutism/src/main/java/PresentationLayer/DiscordHandler.java @@ -33,7 +33,7 @@ import org.javacord.api.entity.user.User; */ public class DiscordHandler { - private static String MostRecentMsg = "how are you today bot"; + private static String MostRecentMsg = ""; public static void main(String[] args) { System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "25"); @@ -49,8 +49,8 @@ public class DiscordHandler { Datahandler.instance.shiftReduceParserInitiate(); Datahandler.instance.instantiateAnnotationMap(); System.out.println("FINISHED ALL ANNOTATIONS"); - Datahandler.instance.addHLstatsMessages(); - Datahandler.instance.updateStringCache(); + //Datahandler.instance.addHLstatsMessages(); + //Datahandler.instance.updateStringCache(); String token = "NTI5NzAxNTk5NjAyMjc4NDAx.Dw0vDg.7-aMjVWdQMYPl8qVNyvTCPS5F_A"; DiscordApi api = new DiscordApiBuilder().setToken(token).login().join(); api.addMessageCreateListener(event -> { @@ -92,17 +92,17 @@ public class DiscordHandler { event.getChannel().sendMessage(ResponseStr); MostRecentMsg = ResponseStr; } - new Thread(() -> { - try { - Datahandler.instance.checkIfUpdateStrings(false); - } catch (CustomError ex) { - Logger.getLogger(DiscordHandler.class.getName()).log(Level.SEVERE, null, ex); - } - }).start(); } catch (CustomError ex) { Logger.getLogger(DiscordHandler.class.getName()).log(Level.SEVERE, null, ex); } } + new Thread(() -> { + try { + Datahandler.instance.checkIfUpdateStrings(false); + } catch (CustomError ex) { + Logger.getLogger(DiscordHandler.class.getName()).log(Level.SEVERE, null, ex); + } + }).start(); } }); } diff --git a/ArtificialAutism/target/ArtificialAutism-1.0.jar b/ArtificialAutism/target/ArtificialAutism-1.0.jar index a3d3e067e74158e82fb7f9d47f599fc45e108071..64615d0a47a8c52dd1f76ff7debd6e00dd3d563c 100644 GIT binary patch delta 52696 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

e^fPxlNpWuAY@yf2 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 I_q4szpKvb