admin
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
This commit is contained in:
parent
4751594b9a
commit
5e3061165f
5 changed files with 62 additions and 9 deletions
|
|
@ -12,6 +12,12 @@ class InputButtonsQuestionGenerator implements QuestionGenerator {
|
||||||
final Random random;
|
final Random random;
|
||||||
final Set<InputButtonsQuestionType>? possibleTypes;
|
final Set<InputButtonsQuestionType>? possibleTypes;
|
||||||
|
|
||||||
|
// UUID regex pattern (same as in test_manager.dart)
|
||||||
|
static final _uuidRegex = RegExp(
|
||||||
|
r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
|
||||||
|
caseSensitive: false,
|
||||||
|
);
|
||||||
|
|
||||||
InputButtonsQuestionGenerator(
|
InputButtonsQuestionGenerator(
|
||||||
this.data, {
|
this.data, {
|
||||||
this.seed,
|
this.seed,
|
||||||
|
|
@ -36,6 +42,17 @@ class InputButtonsQuestionGenerator implements QuestionGenerator {
|
||||||
return types[random.nextInt(types.length)];
|
return types[random.nextInt(types.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a string is a valid UUID
|
||||||
|
bool _isUuid(String value) => _uuidRegex.hasMatch(value.trim());
|
||||||
|
|
||||||
|
/// Gets audio UUID from answerItem.audio if it's a valid UUID, otherwise returns null
|
||||||
|
/// This allows using UUID from MinIO instead of text-based audio identifiers
|
||||||
|
String? _getAudioUuid(TestDataItem answerItem) {
|
||||||
|
final audioValue = answerItem.audio;
|
||||||
|
if (audioValue == null || audioValue.trim().isEmpty) return null;
|
||||||
|
return _isUuid(audioValue) ? audioValue.trim() : null;
|
||||||
|
}
|
||||||
|
|
||||||
Future<InputButtonsTestQuestionBody> inputButtonsTestQuestion(
|
Future<InputButtonsTestQuestionBody> inputButtonsTestQuestion(
|
||||||
TestDataItem answerItem, {
|
TestDataItem answerItem, {
|
||||||
InputButtonsQuestionType? type,
|
InputButtonsQuestionType? type,
|
||||||
|
|
@ -58,7 +75,8 @@ class InputButtonsQuestionGenerator implements QuestionGenerator {
|
||||||
|
|
||||||
String? questionAudio = null;
|
String? questionAudio = null;
|
||||||
if (questionType.audioQuestion) {
|
if (questionType.audioQuestion) {
|
||||||
questionAudio = 'es-ES_${answerItem.audio}';
|
// Use UUID from MinIO if available, otherwise null
|
||||||
|
questionAudio = _getAudioUuid(answerItem);
|
||||||
} else if (withAudio) {
|
} else if (withAudio) {
|
||||||
// nothing to fo here
|
// nothing to fo here
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ class SimpleQuestionGenerator implements QuestionGenerator {
|
||||||
final Random random;
|
final Random random;
|
||||||
final Set<SimpleQuestionType>? possibleTypes;
|
final Set<SimpleQuestionType>? possibleTypes;
|
||||||
|
|
||||||
|
// UUID regex pattern (same as in test_manager.dart)
|
||||||
|
static final _uuidRegex = RegExp(
|
||||||
|
r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
|
||||||
|
caseSensitive: false,
|
||||||
|
);
|
||||||
|
|
||||||
SimpleQuestionGenerator(
|
SimpleQuestionGenerator(
|
||||||
this.data, {
|
this.data, {
|
||||||
this.seed,
|
this.seed,
|
||||||
|
|
@ -36,6 +42,17 @@ class SimpleQuestionGenerator implements QuestionGenerator {
|
||||||
return types[random.nextInt(types.length)];
|
return types[random.nextInt(types.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a string is a valid UUID
|
||||||
|
bool _isUuid(String value) => _uuidRegex.hasMatch(value.trim());
|
||||||
|
|
||||||
|
/// Gets audio UUID from answerCard.audio if it's a valid UUID, otherwise returns null
|
||||||
|
/// This allows using UUID from MinIO instead of text-based audio identifiers
|
||||||
|
String? _getAudioUuid(TestDataItem answerCard) {
|
||||||
|
final audioValue = answerCard.audio;
|
||||||
|
if (audioValue == null || audioValue.trim().isEmpty) return null;
|
||||||
|
return _isUuid(audioValue) ? audioValue.trim() : null;
|
||||||
|
}
|
||||||
|
|
||||||
Future<SimpleTestQuestionBody> simpleTestQuestion(
|
Future<SimpleTestQuestionBody> simpleTestQuestion(
|
||||||
TestDataItem answerCard, {
|
TestDataItem answerCard, {
|
||||||
SimpleQuestionType? type,
|
SimpleQuestionType? type,
|
||||||
|
|
@ -57,14 +74,18 @@ class SimpleQuestionGenerator implements QuestionGenerator {
|
||||||
String? questionAudio = null;
|
String? questionAudio = null;
|
||||||
if (questionType.audioQuestion) {
|
if (questionType.audioQuestion) {
|
||||||
if (questionType.translationAnswers || questionType.imagesAnswers) {
|
if (questionType.translationAnswers || questionType.imagesAnswers) {
|
||||||
questionAudio = 'es-ES_${answerCard.audio}';
|
// Use UUID from MinIO if available, otherwise null
|
||||||
|
questionAudio = _getAudioUuid(answerCard);
|
||||||
}
|
}
|
||||||
} else if (withAudio) {
|
} else if (withAudio) {
|
||||||
if (questionText != null && questionType.originalQuestion) {
|
if (questionText != null && questionType.originalQuestion) {
|
||||||
questionAudio = 'es-ES_$questionText';
|
// For original questions with text, audio is handled separately
|
||||||
|
// Use UUID if available, otherwise null
|
||||||
|
questionAudio = _getAudioUuid(answerCard);
|
||||||
} else if (questionType.translationAnswers ||
|
} else if (questionType.translationAnswers ||
|
||||||
questionType.imagesAnswers) {
|
questionType.imagesAnswers) {
|
||||||
questionAudio = 'es-ES_${answerCard.audio}';
|
// Use UUID from MinIO if available, otherwise null
|
||||||
|
questionAudio = _getAudioUuid(answerCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final answers = [answerCard, ...otherCards]..shuffle();
|
final answers = [answerCard, ...otherCards]..shuffle();
|
||||||
|
|
|
||||||
|
|
@ -677,15 +677,29 @@ class TestManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creation test data
|
// Create creation test data
|
||||||
final testDataItems = cards.map((card) {
|
// Get voices for all cards to use UUID from MinIO instead of text
|
||||||
|
final testDataItems = await Future.wait(cards.map((card) async {
|
||||||
|
// Get voices for this card
|
||||||
|
final voices = await _db.packDao.getCardVoices(card.id.toString());
|
||||||
|
|
||||||
|
// Use first voice's voiceUrl if it's a valid UUID, otherwise null
|
||||||
|
String? audioUuid;
|
||||||
|
if (voices.isNotEmpty) {
|
||||||
|
final voiceUrl = voices.first.voiceUrl.trim();
|
||||||
|
// Check if voiceUrl is a valid UUID (object ID in MinIO)
|
||||||
|
if (_isUuid(voiceUrl)) {
|
||||||
|
audioUuid = voiceUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TestDataItem(
|
return TestDataItem(
|
||||||
id: card.id.toString(),
|
id: card.id.toString(),
|
||||||
original: card.original,
|
original: card.original,
|
||||||
translation: card.translation,
|
translation: card.translation,
|
||||||
image: card.image,
|
image: card.image,
|
||||||
audio: card.original, // Use original as audio
|
audio: audioUuid, // Use UUID from MinIO if available
|
||||||
);
|
);
|
||||||
}).toList();
|
}));
|
||||||
|
|
||||||
final creationTestData = CreationTestData(
|
final creationTestData = CreationTestData(
|
||||||
items: testDataItems,
|
items: testDataItems,
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ class TestsStateManager extends StateManager<TestsState> {
|
||||||
questions.add(GameQuestion.multipleChoice(
|
questions.add(GameQuestion.multipleChoice(
|
||||||
MultipleChoiceQuestion(
|
MultipleChoiceQuestion(
|
||||||
id: 'q_${questions.length}',
|
id: 'q_${questions.length}',
|
||||||
question: question.text ?? '',
|
question: question.w ?? '',
|
||||||
image: question.imageUrl ?? question.image, // Use presigned URL if available
|
image: question.imageUrl ?? question.image, // Use presigned URL if available
|
||||||
audio: question.audio,
|
audio: question.audio,
|
||||||
options: options, // Keep for backward compatibility
|
options: options, // Keep for backward compatibility
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class AnswerOptions extends StatelessWidget {
|
||||||
// Adjust aspect ratio for image buttons (they need more space)
|
// Adjust aspect ratio for image buttons (they need more space)
|
||||||
final hasImages = hasOptionItems &&
|
final hasImages = hasOptionItems &&
|
||||||
question.optionItems.any((item) => item.image != null);
|
question.optionItems.any((item) => item.image != null);
|
||||||
final childAspectRatio = hasImages ? 2.5 : 4.0;
|
final childAspectRatio = hasImages ? 1.1 : 4.0;
|
||||||
|
|
||||||
return GridView.builder(
|
return GridView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue