Skip to content

Commit

Permalink
Merge 3f2d257 into 924e8fc
Browse files Browse the repository at this point in the history
  • Loading branch information
chzesa committed Apr 26, 2021
2 parents 924e8fc + 3f2d257 commit 92125db
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 6 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Url: https://dev.to/napicellatwit/consistency-models-52l
Lukuvinkkejä voi suodattaa
- otsikon perusteella valitsemalla `title`
- kirjoita hakusana, kuten 'otsikk'
- haku löytää pienistä kirjoitusvirheistä huolimatta, esimerkiksi 'heslinki' tuottaa vinkit, joiden otsikossa on sana 'helsinki'
- otsikon perusteella täsmällisen osan sisältäviä valitsemalla `titleExact`
- luettujen perusteella valitsemalla `read`
- lukemattomien perusteella valitsemalla `unread`

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:29.0-jre'
implementation 'com.google.code.gson:gson:2.8.6'
testCompile 'org.mockito:mockito-core:3.1.0'
testImplementation 'org.mockito:mockito-core:3.1.0'
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package lukuvinkkikirjasto.domain.matcher;

import java.lang.Math;
import lukuvinkkikirjasto.domain.Tip;

/**
* Fuzzy title matcher.
*/
public class Levenshtein implements Matcher {
String str;
int distance;

public Levenshtein(String str, int distance) {
this.str = str.toLowerCase().trim();
this.distance = distance;
}

@Override
public boolean matches(Tip t) {
String title = t.getTitle();
int allowance = Math.max(title.length() - str.length(), 0);

return distance(title, str) <= distance + allowance;
}

static String tail(String s) {
return s.substring(1);
}

static int distance(String left, String right) {
if (left.length() == 0 || right.length() == 0) {
return Math.max(left.length(), right.length());
}

if (left.charAt(0) == right.charAt(0)) {
return distance(tail(left), tail(right));
}

return 1 + Math.min(
Math.min(
distance(tail(left), right),
distance(left, tail(right))
),
distance(tail(left), tail(right))
);
}

@Override
public String toString() {
return "Otsikko sisältää: " + str;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public boolean matches(Tip tip) {

@Override
public String toString() {
return "Otsikko: " + query;
return "Otsikkossa täsmällinen osa: " + query;
}

}
17 changes: 16 additions & 1 deletion app/src/main/java/lukuvinkkikirjasto/ui/ConsoleUi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;
import java.util.Scanner;
import lukuvinkkikirjasto.domain.*;
import lukuvinkkikirjasto.domain.matcher.Levenshtein;
import lukuvinkkikirjasto.domain.matcher.Matcher;
import lukuvinkkikirjasto.domain.matcher.Read;
import lukuvinkkikirjasto.domain.matcher.TitleContains;
Expand Down Expand Up @@ -109,6 +110,8 @@ private void listTips() {
List<Matcher> filters = new ArrayList<Matcher>();

while (true) {
System.out.println("Aktiiviset suodatukset: " + filters.toString());

for (Tip tip : tipService.matchesAll(filters)) {
System.out.println("\nId: " + tip.getId());
System.out.println("Otsikko: " + tip.getTitle());
Expand All @@ -121,14 +124,21 @@ private void listTips() {
}
System.out.println("Komennot:");
System.out.println("title - suodata otsikon perusteella");
System.out.println("titleExact - suodata otsikon perusteella tarkat osumat");
System.out.println("read - suodata luetut");
System.out.println("unread - suodata lukemattomat");
System.out.println("clear - tyhjennä suodatukset " + filters.toString());
System.out.println("undo - poista viimeisin suodatin");
System.out.println("clear - tyhjennä suodatukset ");
System.out.println("menu - takaisin päävalikkoon");

String cmd = scanner.nextLine().trim();
switch (cmd) {
case "title":
System.out.println("Mitä otsikosta haetaan?");
String srch = scanner.nextLine();
filters.add(new Levenshtein(srch, 2));
break;
case "titleExact":
System.out.println("Mitä otsikon täytyy sisältää?");
String titleFilter = scanner.nextLine().trim();
filters.add(new TitleContains(titleFilter));
Expand All @@ -139,6 +149,11 @@ private void listTips() {
case "unread":
filters.add(new Unread());
break;
case "undo":
if (filters.size() > 0) {
filters.remove(filters.size() - 1);
}
break;
case "clear":
filters.clear();
break;
Expand Down
9 changes: 7 additions & 2 deletions app/src/test/java/lukuvinkkikirjasto/Stepdefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,16 @@ public void operationIsCancelled() {
inputLines.add("e");
}

@Given("command title is selected$")
public void commandFilterSelected() {
@Given("command title is selected")
public void commandFilterTitleSelected() {
inputLines.add("title");
}

@Given("command titleExact is selected$")
public void commandFilterTitleExactSelected() {
inputLines.add("titleExact");
}

@When("filter {string} is entered")
public void filterIsEntered(String filter) {
inputLines.add(filter);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package lukuvinkkikirjasto.domain.matcher;

import static org.junit.Assert.*;

import lukuvinkkikirjasto.domain.Tip;
import lukuvinkkikirjasto.domain.matcher.*;
import org.junit.*;

/**
* Unit tests Levenshtein algorithm and matcher.
*/
public class LevenshteinTest {

void cmp(int expected, String a, String b) {
assertEquals(expected, Levenshtein.distance(a, b));
assertEquals(expected, Levenshtein.distance(b, a));
}

@Test
public void exactMatch() {
String a = "hello";
String b = "hello";

cmp(0, a, b);
}

@Test
public void leftZeroLength() {
String a = "";
String b = "world";

cmp(5, a, b);
}

@Test
public void rightZeroLength() {
String a = "morose";
String b = "";

cmp(6, a, b);
}

@Test
public void oneOffLength() {
String a = "test";
String b = "testx";

cmp(1, a, b);
}

@Test
public void oneOffAtBeginning() {
String a = "xtest";
String b = "test";

cmp(1, a, b);
}

@Test
public void oneOffLengthExtraInMiddle() {
String a = "world";
String b = "worxld";

cmp(1, a, b);
}

@Test
public void oneOffLetterChanged() {
String a = "carousel";
String b = "caxousel";

cmp(1, a, b);
}

@Test
public void differentWord() {
String a = "aaaaa";
String b = "bbbbbbb";

cmp(7, a, b);
}

@Test
public void differentWord2() {
String a = "aaaaa";
String b = "bbaabbb";

cmp(5, a, b);
}

@Test
public void testFuzzyMatch() {
String query = "testtt";
Tip tip = new Tip(1, "test", "a");
Matcher m = new Levenshtein(query, 2);
assertTrue(m.matches(tip));
}

@Test
public void testFuzzyNoMatch() {
String query = "texx";
Tip tip = new Tip(1, "test", "a");
Matcher m = new Levenshtein(query, 1);
assertFalse(m.matches(tip));
}

@Test
public void testSwappedLetters() {
String query = "heslinki";
Tip tip = new Tip(1, "helsinki", "a");
Matcher m = new Levenshtein(query, 2);
assertTrue(m.matches(tip));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Feature: Tips can be filtered
Given tip with title "yksi" and url "yksi.com" is created
And tip with title "kaksi" and url "kaksi.com" is created
Given command list is selected
And command title is selected
And command titleExact is selected
And filter "kaksi" is entered
Then filtered results should contain "kaksi.com" but not "yksi.com"
10 changes: 10 additions & 0 deletions app/src/test/resources/lukuvinkkikirjasto/fuzzy_matching.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Feature: Title queries with spelling mistakes match closely related tips

Scenario: Only read tips are shown
Given tip with title "Helsingin Yliopisto" and url "example.com" is created
And tip with title "Helsinki" and url "example.com" is created
And command list is selected
And command title is selected
When filter "hesling" is entered
Then output has line "Helsingin Yliopisto" 2 times
And output has line "Helsinki" 1 times

0 comments on commit 92125db

Please sign in to comment.