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