-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
204 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
app/src/main/java/lukuvinkkikirjasto/domain/matcher/Levenshtein.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
app/src/test/java/lukuvinkkikirjasto/domain/matcher/LevenshteinTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
app/src/test/resources/lukuvinkkikirjasto/fuzzy_matching.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |