* fix(IT Controller): fixed accuracy issues with star calcultion and point calculation for vocab + grammar. Added number animation. Staggered animations * generated * chore: redirect to new group page on click new chat button in space view (#2354) * chore: disable custom message text sizing (#2355) * feat: initial work to prevent giving points for copy-pasted text (#2345) * feat: initial work to prevent giving points for copy-pasted text * chore: replace tokenization with comparing token content with pasted content * fix(emoji_activity_generator): ensure unique choices * fix(intl_en): two copy edits * fix(lemma_meaning_widget): fix text alignment * chore(practice_selection): preferencing tokens without activities in selection * 2364 on chat creation with activity if no room image set activity image (#2371) * chore: formatting * chore: on chat creation without activity, set avatar to activity image if no image set * chore: in empty chat popup, listen for changes to participant count and close self if it increases (#2372) * chore: constrain width of unsubscribed card (#2373) * chore: fix dialogs in report offensive message flow (#2380) * chore: fix off-center close button in level up notifications (#2382) * chore: fix discrepency between original message and centered message border radius (#2383) * chore: don't show presence indicator on small avatars (#2386) * chore: give max height to image in activity suggestion dialog (#2403) * chore: when navigating to space details, always open space view (#2405) * chore: fix vertical alignment of tokens in HTML-formatted messages (#2406) * added robot animation and message to instruct user to wait after too … (#2415) * added robot animation and message to instruct user to wait after too many join with code attempts * chore: formatting * replaced hardcoded text with intl_en.arb * Resolving missing import * generated * chore: formatting --------- Co-authored-by: ggurdin <ggurdin@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * refactor: separate token and message reading assistance modes (#2416) * refactor: separate token and message reading assistance modes * chore: apply same token styling to HTML formatted messages * chore: don't wait for lemma responses before showing reading assistance content * 2421 reading assistance mode split feedback from will (#2422) * chore: make input bar shorter in token mode * chore: retry showing reading assistance content for initial token * chore: make background lighter in token mode * Added 'JoinByCode' button on new group view (#2417) * Added 'JoinByCode' button on new group view * generated --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> * fix(IT): added chreo code back + added original feedback star class back * generated * chore: revert change to it controller, use choreo record to determine which constructs are new --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> Co-authored-by: wcjord <32568597+wcjord@users.noreply.github.com> Co-authored-by: Sofanyas Genene <123987957+Sofanyas@users.noreply.github.com> Co-authored-by: ggurdin <ggurdin@gmail.com>
219 lines
7 KiB
Dart
219 lines
7 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
|
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
|
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
|
import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart';
|
|
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
|
import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart';
|
|
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
|
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
|
import 'package:fluffychat/widgets/matrix.dart';
|
|
import '../repo/similarity_repo.dart';
|
|
|
|
class AlternativeTranslator {
|
|
final Choreographer choreographer;
|
|
bool showAlternativeTranslations = false;
|
|
bool loadingAlternativeTranslations = false;
|
|
bool showTranslationFeedback = false;
|
|
String? userTranslation;
|
|
FeedbackKey? translationFeedbackKey;
|
|
List<String> translations = [];
|
|
SimilartyResponseModel? similarityResponse;
|
|
|
|
AlternativeTranslator(this.choreographer);
|
|
|
|
void clear() {
|
|
userTranslation = null;
|
|
showAlternativeTranslations = false;
|
|
loadingAlternativeTranslations = false;
|
|
showTranslationFeedback = false;
|
|
translationFeedbackKey = null;
|
|
translations = [];
|
|
similarityResponse = null;
|
|
}
|
|
|
|
double get _percentCorrectChoices {
|
|
final totalSteps = choreographer.choreoRecord.itSteps.length;
|
|
if (totalSteps == 0) return 0.0;
|
|
final int correctFirstAttempts = choreographer.itController.completedITSteps
|
|
.where(
|
|
(step) => !step.continuances.any(
|
|
(c) =>
|
|
c.level != ChoreoConstants.levelThresholdForGreen &&
|
|
c.wasClicked,
|
|
),
|
|
)
|
|
.length;
|
|
final double percentage = (correctFirstAttempts / totalSteps) * 100;
|
|
return percentage;
|
|
}
|
|
|
|
int get starRating {
|
|
final double percent = _percentCorrectChoices;
|
|
if (percent == 100) return 5;
|
|
if (percent >= 80) return 4;
|
|
if (percent >= 60) return 3;
|
|
if (percent >= 40) return 2;
|
|
if (percent > 0) return 1;
|
|
return 0;
|
|
}
|
|
|
|
Future<void> setTranslationFeedback() async {
|
|
try {
|
|
choreographer.startLoading();
|
|
translationFeedbackKey = FeedbackKey.loadingPleaseWait;
|
|
showTranslationFeedback = true;
|
|
userTranslation = choreographer.currentText;
|
|
|
|
final double percentCorrect = _percentCorrectChoices;
|
|
|
|
// Set feedback based on percentage
|
|
if (percentCorrect == 100) {
|
|
translationFeedbackKey = FeedbackKey.allCorrect;
|
|
} else if (percentCorrect >= 80) {
|
|
translationFeedbackKey = FeedbackKey.newWayAllGood;
|
|
} else {
|
|
translationFeedbackKey = FeedbackKey.othersAreBetter;
|
|
}
|
|
} catch (err, stack) {
|
|
if (err is! http.Response) {
|
|
ErrorHandler.logError(
|
|
e: err,
|
|
s: stack,
|
|
data: {
|
|
"sourceText": choreographer.itController.sourceText,
|
|
"currentText": choreographer.currentText,
|
|
"userL1": choreographer.l1LangCode,
|
|
"userL2": choreographer.l2LangCode,
|
|
"goldRouteTranslation":
|
|
choreographer.itController.goldRouteTracker.fullTranslation,
|
|
},
|
|
);
|
|
}
|
|
choreographer.errorService.setError(
|
|
ChoreoError(type: ChoreoErrorType.unknown, raw: err),
|
|
);
|
|
} finally {
|
|
choreographer.stopLoading();
|
|
}
|
|
}
|
|
|
|
List<OneConstructUse> get _itStepConstructs {
|
|
final metadata = ConstructUseMetaData(
|
|
roomId: choreographer.roomId,
|
|
timeStamp: DateTime.now(),
|
|
);
|
|
|
|
final List<OneConstructUse> constructs = [];
|
|
for (final step in choreographer.choreoRecord.itSteps) {
|
|
for (final continuance in step.continuances) {
|
|
final ConstructUseTypeEnum useType = continuance.wasClicked &&
|
|
continuance.level == ChoreoConstants.levelThresholdForGreen
|
|
? ConstructUseTypeEnum.corIt
|
|
: continuance.wasClicked
|
|
? ConstructUseTypeEnum.incIt
|
|
: ConstructUseTypeEnum.ignIt;
|
|
|
|
final tokens = continuance.tokens.where((t) => t.lemma.saveVocab);
|
|
constructs.addAll(
|
|
tokens.map(
|
|
(token) => OneConstructUse(
|
|
useType: useType,
|
|
lemma: token.lemma.text,
|
|
constructType: ConstructTypeEnum.vocab,
|
|
metadata: metadata,
|
|
category: token.pos,
|
|
form: token.text.content,
|
|
),
|
|
),
|
|
);
|
|
for (final token in tokens) {
|
|
constructs.add(
|
|
OneConstructUse(
|
|
useType: useType,
|
|
lemma: token.pos,
|
|
form: token.text.content,
|
|
category: "POS",
|
|
constructType: ConstructTypeEnum.morph,
|
|
metadata: metadata,
|
|
),
|
|
);
|
|
for (final entry in token.morph.entries) {
|
|
constructs.add(
|
|
OneConstructUse(
|
|
useType: useType,
|
|
lemma: entry.value,
|
|
form: token.text.content,
|
|
category: entry.key,
|
|
constructType: ConstructTypeEnum.morph,
|
|
metadata: metadata,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return constructs;
|
|
}
|
|
|
|
int countNewConstructs(ConstructTypeEnum type) {
|
|
final vocabUses = _itStepConstructs.where((c) => c.constructType == type);
|
|
final Map<ConstructIdentifier, int> constructPoints = {};
|
|
for (final use in vocabUses) {
|
|
constructPoints[use.identifier] ??= 0;
|
|
constructPoints[use.identifier] =
|
|
constructPoints[use.identifier]! + use.pointValue;
|
|
}
|
|
|
|
final constructListModel =
|
|
MatrixState.pangeaController.getAnalytics.constructListModel;
|
|
|
|
int newConstructCount = 0;
|
|
for (final entry in constructPoints.entries) {
|
|
final construct = constructListModel.getConstructUses(entry.key);
|
|
if (construct?.points == entry.value) {
|
|
newConstructCount++;
|
|
}
|
|
}
|
|
|
|
return newConstructCount;
|
|
}
|
|
|
|
String getDefaultFeedback(BuildContext context) {
|
|
final l10n = L10n.of(context);
|
|
switch (translationFeedbackKey) {
|
|
case FeedbackKey.allCorrect:
|
|
return l10n.perfectTranslation;
|
|
case FeedbackKey.newWayAllGood:
|
|
return l10n.greatJobTranslation;
|
|
case FeedbackKey.othersAreBetter:
|
|
if (_percentCorrectChoices >= 60) {
|
|
return l10n.goodJobTranslation;
|
|
}
|
|
if (_percentCorrectChoices >= 40) {
|
|
return l10n.makingProgress;
|
|
}
|
|
return l10n.keepPracticing;
|
|
case FeedbackKey.loadingPleaseWait:
|
|
return l10n.letMeThink;
|
|
case FeedbackKey.allDone:
|
|
return l10n.allDone;
|
|
default:
|
|
return l10n.loadingPleaseWait;
|
|
}
|
|
}
|
|
}
|
|
|
|
enum FeedbackKey {
|
|
allCorrect,
|
|
newWayAllGood,
|
|
othersAreBetter,
|
|
loadingPleaseWait,
|
|
allDone,
|
|
}
|
|
|
|
extension FeedbackKeyExtension on FeedbackKey {}
|