Skip to content

Commit

Permalink
Merge pull request #35 from bunju20/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
seochan99 authored Feb 20, 2024
2 parents 6318fb4 + b9e2fa9 commit 80309a9
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 67 deletions.
2 changes: 2 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,5 @@ flutter {
}

dependencies {}

apply plugin: 'com.google.gms.google-services'
43 changes: 23 additions & 20 deletions lib/viewModels/script/analyze_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import 'package:flutter/foundation.dart';

import 'package:flutter_sound/flutter_sound.dart';
import 'package:http/http.dart' as http;
import 'dart:convert'; // JSON 데이터를 다루기 위해 필요
class AnalyzeViewModel with ChangeNotifier {
List<String> userWord = [];
List<String> userSenten = [];
List<int> wrongWordIndexes = [];
List<double> wrongFastIndexes = [];

final List<String> userWord = [
"가", "나", "다", "어쩌구", "저쩌구", "입니다", "나는", "매일", "조깅을", "합니다",
"플러터로", "앱", "개발을", "배우고", "있어요", "이것은", "더미", "텍스트입니다",
"데이터를", "시각화하는", "것은", "중요합니다"
];
final List<String> userSenten = [
"가 나 다 어쩌구 저쩌구 입니다.",
"나는 매일 조깅을 합니다.",
"플러터로 앱 개발을 배우고 있어요.",
"이것은 더미 텍스트입니다.",
"데이터를 시각화하는 것은 중요합니다.",
];
final List<int> wrongWordIndexes = [2, 14]; // "다", "앱"을 가리킴
final List<int> wrongFastIndexes = [1, 3]; // 두 번째와 네 번째 문장을 가리킴
void updateData(Map<String, dynamic> data) {
userWord = List<String>.from(data['user_word'] as List<dynamic>? ?? []);
userSenten = List<String>.from(data['user_sentence'] as List<dynamic>? ?? []);
wrongWordIndexes = List<int>.from(data['wrong'] as List<dynamic>? ?? []);
wrongFastIndexes = (data['speed'] as List<dynamic>? ?? []).map((e) {

// ViewModel 초기화
AnalyzeViewModel() {
// 필요한 초기화 로직 추가
if (e is double) {
return e;
} else if (e is int) {
return e.toDouble();
} else {
// 로그 출력 또는 오류 처리
print("Warning: Invalid type in 'speed' list, defaulting to 0.0");
return 0.0; // 기본값
}
}).toList();
notifyListeners(); // 데이터가 업데이트되면 리스너들에게 알립니다.
}

// 여기에 필요한 기능을 추가하세요.
}
38 changes: 25 additions & 13 deletions lib/viewModels/script/create_script_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:speech_to_text/speech_to_text.dart' as stt;
Expand All @@ -8,6 +10,8 @@ import 'dart:async';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:earlips/views/script/analyze_screen.dart';
import 'package:earlips/viewModels/script/analyze_viewmodel.dart';


class CreateScriptViewModel extends ChangeNotifier {
bool isRecording = false;
Expand All @@ -28,6 +32,7 @@ class CreateScriptViewModel extends ChangeNotifier {
}

void _init() async {
Get.put(AnalyzeViewModel());
await requestPermission();
speechToText.initialize(
onError: (val) => print('Error: $val'),
Expand Down Expand Up @@ -73,33 +78,42 @@ class CreateScriptViewModel extends ChangeNotifier {


Future<void> sendTextAndAudio() async {
String url = 'https://heheds.free.beeceptor.com';
String url = 'https://962554f7-5348-4141-a3df-1a50c06b79b5-00-15gg2xcmiy7a0.sisko.replit.dev/upload';
String textToSend = writedTextController.text;
if (audioFilePath == null) {
if (audioFilePath.isEmpty) {
print('Audio file is not available.');
return;
}

try {
var request = http.MultipartRequest('POST', Uri.parse(url))
..fields['text'] = textToSend // 텍스트 데이터 추가
..files.add(await http.MultipartFile.fromPath(
'audio', // 서버에서 음성 파일을 식별하는 필드명
audioFilePath,
));
..fields['text'] = textToSend
..files.add(await http.MultipartFile.fromPath('audio', audioFilePath));

var response = await request.send();
if (response.statusCode == 200) {
print('Data and audio sent successfully');
final respStr = await response.stream.bytesToString();
final jsonResponse = json.decode(respStr);
print('Server response: $respStr');

if (jsonResponse != null && jsonResponse['data'] != null) {
final analyzeViewModel = Get.find<AnalyzeViewModel>();
analyzeViewModel.updateData(jsonResponse['data']);
Get.to(() => AnalyzeScreen()); // AnalyzeScreen으로 이동
} else {
print('Received null or invalid data from the server.');
}
} else {
print('Failed to send data and audio');
print('Failed to send data and audio. Status code: ${response.statusCode}');
}
} catch (e) {
print(e.toString());
}
}




void _handleStatus(String status) {
if (handDone) return;
if (status == 'done') {
Expand Down Expand Up @@ -149,11 +163,9 @@ class CreateScriptViewModel extends ChangeNotifier {
notifyListeners();
}

void complete() {
void complete() async {
print("완료버튼 눌렀습니다.");
sendTextAndAudio(); // 텍스트와 오디오 파일 전송
//스크린을 이동 analyze_screen으로 이동하는 코드
Get.to(() => AnalyzeScreen());
await sendTextAndAudio(); // 비동기 호출로 수정
}


Expand Down
84 changes: 50 additions & 34 deletions lib/views/script/analyze_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:earlips/viewModels/script/analyze_viewmodel.dart';
import '../../utilities/app_routes.dart';



class AnalyzeScreen extends StatefulWidget {
AnalyzeScreen({Key? key}) : super(key: key);
@override
_AnalyzeScreenState createState() => _AnalyzeScreenState();
}

class _AnalyzeScreenState extends State<AnalyzeScreen> {
late AnalyzeViewModel viewModel;

@override
void initState() {
super.initState();
viewModel = Get.put(AnalyzeViewModel()); // 여기서 viewModel을 등록
print(viewModel.userSenten);
}

@override
Widget build(BuildContext context) {
Expand All @@ -36,13 +43,13 @@ class _AnalyzeScreenState extends State<AnalyzeScreen> {
width: Get.width - 40,
height: Get.height * 0.2,
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(10.0), // 내부 여백을 추가합니다.
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Colors.white, // 배경색을 지정합니다.
borderRadius: BorderRadius.circular(15.0), // 테두리 둥글기를 지정합니다.
border: Border.all(color: Colors.white), // 테두리 색상을 지정합니다. 필요에 따라 변경 가능합니다.
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Colors.white),
),
child: _TopText(),
child: _TopText(), // 이 부분은 상태를 표시하지 않으므로 그대로 유지합니다.
),
Stack(
children: [
Expand All @@ -51,15 +58,14 @@ class _AnalyzeScreenState extends State<AnalyzeScreen> {
width: Get.width - 40,
height: Get.height * 0.5,
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(10.0), // 내부 여백을 추가합니다.
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Colors.white, // 배경색을 지정합니다.
borderRadius: BorderRadius.circular(15.0), // 테두리 둥글기를 지정합니다.
border: Border.all(color: Colors.white), // 테두리 색상을 지정합니다. 필요에 따라 변경 가능합니다.
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Colors.white),
),
child: TextStylingWidget(),
child: TextStylingWidget(viewModel: viewModel), // viewModel을 전달합니다.
),

],
),
],
Expand All @@ -68,13 +74,12 @@ class _AnalyzeScreenState extends State<AnalyzeScreen> {
floatingActionButton: Container(
width: Get.width,
alignment: Alignment.bottomCenter,

child: FloatingActionButton(
onPressed: () {
Get.toNamed(Routes.HOME);
},
child: Icon(Icons.home), // 홈 아이콘 사용
tooltip: '홈으로', // 롱 프레스 시 표시되는 텍스트
child: Icon(Icons.home),
tooltip: '홈으로',
),
),
),
Expand All @@ -83,7 +88,9 @@ class _AnalyzeScreenState extends State<AnalyzeScreen> {
}

class TextStylingWidget extends StatelessWidget {
final AnalyzeViewModel model = Get.put(AnalyzeViewModel());
final AnalyzeViewModel viewModel; // viewModel을 받기 위한 생성자 파라미터를 추가합니다.

TextStylingWidget({required this.viewModel}); // 생성자를 통해 viewModel을 초기화합니다.

@override
Widget build(BuildContext context) {
Expand All @@ -98,32 +105,46 @@ class TextStylingWidget extends StatelessWidget {
);
}


List<TextSpan> _buildTextSpans() {
List<TextSpan> spans = [];
int globalWordIndex = 0; // 전체 단어에 대한 인덱스를 추적합니다.
int globalWordIndex = 0;

for (int i = 0; i < model.userSenten.length; i++) {
final List<String> words = model.userSenten[i].split(' ');
for (int i = 0; i < viewModel.userSenten.length; i++) {
final List<String> words = viewModel.userSenten[i].split(' ');
List<TextSpan> wordSpans = [];

for (String word in words) {
final bool isWrongWord = model.wrongWordIndexes.contains(globalWordIndex);
final bool isWrongWord = viewModel.wrongWordIndexes.contains(globalWordIndex);
wordSpans.add(TextSpan(
text: "$word ",
style: TextStyle(
color: isWrongWord ? Colors.red : Colors.black,
),
));
globalWordIndex++; // 각 단어를 처리할 때마다 전체 단어 인덱스를 증가시킵니다.
globalWordIndex++;
}

// `wrongFastIndexes`의 값에 따라 밑줄 색상을 결정합니다.
Color underlineColor = Colors.white; // 기본값은 투명색입니다.
if (viewModel.wrongFastIndexes[i] < 1) {
underlineColor = Colors.purple; // 1미만인 경우 보라색 밑줄
} else if (viewModel.wrongFastIndexes[i] > 1) {
underlineColor = Colors.red; // 1초과인 경우 빨간색 밑줄
}

spans.add(TextSpan(
children: wordSpans,
style: TextStyle(
decoration: model.wrongFastIndexes.contains(i) ? TextDecoration.underline : TextDecoration.none,
decoration: viewModel.wrongFastIndexes[i] != 0 ? TextDecoration.underline : TextDecoration.none,
decorationColor: underlineColor, // 밑줄 색상을 지정합니다.
decorationStyle: TextDecorationStyle.solid,
decorationThickness: 3.0,
//밑줄을 밑으로 내리기 위한 값

),
));
spans.add(TextSpan(text: "\n")); // 문장 사이에 줄바꿈 추가
spans.add(TextSpan(text: "\n"));
}

return spans;
Expand Down Expand Up @@ -166,21 +187,16 @@ class _TopText extends StatelessWidget {
text: TextSpan(
style: TextStyle(fontSize: 16, color: Colors.black),
children: <TextSpan>[
TextSpan(text: '문장의 빠르기가 빠르거나 느리면 밑줄이 표시됩니다. ex)'),
TextSpan(text: '문장이 빠르면 빨강, 느리면 보라색 밑줄로 표시됩니다.'),
// 예시에 적용할 스타일
TextSpan(
text: '강아지는 ',
style: TextStyle(decoration: TextDecoration.underline),
),
TextSpan(
text: '뛴다',
style: TextStyle(decoration: TextDecoration.underline),
),
//들여쓰기
],
),
),
],
),
);
}
}

}

0 comments on commit 80309a9

Please sign in to comment.