@ -1,5 +1,4 @@
import ' dart:developer ' ;
import ' dart:math ' ;
import ' package:flutter/foundation.dart ' ;
@ -19,6 +18,8 @@ import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart';
import ' package:fluffychat/pangea/learning_settings/constants/language_constants.dart ' ;
import ' package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart ' ;
import ' package:fluffychat/pangea/toolbar/models/practice_activity_model.dart ' ;
import ' package:fluffychat/pangea/toolbar/repo/lemma_activity_generator.dart ' ;
import ' package:fluffychat/pangea/toolbar/repo/lemma_meaning_activity_generator.dart ' ;
import ' package:fluffychat/widgets/matrix.dart ' ;
import ' ../../analytics/models/lemma.dart ' ;
import ' ../../common/constants/model_keys.dart ' ;
@ -314,14 +315,14 @@ class PangeaToken {
] ) {
switch ( a ) {
case ActivityTypeEnum . wordMeaning:
if ( daysSinceLastUseByType ( ActivityTypeEnum . wordMeaning ) < 1 ) {
if ( daysSinceLastUseByType ( ActivityTypeEnum . wordMeaning ) < 7 ) {
return false ;
}
if ( isContentWord ) {
return vocabConstruct . points < 3 0 ;
return vocabConstruct . points < 3 ;
} else if ( canBeDefined ) {
return vocabConstruct . points < 5 ;
return vocabConstruct . points < 1 ;
} else {
return false ;
}
@ -398,10 +399,10 @@ class PangeaToken {
) ;
return distractors . isNotEmpty ;
case ActivityTypeEnum . wordMeaning:
return Lemma InfoRepo. getDistractorDefinition s(
return Lemma MeaningActivityGenerator. canGenerateDistractor s(
lemma . text ,
1 ,
) .isNotEmpty ;
pos ,
) ;
case ActivityTypeEnum . emoji:
case ActivityTypeEnum . wordFocusListening:
case ActivityTypeEnum . hiddenWordListening:
@ -410,7 +411,8 @@ class PangeaToken {
}
Future < bool > canGenerateLemmaDistractors ( ) async {
final distractors = await lemmaActivityDistractors ( this ) ;
final distractors =
await LemmaActivityGenerator ( ) . lemmaActivityDistractors ( this ) ;
return distractors . isNotEmpty ;
}
@ -657,72 +659,4 @@ class PangeaToken {
possibleDistractors . shuffle ( ) ;
return possibleDistractors . take ( 3 ) . toList ( ) ;
}
Future < List < String > > lemmaActivityDistractors ( PangeaToken token ) async {
final List < String > lemmas = MatrixState
. pangeaController . getAnalytics . constructListModel
. constructList ( type: ConstructTypeEnum . vocab )
. map ( ( c ) = > c . lemma )
. toSet ( )
. toList ( ) ;
/ / Offload computation to an isolate
final Map < String , int > distances =
await compute ( _computeDistancesInIsolate , {
' lemmas ' : lemmas ,
' target ' : token . lemma . text ,
} ) ;
/ / Sort lemmas by distance
final sortedLemmas = distances . keys . toList ( )
. . sort ( ( a , b ) = > distances [ a ] ! . compareTo ( distances [ b ] ! ) ) ;
/ / Take the shortest 4
final choices = sortedLemmas . take ( 4 ) . toList ( ) ;
if ( ! choices . contains ( token . lemma . text ) ) {
final random = Random ( ) ;
choices [ random . nextInt ( 4 ) ] = token . lemma . text ;
}
return choices ;
}
/ / isolate helper function
Map < String , int > _computeDistancesInIsolate ( Map < String , dynamic > params ) {
final List < String > lemmas = params [ ' lemmas ' ] ;
final String target = params [ ' target ' ] ;
/ / Calculate Levenshtein distances
final Map < String , int > distances = { } ;
for ( final lemma in lemmas ) {
distances [ lemma ] = levenshteinDistanceSync ( target , lemma ) ;
}
return distances ;
}
int levenshteinDistanceSync ( String s , String t ) {
final int m = s . length ;
final int n = t . length ;
final List < List < int > > dp = List . generate (
m + 1 ,
( _ ) = > List . generate ( n + 1 , ( _ ) = > 0 ) ,
) ;
for ( int i = 0 ; i < = m ; i + + ) {
for ( int j = 0 ; j < = n ; j + + ) {
if ( i = = 0 ) {
dp [ i ] [ j ] = j ;
} else if ( j = = 0 ) {
dp [ i ] [ j ] = i ;
} else if ( s [ i - 1 ] = = t [ j - 1 ] ) {
dp [ i ] [ j ] = dp [ i - 1 ] [ j - 1 ] ;
} else {
dp [ i ] [ j ] = 1 +
[ dp [ i - 1 ] [ j ] , dp [ i ] [ j - 1 ] , dp [ i - 1 ] [ j - 1 ] ]
. reduce ( ( a , b ) = > a < b ? a : b ) ;
}
}
}
return dp [ m ] [ n ] ;
}
}