Skip to content

Commit

Permalink
Merge pull request #49 from seochan99/feature/translate
Browse files Browse the repository at this point in the history
✨ Feat: language, chart
  • Loading branch information
bunju20 authored Feb 21, 2024
2 parents 6626366 + 46a3e24 commit ae55e6a
Show file tree
Hide file tree
Showing 10 changed files with 656 additions and 482 deletions.
11 changes: 11 additions & 0 deletions lib/languages.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:get/get.dart';

class Languages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'ko_KR': {'title': '제목'},
'en_US': {'title': 'title'},
'ja_JP': {'title': '題名'},
'vi_VN': {'title': 'Tiêu đề'},
};
}
23 changes: 10 additions & 13 deletions lib/viewModels/record/record_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ import 'package:path_provider/path_provider.dart';

class RecordViewModel extends GetxController {
final FlutterSoundRecorder _audioRecorder = FlutterSoundRecorder();
bool _isRecorderInitialized = false; // 녹음기 초기화 여부 : 파일
bool _isRecorderInitialized = false;
final RxBool isRecording = false.obs;
RxString audioFilePath = ''.obs;
RxDouble loudness = 0.0.obs; // Reactive variable for loudness

final RxMap<String, dynamic> response =
<String, dynamic>{}.obs; // Specify the types

@override
void onInit() {
_requestPermission();
_audioRecorder.openRecorder(); // Initialize recorder
_audioRecorder.onProgress!.listen((e) {
loudness.value = e.decibels! / 160; // Example: Normalize decibels
});
super.onInit();
}

Expand Down Expand Up @@ -65,18 +71,13 @@ class RecordViewModel extends GetxController {
}

Future<void> sendTextAndAudio(String content, int type) async {

isRecording.value ? await _stopRecording() : await _startRecording();
update();
if(isRecording.value == true) {
if (isRecording.value == true) {
return;
}
print("들어오긴 함?");
String url =
'${dotenv.env['API_URL']!}/study/${type == 0 ? 'syllable' : (type == 1 ? 'word' : 'sentence')}';


print(audioFilePath.value);
if (audioFilePath.value.isEmpty) {
return;
}
Expand All @@ -93,14 +94,10 @@ class RecordViewModel extends GetxController {
final jsonResponse = json.decode(respStr);
//
this.response.value = jsonResponse;
print(jsonResponse);
} else {
print('Failed to upload');
}
} catch (e) {}
} else {}
} catch (_) {}
}


@override
void onClose() {
_audioRecorder.closeRecorder();
Expand Down
46 changes: 46 additions & 0 deletions lib/views/word/widget/fail_word_dialog_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:earlips/utilities/style/color_styles.dart';
import 'package:earlips/viewModels/word/word_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

Future<dynamic> FailWordDialogWidget(
WordViewModel wordViewModel, PageController pageController) {
return Get.dialog(
AlertDialog(
title: const Text('학습 실패'),
content: const Text('다시 한번 녹음해주세요.'),
backgroundColor: ColorSystem.white,
surfaceTintColor: ColorSystem.white,
actions: [
ElevatedButton(
onPressed: () async {
Get.back();
},
child: const Text('다시하기'),
),
ElevatedButton(
onPressed: () async {
// 마지막 단어가 아닐 경우 뒤로가기, 마지막 단어일 경우 홈으로 이동
wordViewModel.currentIndex.value < wordViewModel.wordList.length - 1
? Get.back()
: Get.offAllNamed('/');
// 다음 단어로 넘어가기
if (wordViewModel.currentIndex.value <
wordViewModel.wordList.length - 1) {
pageController.animateToPage(
wordViewModel.currentIndex.value + 1,
duration: const Duration(milliseconds: 300),
curve: Curves.ease,
);

// currentIndex 증가
wordViewModel.currentIndex.value =
wordViewModel.currentIndex.value + 1;
}
},
child: const Text('다음 단어'),
),
],
),
);
}
35 changes: 35 additions & 0 deletions lib/views/word/widget/highlight_mistake_text_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';

class HighlightMistakesTextWidget extends StatelessWidget {
final List<dynamic> userWords; // 사용자가 발음한 단어 리스트
final List<dynamic> wrongIndices; // 잘못 발음한 단어의 인덱스 리스트

const HighlightMistakesTextWidget({
super.key,
required this.userWords,
required this.wrongIndices,
});

@override
Widget build(BuildContext context) {
return wrongIndices[0] == -1
? const Text("틀린단어 없음")
: RichText(
text: TextSpan(
children: userWords.asMap().entries.map((entry) {
int idx = entry.key;
String word = entry.value;
bool isWrong = wrongIndices.contains(idx);
return TextSpan(
text: "$word ", // 단어와 공백을 포함시킵니다.
style: TextStyle(
color: isWrong
? Colors.red
: Colors.black, // 잘못된 부분은 빨간색으로, 그 외는 검정색으로 표시
),
);
}).toList(),
),
);
}
}
194 changes: 194 additions & 0 deletions lib/views/word/widget/sentence_alert_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import 'package:earlips/utilities/style/color_styles.dart';
import 'package:earlips/viewModels/record/record_viewmodel.dart';
import 'package:earlips/viewModels/word/word_viewmodel.dart';
import 'package:earlips/views/word/widget/highlight_mistake_text_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

Future<dynamic> SentenceAlertWidget(RecordViewModel model,
WordViewModel wordViewModel, PageController pageController) {
return Get.dialog(
AlertDialog(
title: const Text('문장 테스트 결과',
style: TextStyle(
color: ColorSystem.black,
fontSize: 20,
)),
surfaceTintColor: ColorSystem.white,
backgroundColor: ColorSystem.white,
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'문장',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text(
'${model.response['sentence_word'] != null ? model.response['sentence_word'].join(" ") : "다시 녹음해주세요"}',
style: const TextStyle(
color: ColorSystem.black,
fontSize: 14,
),
)
],
),
const SizedBox(height: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'사용자 발음',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
HighlightMistakesTextWidget(
userWords: model.response['user_word'] ?? [],
wrongIndices: model.response['wrong'] ?? [-1],
),
],
),
const SizedBox(height: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'틀린 부분',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text(
'${model.response['wrong'] != null && model.response['wrong'][0] != -1 ? model.response['wrong'].join(", ") : "알 수 없음"} 번째 단어',
style: const TextStyle(
color: ColorSystem.black,
fontSize: 14,
),
)
],
),
const SizedBox(height: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'볼륨',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text('${model.response['loudness'] ?? '알 수 없음'}'),
],
),
const SizedBox(height: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'변동성',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text(
model.response['variance'] == null
? "알 수 없음"
: (model.response['variance'] == 1 ? "일정함" : "변동 폭 큼"),
style: const TextStyle(
color: ColorSystem.black,
fontSize: 14,
),
)
],
),
const SizedBox(height: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'속도',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Text(
_getSpeedDescription(model.response['speed'] ?? 1),
style: const TextStyle(
color: ColorSystem.black,
fontSize: 14,
),
),
],
)
],
),
),
actions: <Widget>[
TextButton(
child: const Text(
'다음',
style: TextStyle(
color: ColorSystem.black,
fontSize: 16,
),
),
onPressed: () async {
// 다음으로 넘어가는 코드
await wordViewModel.markWordAsDone(wordViewModel
.wordList[wordViewModel.currentIndex.value].wordCard);
wordViewModel.currentIndex.value < wordViewModel.wordList.length - 1
? Get.back()
: Get.offAllNamed('/');

// 다음 단어로 넘어가기
if (wordViewModel.currentIndex.value <
wordViewModel.wordList.length - 1) {
pageController.animateToPage(
wordViewModel.currentIndex.value + 1,
duration: const Duration(milliseconds: 300),
curve: Curves.ease,
);
// currentIndex 증가
wordViewModel.currentIndex.value =
wordViewModel.currentIndex.value + 1;
}
},
),
],
),
);
}

String _getSpeedDescription(double speed) {
switch (speed) {
case 0:
return '엄청 느림';
case 0.5:
return '느림';
case 1:
return '평범';
case 1.5:
return '약간 빠름';
case 2:
return '완전 빠름';
default:
return '알 수 없음'; // 속도 값이 주어진 범위에 없는 경우
}
}
Loading

0 comments on commit ae55e6a

Please sign in to comment.