diff --git a/app/src/main/java/ch/nuth/zhaw/exbox/FuzzySearchServer.java b/app/src/main/java/ch/nuth/zhaw/exbox/FuzzySearchServer.java index c4be5d0..53a4b92 100644 --- a/app/src/main/java/ch/nuth/zhaw/exbox/FuzzySearchServer.java +++ b/app/src/main/java/ch/nuth/zhaw/exbox/FuzzySearchServer.java @@ -1,10 +1,12 @@ package ch.nuth.zhaw.exbox; +import java.io.BufferedReader; +import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; public class FuzzySearchServer implements CommandExecutor { public static List names = new ArrayList<>(); // List of all names @@ -15,11 +17,24 @@ public class FuzzySearchServer implements CommandExecutor { // each name only once (i.e. no doublettes allowed public static void loadNames(String nameString) { // TODO implement + BufferedReader reader = new BufferedReader(new StringReader(nameString)); + String line; + + try { + while ((line = reader.readLine()) != null) { + String name = line.split(";")[0]; + names.add(name); + } + } catch (Exception e) { + System.err.println("An error occurred:"); + System.err.println(e); + } } // add a single trigram to 'trigrams' index public static void addToTrigrams(int nameIdx, String trig) { // TODO implement + trigrams.computeIfAbsent(trig, (_name) -> new ArrayList<>()).add(nameIdx); } // works better for flipped and short names if " " added and lowercase @@ -29,52 +44,80 @@ public class FuzzySearchServer implements CommandExecutor { // construct a list of trigrams for a name public static List trigramForName(String name) { + List result = new ArrayList<>(); name = nomalize(name); // TODO implement + + for (int i = 0; i < name.length() - 3; i++) { + result.add(name.substring(i, i + 3)); + } + + return result; } public static void constructTrigramIndex(List names) { for (int nameIdx = 0; nameIdx < names.size(); nameIdx++) { List trigs = trigramForName(names.get(nameIdx)); + for (String trig : trigs) { addToTrigrams(nameIdx, trig); } } } - private static void incCount(int cntIdx) { - Integer c = counts.get(cntIdx); - c = (c == null) ? 1 : c + 1; - counts.put(cntIdx, c); + private static void incCount(int cntIdx, Map counts) { + int count = counts.computeIfAbsent(cntIdx, (_index) -> 0); + counts.put(cntIdx, count + 1); } // find name index with most corresponding trigrams // if no trigram/name matches at all then return -1 - public static int findIdx(String name) { - counts.clear(); + public static int findIdx(String name, Map counts) { int maxIdx = -1; - // TODO implement + int maxCount = -1; + + for (String trigram : trigramForName(name)) { + if (trigrams.containsKey(trigram)) { + for (int index : trigrams.get(trigram)) { + incCount(index, counts); + } + } + } + + for (Entry entry : counts.entrySet()) { + if (entry.getValue() > maxCount) { + maxCount = entry.getValue(); + maxIdx = entry.getKey(); + } + } + return maxIdx; } - // finde Namen gebe "" zurück wenn gefundener Name nicht grösser als verlangter score ist. + + // finde Namen gebe "" zurück wenn gefundener Name nicht grösser als verlangter + // score ist. public static String find(String searchName, int scoreRequired) { - int found = findIdx(searchName); + Map counts = new HashMap<>(); + int found = findIdx(searchName, counts); String foundName = ""; - if (found >= 0 && score(found) >= scoreRequired) { + + if (found >= 0 && score(found, counts) >= scoreRequired) { foundName = names.get(found); } return foundName; } - private static int score(int found) { + private static int score(int found, Map counts) { String foundName = names.get(found); return (int) (100.0 * Math.min(counts.get(found), foundName.length()) / foundName.length()); } public String execute(String searchName) { - int found = findIdx(searchName); + Map counts = new HashMap<>(); + int found = findIdx(searchName, counts); + if (found >= 0) { - int score = score(found); + int score = score(found, counts); String foundName = names.get(found); return searchName + " -> " + foundName + " " + score + "%\n"; } else { @@ -82,14 +125,6 @@ public class FuzzySearchServer implements CommandExecutor { } } - public static void main(String[] args) { - FuzzySearchServer fs = new FuzzySearchServer(); - System.out.println(fs.execute("Kiptum Daniel")); - System.out.println(fs.execute("Daniel Kiptum")); - System.out.println(fs.execute("Kip Dan")); - System.out.println(fs.execute("Dan Kip")); - } - static { String rangliste = "Mueller Stefan;02:31:14\n" + "Marti Adrian;02:30:09\n" +