fix(reading_assistance): fixed a bug in scoring matches
This commit is contained in:
parent
c60b16dfe2
commit
88369ba8f7
8 changed files with 72 additions and 57 deletions
|
|
@ -1,8 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
abstract class AppConfig {
|
||||
// #Pangea
|
||||
|
|
@ -55,7 +53,8 @@ abstract class AppConfig {
|
|||
// static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||
static const Color primaryColor = Color(0xFF8560E0);
|
||||
static const Color primaryColorLight = Color(0xFFDBC9FF);
|
||||
static const Color secondaryColor = Color(0xFF41a2bc);
|
||||
// static const Color secondaryColor = Color(0xFF41a2bc);
|
||||
static const Color secondaryColor = Color.fromARGB(255, 253, 191, 1);
|
||||
static const Color activeToggleColor = Color(0xFF33D057);
|
||||
static const Color success = Color(0xFF33D057);
|
||||
static const Color warning = Color.fromARGB(255, 210, 124, 12);
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ abstract class FluffyThemes {
|
|||
seedColor: seed ??
|
||||
AppConfig.colorSchemeSeed ??
|
||||
Theme.of(context).colorScheme.primary,
|
||||
// primary: AppConfig.primaryColor,
|
||||
// secondary: AppConfig.gold,
|
||||
);
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
return ThemeData(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class InstructionsInlineTooltip extends StatefulWidget {
|
||||
final InstructionsEnum instructionsEnum;
|
||||
|
|
@ -103,7 +101,7 @@ class InstructionsInlineTooltipState extends State<InstructionsInlineTooltip>
|
|||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
color: Color.alphaBlend(
|
||||
Colors.black.withAlpha(70),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(70),
|
||||
AppConfig.gold,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
@ -23,6 +17,10 @@ import 'package:fluffychat/pangea/practice_activities/practice_record.dart';
|
|||
import 'package:fluffychat/pangea/practice_activities/practice_target.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/relevant_span_display_details.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
class PracticeActivityModel {
|
||||
List<PangeaToken> targetTokens;
|
||||
|
|
@ -95,9 +93,9 @@ class PracticeActivityModel {
|
|||
score: isCorrect ? 1 : 0,
|
||||
);
|
||||
|
||||
debugPrint(
|
||||
"onMultipleChoiceSelect: ${choice.form} ${responseUseType(choice)}",
|
||||
);
|
||||
// debugPrint(
|
||||
// "onMultipleChoiceSelect: ${choice.form} ${responseUseType(choice)}",
|
||||
// );
|
||||
|
||||
MatrixState.pangeaController.putAnalytics.setState(
|
||||
AnalyticsStream(
|
||||
|
|
@ -105,7 +103,7 @@ class PracticeActivityModel {
|
|||
roomId: event?.room.id,
|
||||
constructs: [
|
||||
OneConstructUse(
|
||||
useType: responseUseType(choice)!,
|
||||
useType: practiceTarget.record.responses.last.useType(activityType),
|
||||
lemma: choice.form.cId.lemma,
|
||||
constructType: choice.form.cId.type,
|
||||
metadata: ConstructUseMetaData(
|
||||
|
|
@ -133,8 +131,12 @@ class PracticeActivityModel {
|
|||
) {
|
||||
// the user has already selected this choice
|
||||
// so we don't want to record it again
|
||||
if (practiceTarget.record.hasTextResponse(choice.choiceContent) ||
|
||||
if (practiceTarget.record.alreadyHasMatchResponse(
|
||||
token.vocabConstructID,
|
||||
choice.choiceContent,
|
||||
) ||
|
||||
isComplete) {
|
||||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -144,8 +146,12 @@ class PracticeActivityModel {
|
|||
(answer) => answer.toLowerCase() == choice.choiceContent.toLowerCase(),
|
||||
);
|
||||
} else if (matchContent != null) {
|
||||
isCorrect = matchContent!.matchInfo[token.vocabForm]!
|
||||
.contains(choice.choiceContent);
|
||||
// we check to see if it's in the list of acceptable answers
|
||||
// rather than if the vocabForm is the same because an emoji
|
||||
// could be in multiple constructs so there could be multiple answers
|
||||
final answers = matchContent!.matchInfo[token.vocabForm];
|
||||
debugger(when: answers == null && kDebugMode);
|
||||
isCorrect = answers!.contains(choice.choiceContent);
|
||||
} else {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -156,11 +162,11 @@ class PracticeActivityModel {
|
|||
return;
|
||||
}
|
||||
|
||||
// NOTE: the response is associated with the contructId of the choice, not the selected token
|
||||
// NOTE: the response is associated with the contructId of the selected token, not the choice
|
||||
// example: the user selects the word "cat" to match with the emoji 🐶
|
||||
// the response is associated with correct word "dog", not the word "cat"
|
||||
// the response is associated with incorrect word "cat", not the word "dog"
|
||||
practiceTarget.record.addResponse(
|
||||
cId: choice.form.cId,
|
||||
cId: token.vocabConstructID,
|
||||
text: choice.choiceContent,
|
||||
target: practiceTarget,
|
||||
score: isCorrect ? 1 : 0,
|
||||
|
|
@ -174,15 +180,16 @@ class PracticeActivityModel {
|
|||
roomId: event?.room.id,
|
||||
constructs: [
|
||||
OneConstructUse(
|
||||
useType: responseUseType(choice)!,
|
||||
lemma: choice.form.cId.lemma,
|
||||
constructType: choice.form.cId.type,
|
||||
useType:
|
||||
practiceTarget.record.responses.last.useType(activityType),
|
||||
lemma: token.lemma.text,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: event?.room.id,
|
||||
timeStamp: DateTime.now(),
|
||||
eventId: event?.eventId,
|
||||
),
|
||||
category: choice.form.cId.category,
|
||||
category: token.pos,
|
||||
// in the case of a wrong answer, the cId doesn't match the token
|
||||
form: token.text.content,
|
||||
),
|
||||
|
|
@ -226,27 +233,18 @@ class PracticeActivityModel {
|
|||
/// if null, it means the user has not yet responded with that choice
|
||||
bool? wasCorrectMatch(PracticeChoice choice) {
|
||||
for (final response in practiceTarget.record.responses) {
|
||||
if (response.cId == choice.form.cId && response.isCorrect) {
|
||||
if (response.text == choice.choiceContent && response.isCorrect) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (final response in practiceTarget.record.responses) {
|
||||
if (response.cId == choice.form.cId) {
|
||||
if (response.text == choice.choiceContent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstructUseTypeEnum? responseUseType(PracticeChoice choice) {
|
||||
for (final response in practiceTarget.record.responses) {
|
||||
if (response.cId == choice.form.cId) {
|
||||
return response.useType(activityType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PracticeRecord get record => practiceTarget.record;
|
||||
|
||||
PracticeTarget get practiceTarget => PracticeTarget(
|
||||
|
|
|
|||
|
|
@ -2,12 +2,6 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/network/requests.dart';
|
||||
|
|
@ -25,6 +19,10 @@ import 'package:fluffychat/pangea/practice_activities/practice_activity_model.da
|
|||
import 'package:fluffychat/pangea/practice_activities/word_focus_listening_generator.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// Represents an item in the completion cache.
|
||||
class _RequestCacheItem {
|
||||
|
|
@ -173,7 +171,6 @@ class PracticeRepo {
|
|||
// TODO resolve some wierdness here whereby the activity can be null but then... it's not
|
||||
final eventCompleter = Completer<PracticeActivityEvent?>();
|
||||
|
||||
debugPrint('Activity generated: ${res.activity.toJson()}');
|
||||
if (event != null) {
|
||||
_sendAndPackageEvent(res.activity, event).then((event) {
|
||||
eventCompleter.complete(event);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/constructs/construct_form.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_choice.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PracticeMatchActivity {
|
||||
/// The constructIdenfifiers involved in the activity
|
||||
|
|
@ -13,6 +13,11 @@ class PracticeMatchActivity {
|
|||
PracticeMatchActivity({
|
||||
required this.matchInfo,
|
||||
}) {
|
||||
for (final ith in matchInfo.entries) {
|
||||
debugPrint(
|
||||
'Construct: ${ith.key}, Forms: ${ith.value}',
|
||||
);
|
||||
}
|
||||
// if there are multiple forms for a construct, pick one to display
|
||||
// each cosntruct will have ~3 forms
|
||||
// sometimes a form could be in multiple constructs
|
||||
|
|
@ -21,13 +26,17 @@ class PracticeMatchActivity {
|
|||
// either from that construct's options, or returning to the previous construct
|
||||
// and picking a different form from there
|
||||
for (final ith in matchInfo.entries) {
|
||||
for (final acceptableAnswer in ith.value) {
|
||||
for (int i = 0; i < ith.value.length; i++) {
|
||||
final String acceptableAnswer = ith.value[i];
|
||||
if (!choices
|
||||
.any((element) => element.choiceContent == acceptableAnswer)) {
|
||||
choices.add(
|
||||
PracticeChoice(choiceContent: acceptableAnswer, form: ith.key),
|
||||
);
|
||||
break;
|
||||
debugPrint(
|
||||
'Added choice: ${choices.last.choiceContent} for form: ${choices.last.form.form}',
|
||||
);
|
||||
i = ith.value.length; // break out of the loop
|
||||
}
|
||||
// TODO: if none found, we can probably pick a different form for the other one
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
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';
|
||||
|
|
@ -16,6 +14,7 @@ import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
|||
import 'package:fluffychat/pangea/practice_activities/practice_activity_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record_repo.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_target.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class PracticeRecord {
|
||||
late DateTime createdAt;
|
||||
|
|
@ -72,6 +71,15 @@ class PracticeRecord {
|
|||
return responses.any((element) => element.text == text);
|
||||
}
|
||||
|
||||
bool alreadyHasMatchResponse(
|
||||
ConstructIdentifier cId,
|
||||
String text,
|
||||
) {
|
||||
return responses.any(
|
||||
(element) => element.cId == cId && element.text == text,
|
||||
);
|
||||
}
|
||||
|
||||
/// [target] needed for saving the record, little funky
|
||||
/// [cId] identifies the construct in the case of match activities which have multiple
|
||||
/// [text] is the user's response
|
||||
|
|
@ -111,6 +119,7 @@ class PracticeRecord {
|
|||
score: score,
|
||||
),
|
||||
);
|
||||
debugPrint("responses: ${responses.map((r) => r.toJson())}");
|
||||
|
||||
PracticeRecordRepo.save(target, this);
|
||||
} catch (e) {
|
||||
|
|
@ -156,6 +165,9 @@ class PracticeRecord {
|
|||
}
|
||||
|
||||
class ActivityRecordResponse {
|
||||
/// the cId of the construct that the user attached their response to
|
||||
/// ie. in the "I like the dog" if the user erroneously attaches a dog emoji to the word like
|
||||
/// then the cId is that of 'like
|
||||
ConstructIdentifier cId;
|
||||
// the user's response
|
||||
// has nullable string, nullable audio bytes, nullable image bytes, and timestamp
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_record_repo.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Picks which tokens to do activities on and what types of activities to do
|
||||
/// Caches result so that we don't have to recompute it
|
||||
|
|
@ -90,7 +89,8 @@ class PracticeTarget {
|
|||
}
|
||||
|
||||
return tokens.every(
|
||||
(t) => record.responses.any((res) => res.cId == t.vocabConstructID),
|
||||
(t) => record.responses
|
||||
.any((res) => res.cId == t.vocabConstructID && res.isCorrect),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue