Skip to content

Commit

Permalink
Merge pull request #87 from JeffinsonDarmawan/Fuzzy-Logic-2
Browse files Browse the repository at this point in the history
Add Damerau-Levenshtein distance and fixed a bug on parser
  • Loading branch information
Ijaaz01 committed Apr 2, 2024
2 parents 9d992aa + ca1c508 commit 5dd5baf
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 29 deletions.
36 changes: 21 additions & 15 deletions src/main/java/florizz/core/FuzzyLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public static String detectItem(String userInput) throws FlorizzException {
Ui uiFuzzy = new Ui();

// Iterate over predefined commands
for (String command : ITEMS.keySet()) {
int distance = computeLevenshteinDistance(command, userInput);
for (String item : ITEMS.keySet()) {
int distance = computeDLDistance(item, userInput);
if (distance < bestDistance) {
bestDistance = distance;
bestMatch = command;
bestMatch = item;
}
}

Expand All @@ -79,19 +79,19 @@ public static String detectItem(String userInput) throws FlorizzException {
}

/**
* Computes the Levenshtein distance which is a metric used to measure the similarity between two strings.
* Computes the Damerau-Levenshtein distance which is a metric used to measure the similarity between two strings.
* It calculates the minimum number of single-character edits required to change one string into another.
* These edits can be insertions, deletions, or substitutions of individual characters.
* These edits can be insertions, deletions, substitutions and transpositions of individual characters.
*
* @param s1 The first string.
* @param s2 The second string.
* @return The Levenshtein distance between the two strings.
* @param item The first string.
* @param userInput The second string.
* @return The Damerau-Levenshtein distance between the two strings.
*/
private static int computeLevenshteinDistance(String s1, String s2) {
assert s1 != null && s2 != null : "Strings cannot be null";
private static int computeDLDistance(String item, String userInput) {
assert item != null && userInput != null : "Strings cannot be null";

int m = s1.length();
int n = s2.length();
int m = item.length();
int n = userInput.length();

int[] previousRow = new int[n + 1];
int[] currentRow = new int[n + 1];
Expand All @@ -101,16 +101,22 @@ private static int computeLevenshteinDistance(String s1, String s2) {
previousRow[j] = j;
}

// Calculate the Levenshtein distance
// Calculate the Damerau-Levenshtein distance
for (int i = 1; i <= m; i++) {
currentRow[0] = i;

for (int j = 1; j <= n; j++) {
int substitutionCost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;
int substitutionCost = (item.charAt(i - 1) == userInput.charAt(j - 1)) ? 0 : 1;
currentRow[j] = Math.min(Math.min(
previousRow[j] + 1, // deletion
currentRow[j - 1] + 1), // insertion
previousRow[j - 1] + substitutionCost); // substitution

// Check for transpositions
if (i > 1 && j > 1 && item.charAt(i - 1) == userInput.charAt(j - 2)
&& item.charAt(i - 2) == userInput.charAt(j - 1)) {
currentRow[j] = Math.min(currentRow[j], previousRow[j - 2] + substitutionCost);
}
}

// Swap rows
Expand All @@ -119,7 +125,7 @@ private static int computeLevenshteinDistance(String s1, String s2) {
currentRow = tempRow;
}

// Return the Levenshtein distance
// Return the Damerau-Levenshtein distance
assert previousRow[n] >= 0 : "Levenshtein distance cannot be negative";
return previousRow[n];
}
Expand Down
47 changes: 34 additions & 13 deletions src/main/java/florizz/core/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,47 @@ public static Command parse (String input) throws FlorizzException {


/**
* Splits input into command and arguments. Also handles capitalisation and space exceptions
* Splits input into command and arguments (if any). Handles capitalisation, whitespaces and small typos.
*
* @param input
* @return String[] output; output[0] = command ; output[1] arguments
* @return String[] output; output[0] = item ; output[1] = argument(s)
*/

private static String[] commandHandler(String input) throws FlorizzException {
String[] output = new String[2];
String trimmedInput = input.trim();
int firstWhitespace = trimmedInput.indexOf(" ");
if (firstWhitespace != -1) {
// input have arguments
output[0] = FuzzyLogic.detectItem(trimmedInput.substring(0,firstWhitespace).toLowerCase());
output[1] = FuzzyLogic.detectItem(trimmedInput.substring(firstWhitespace).trim());
} else {
output[0] = FuzzyLogic.detectItem(trimmedInput.toLowerCase());
String[] outputs = new String[2];
try {
String trimmedInput = input.trim();
int firstWhitespace = trimmedInput.indexOf(" ");
if (firstWhitespace != -1) {
outputs[0] = FuzzyLogic.detectItem(trimmedInput.substring(0,firstWhitespace).toLowerCase());
switch (outputs[0]) {
case ("delete"): // Fallthrough
case ("new"):
outputs[1] = trimmedInput.substring(firstWhitespace).trim();
break;
case ("remove"): // Fallthrough
case ("add"):
String[] arguments = new String[2];
String trimmedArgument = trimmedInput.substring(firstWhitespace).trim();
int secondWhitespace = trimmedArgument.indexOf(" ");
arguments[0] = FuzzyLogic.detectItem(trimmedArgument.substring(0,secondWhitespace));
arguments[1] = trimmedArgument.substring(secondWhitespace).trim();
outputs[1] = arguments[0] + " " + arguments[1];
break;
default:
outputs[1] = FuzzyLogic.detectItem(trimmedInput.substring(firstWhitespace).trim());
break;
}
} else {
outputs[0] = FuzzyLogic.detectItem(trimmedInput.toLowerCase());
}
} catch (FlorizzException ex) {
Logger.getLogger("CommandHandler").log(Level.SEVERE, "Exception occurred in commandHandler", ex);
throw ex;
}
return output;
return outputs;
}


/**
* remove prefix from an input string
* e.g. "/to For Mom" -> " For Mom"
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/florizz/core/Ui.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void printBouquetDeleted(Bouquet bouquetDeleted){
* @param bouquetList The list of saved bouquets.
*/
public void printAllBouquets(ArrayList<Bouquet> bouquetList){
System.out.println("Here are the list of your saved bouquets:");
System.out.println("Here is the list of your saved bouquets:");
int i = 1;
double totalPrice = 0;
for (Bouquet bouquet : bouquetList){
Expand Down

0 comments on commit 5dd5baf

Please sign in to comment.