Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: sort by longest exact match in immersion kit & massif #370

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 48 additions & 12 deletions yuuna/lib/src/creator/enhancements/immersion_kit_enhancement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ImmersionKitResult {
required this.wordList,
required this.wordIndices,
required this.calculateRange,
required this.longestExactMatch,
});

/// The sentence in plain unformatted form.
Expand All @@ -48,6 +49,9 @@ class ImmersionKitResult {

TextRange? _calculatedRange;

/// How many consecutive characters match the search term exactly
int longestExactMatch;

/// Function to calculate the range of search term
TextRange Function() calculateRange;

Expand Down Expand Up @@ -236,6 +240,26 @@ class ImmersionKitEnhancement extends Enhancement {
}
}

int _longestExactRangeForResult({
required List<int> wordIndices,
required List<String> wordList,
required String term,
required String text,
}) {
/// Start at the first character of the given cloze
int textPosition = wordList.sublist(0, wordIndices.first).join().length;
int termPosition = 0;

while (textPosition < text.length &&
termPosition < term.length &&
term[termPosition] == text[textPosition]) {
termPosition++;
textPosition++;
}

return termPosition;
}

/// Search the Massif API for example sentences and return a list of results.
Future<List<ImmersionKitResult>> searchForSentences({
required AppModel appModel,
Expand Down Expand Up @@ -290,18 +314,23 @@ class ImmersionKitEnhancement extends Enhancement {
String audioUrl = example['sound_url'];

ImmersionKitResult result = ImmersionKitResult(
text: text,
source: source,
imageUrl: imageUrl,
audioUrl: audioUrl,
wordList: wordList,
wordIndices: wordIndices,
calculateRange: () => _getRangeFromIndexedList(
wordIndices: wordIndices,
text: text,
source: source,
imageUrl: imageUrl,
audioUrl: audioUrl,
wordList: wordList,
term: searchTerm,
),
);
wordIndices: wordIndices,
calculateRange: () => _getRangeFromIndexedList(
wordIndices: wordIndices,
wordList: wordList,
term: searchTerm,
),
longestExactMatch: _longestExactRangeForResult(
wordIndices: wordIndices,
wordList: wordList,
text: text,
term: searchTerm,
));

/// Sentence examples that are merely the word itself are pretty
/// redundant.
Expand All @@ -313,7 +342,7 @@ class ImmersionKitEnhancement extends Enhancement {
/// Make sure series aren't too consecutive.
results.shuffle();

/// Results with images come first.
/// Sort by: has image -> has audio -> longest exact match -> shortest sentence
results.sort((a, b) {
int hasImage = (a.imageUrl.isNotEmpty ? -1 : 1)
.compareTo(b.imageUrl.isNotEmpty ? -1 : 1);
Expand All @@ -329,6 +358,13 @@ class ImmersionKitEnhancement extends Enhancement {
return hasAudio;
}

/// Sort by longest subterm
int longestMatch = b.longestExactMatch.compareTo(a.longestExactMatch);

if (longestMatch != 0) {
return longestMatch;
}

return a.text.length.compareTo(b.text.length);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class MassifResult {
required this.range,
required this.source,
required this.spans,
required this.longestExactMatch,
});

/// The sentence in plain unformatted form.
Expand All @@ -27,6 +28,9 @@ class MassifResult {
/// A formatted widget which may contain highlighted text.
List<InlineSpan> spans;

/// How many consecutive characters match the search term exactly
int longestExactMatch;

/// First selected range.
TextRange range;

Expand Down Expand Up @@ -102,6 +106,29 @@ class MassifExampleSentencesEnhancement extends Enhancement {
);
}

int _longestExactRangeForResult({
required int? start,
required String term,
required String text,
}) {
if (start == null) {
return 0;
}

/// Start at the first character of the given cloze
int textPosition = start;
int termPosition = 0;

while (textPosition < text.length &&
termPosition < term.length &&
term[termPosition] == text[textPosition]) {
termPosition++;
textPosition++;
}

return termPosition;
}

/// Search the Massif API for example sentences and return a list of results.
Future<List<MassifResult>> searchForSentences({
required BuildContext context,
Expand Down Expand Up @@ -209,11 +236,27 @@ class MassifExampleSentencesEnhancement extends Enhancement {
}

MassifResult result = MassifResult(
text: text,
range: range,
source: source,
spans: spans,
);
text: text,
range: range,
source: source,
spans: spans,
longestExactMatch: _longestExactRangeForResult(
start: start,
term: searchTerm,
text: text,
));

/// Sort by: longest exact match -> shortest sentence
results.sort((a, b) {
/// Sort by longest subterm
int longestMatch = b.longestExactMatch.compareTo(a.longestExactMatch);

if (longestMatch != 0) {
return longestMatch;
}

return a.text.length.compareTo(b.text.length);
});

results.add(result);
}
Expand Down
Loading