forked from nus-cs2103-AY1920S1/addressbook-level3
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from AY1920S1-CS2103-T14-4/Autocomplete_ZH
AutoComplete V1
- Loading branch information
Showing
23 changed files
with
787 additions
and
108 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
@startuml | ||
|
||
(*) --> "user input" | ||
if "listener detects input change" then | ||
--> [Yes] "initialize AC model" | ||
--> "get suggestions based on truncated input" | ||
--> "display the result on listview" | ||
--> (*) | ||
else | ||
--> [No] "display empty listview" | ||
--> (*) | ||
endif | ||
|
||
@enduml |
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,72 @@ | ||
@startuml | ||
!include style.puml | ||
|
||
box Ui UI_COLOR_T1 | ||
participant ":CommandBox" as CommandBox UI_COLOR | ||
'participant ":QueryCard" as QueryCard UI_COLOR | ||
'participant ":TextField" as TextField UI_COLOR | ||
end box | ||
|
||
box Logic LOGIC_COLOR_T1 | ||
participant ":AutoComplete" as AutoComplete LOGIC_COLOR | ||
participant ":BinarySearch" as BinarySearch LOGIC_COLOR | ||
end box | ||
|
||
box Model MODEL_COLOR_T1 | ||
participant ":AutoCompleteModel" as AutoCompleteModel MODEL_COLOR | ||
participant ":Word" as Word MODEL_COLOR | ||
end box | ||
|
||
[-> CommandBox : autoCompleteListener() | ||
activate CommandBox | ||
|
||
[-> CommandBox : userInput | ||
|
||
CommandBox -> AutoComplete : initAc() | ||
activate AutoComplete | ||
|
||
AutoComplete -> AutoComplete : importDictionary(file) | ||
AutoComplete -> AutoComplete : data | ||
|
||
create AutoCompleteModel | ||
AutoComplete -> AutoCompleteModel : data | ||
activate AutoCompleteModel | ||
|
||
AutoCompleteModel -> AutoComplete | ||
deactivate AutoCompleteModel | ||
deactivate AutoComplete | ||
|
||
CommandBox -> AutoComplete : getSuggestions(userInput) | ||
activate AutoComplete | ||
|
||
AutoComplete -> AutoCompleteModel : allMatches(userInput) | ||
activate AutoCompleteModel | ||
|
||
create Word | ||
AutoCompleteModel -> Word : userInput, weight | ||
activate Word | ||
|
||
Word -> AutoCompleteModel | ||
deactivate Word | ||
|
||
AutoCompleteModel -> BinarySearch : firstIndexOf(userInput) | ||
activate BinarySearch | ||
|
||
BinarySearch -> AutoCompleteModel : index1 | ||
deactivate BinarySearch | ||
|
||
AutoCompleteModel -> BinarySearch : lastIndexOf(userInput) | ||
activate BinarySearch | ||
|
||
BinarySearch -> AutoCompleteModel : index2 | ||
deactivate BinarySearch | ||
|
||
AutoCompleteModel -> AutoComplete : matchedResults | ||
deactivate AutoCompleteModel | ||
|
||
AutoComplete -> CommandBox : matchedResults | ||
deactivate AutoComplete | ||
|
||
CommandBox ->[ : display() | ||
deactivate CommandBox | ||
@enduml |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
112 changes: 112 additions & 0 deletions
112
src/main/java/seedu/address/logic/search/AutoComplete.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,112 @@ | ||
package seedu.address.logic.search; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import seedu.address.MainApp; | ||
import seedu.address.model.autocomplete.AutoCompleteModel; | ||
import seedu.address.model.autocomplete.Word; | ||
|
||
/** | ||
* Main controller class to execute the searching logic | ||
*/ | ||
public class AutoComplete { | ||
|
||
private static final int numOfSug = 10; | ||
|
||
private static AutoCompleteModel acModel; | ||
private static Word[] matchedResults; | ||
private static boolean displayWeights; | ||
|
||
public AutoComplete() { | ||
matchedResults = new Word[numOfSug]; | ||
displayWeights = false; | ||
} | ||
|
||
/** | ||
* Read word storage from txt | ||
* | ||
* @param is path for the library of words | ||
* @return the suggestions to be shown in textField | ||
*/ | ||
private static Word[] importDictionary(InputStream is) { | ||
Word[] queries = null; | ||
try { | ||
is.mark(0); | ||
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); | ||
int lines = 0; | ||
while (reader.readLine() != null) { | ||
lines++; | ||
} | ||
is.reset(); | ||
queries = new Word[lines]; | ||
for (int i = 0; i < lines; i++) { | ||
String line = reader.readLine(); | ||
if (line == null) { | ||
System.err.println("Could not read line " + (i + 1)); | ||
System.exit(1); | ||
} | ||
int tab = line.indexOf('\t'); | ||
if (tab == -1) { | ||
System.err.println("No tab character in line " + (i + 1)); | ||
System.exit(1); | ||
} | ||
long weight = Long.parseLong(line.substring(0, tab).trim()); | ||
String query = line.substring(tab + 1); | ||
queries[i] = new Word(query, weight); | ||
} | ||
reader.close(); | ||
} catch (Exception e) { | ||
System.err.println("Could not read or parse input file "); | ||
e.printStackTrace(); | ||
System.exit(1); | ||
} | ||
|
||
return queries; | ||
} | ||
|
||
/** | ||
* Initialize an autocomplete model | ||
*/ | ||
public static void initAc() { | ||
InputStream in = MainApp.class.getResourceAsStream("/data/vocabulary.txt"); | ||
Word[] data = importDictionary(in); | ||
acModel = new AutoCompleteModel(data); | ||
} | ||
|
||
/** | ||
* Makes a call to the implementation of AutoCompleteModel to get | ||
* suggestions for the currently entered text. | ||
* | ||
* @param text string to search for | ||
*/ | ||
public static List<String> getSuggestions(String text) { | ||
|
||
List<String> suggestions = new ArrayList<>(); | ||
// don't search for suggestions if there is no input | ||
if (text.length() > 0) { | ||
// get all matching words | ||
Word[] allResults = acModel.allMatches(text); | ||
if (allResults == null) { | ||
throw new NullPointerException("allMatches() is null"); | ||
} | ||
|
||
if (allResults.length > numOfSug) { | ||
matchedResults = Arrays.copyOfRange(allResults, 0, numOfSug); | ||
} else { | ||
matchedResults = allResults; | ||
} | ||
|
||
if (!displayWeights) { | ||
for (Word matchedResult : matchedResults) { | ||
suggestions.add(matchedResult.getQuery()); | ||
} | ||
} | ||
} | ||
return suggestions; | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
src/main/java/seedu/address/logic/search/BinarySearch.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,99 @@ | ||
package seedu.address.logic.search; | ||
|
||
import java.util.Comparator; | ||
|
||
/** | ||
* Utility class to find the first and the last index of key using Binary Search. | ||
*/ | ||
public class BinarySearch { | ||
|
||
/** | ||
* Searches the specified array for the specified value using modification of binary | ||
* search algorithm and returns the index of the first key in list[] that equals the search key, | ||
* or -1 if no such key were found. | ||
* | ||
* @param list - the array of keys to be searched | ||
* @param key - the value to be searched for | ||
* @param comparator - the comparator by which array is ordered | ||
* @return - the index of the last key in list that equals the search key, -1 if not found | ||
* @throws NullPointerException - if list is null | ||
* @throws NullPointerException - if key is null | ||
* @throws NullPointerException - if comparator is null | ||
*/ | ||
public static <T> int firstIndexOf(T[] list, T key, Comparator<T> comparator) { | ||
if (list == null || key == null || comparator == null) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
if (list.length == 0) { | ||
return -1; | ||
} | ||
if (comparator.compare(list[0], key) == 0) { | ||
return 0; | ||
} | ||
|
||
int lo = 0; | ||
int hi = list.length - 1; | ||
|
||
while (lo <= hi) { | ||
int mid = lo + (hi - lo) / 2; | ||
int cmp = comparator.compare(list[mid], key); | ||
|
||
if (cmp >= 1) { | ||
hi = mid - 1; | ||
} else if (cmp <= -1) { | ||
lo = mid + 1; | ||
} else if (comparator.compare(list[mid - 1], list[mid]) == 0) { | ||
hi = mid - 1; | ||
} else { | ||
return mid; | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
/** | ||
* Searches the specified array for the specified value using modification of binary | ||
* search algorithm and returns the index of the last key in list[] that equals the search key, | ||
* or -1 if no such key were found. | ||
* | ||
* @param list - the array of keys to be searched | ||
* @param key - the value to be searched for | ||
* @param comparator - the comparator by which array is ordered | ||
* @return - the index of the last key in list that equals the search key, -1 if not found | ||
* @throws NullPointerException - if list is null | ||
* @throws NullPointerException - if key is null | ||
* @throws NullPointerException - if comparator is null | ||
*/ | ||
public static <T> int lastIndexOf(T[] list, T key, Comparator<T> comparator) { | ||
if (list == null || key == null || comparator == null) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
if (list.length == 0) { | ||
return -1; | ||
} | ||
if (comparator.compare(list[list.length - 1], key) == 0) { | ||
return list.length - 1; | ||
} | ||
|
||
int lo = 0; | ||
int hi = list.length - 1; | ||
|
||
while (lo <= hi) { | ||
int mid = lo + (hi - lo) / 2; | ||
int cmp = comparator.compare(list[mid], key); | ||
|
||
if (cmp >= 1) { | ||
hi = mid - 1; | ||
} else if (cmp <= -1) { | ||
lo = mid + 1; | ||
} else if (comparator.compare(list[mid + 1], list[mid]) == 0) { | ||
lo = mid + 1; | ||
} else { | ||
return mid; | ||
} | ||
} | ||
return -1; | ||
} | ||
} |
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
Oops, something went wrong.