You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fluffychat/lib/pangea/choreographer/controllers/alternative_translator.dart

220 lines
7.0 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 {}