diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index b5586f2..391a902 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -1,26 +1,24 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 13.0 - - + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/lib/app/router/app_router.dart b/lib/app/router/app_router.dart index 4b7fc9b..b00eb42 100644 --- a/lib/app/router/app_router.dart +++ b/lib/app/router/app_router.dart @@ -145,7 +145,10 @@ GoRouter goRouter(Ref ref) { GoRoute( path: 'chat', parentNavigatorKey: _rootNavigatorKey, - builder: (context, state) => const ChatScreen(), + builder: (context, state) { + final initialPrompt = state.extra as String?; + return ChatScreen(initialPrompt: initialPrompt); + }, ), ], ), diff --git a/lib/features/chat/presentation/chat_screen.dart b/lib/features/chat/presentation/chat_screen.dart index 41982c8..5a1dda7 100644 --- a/lib/features/chat/presentation/chat_screen.dart +++ b/lib/features/chat/presentation/chat_screen.dart @@ -6,7 +6,9 @@ import 'package:learning_coach/shared/data/providers.dart'; import 'package:learning_coach/shared/models/models.dart'; class ChatScreen extends ConsumerStatefulWidget { - const ChatScreen({super.key}); + final String? initialPrompt; + + const ChatScreen({super.key, this.initialPrompt}); @override ConsumerState createState() => _ChatScreenState(); @@ -17,6 +19,31 @@ class _ChatScreenState extends ConsumerState { final ScrollController _scrollController = ScrollController(); bool _isSending = false; + @override + void initState() { + super.initState(); + if (widget.initialPrompt != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _sendInitialMessage(widget.initialPrompt!); + }); + } + } + + Future _sendInitialMessage(String text) async { + setState(() => _isSending = true); + try { + // Add user message first (optional, maybe we don't want to show the long prompt?) + // For now let's show it so user knows context is sent. + // Alternatively, we could send it as a "system" message or just directly call provider. + await ref.read(chatMessagesProvider.notifier).sendMessage(text); + Future.delayed(const Duration(milliseconds: 100), _scrollToBottom); + } finally { + if (mounted) { + setState(() => _isSending = false); + } + } + } + @override void dispose() { _controller.dispose(); diff --git a/lib/features/home/presentation/widgets/home_widgets.dart b/lib/features/home/presentation/widgets/home_widgets.dart index debb9eb..8f3ebcc 100644 --- a/lib/features/home/presentation/widgets/home_widgets.dart +++ b/lib/features/home/presentation/widgets/home_widgets.dart @@ -5,7 +5,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:learning_coach/core/constants/app_strings.dart'; import 'package:learning_coach/core/providers/locale_provider.dart'; +import 'package:learning_coach/shared/data/api_stats_repository.dart'; import 'package:learning_coach/shared/data/providers.dart'; +import 'package:learning_coach/shared/models/models.dart'; // --- Today Plan Card --- class TodayPlanCard extends ConsumerStatefulWidget { @@ -545,6 +547,7 @@ class _CoachTipCardState extends ConsumerState with SingleTickerProviderStateMixin { late AnimationController _floatController; late Animation _floatAnimation; + bool _isLoading = false; @override void initState() { @@ -564,6 +567,110 @@ class _CoachTipCardState extends ConsumerState super.dispose(); } + Future _handleTap() async { + if (_isLoading) return; + + setState(() => _isLoading = true); + + try { + // 1. Fetch Data + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + + final dailyStatsList = await ref.read(dailyStatsProvider.future); + final sessions = await ref + .read(apiStudySessionRepositoryProvider) + .getSessions(); + final goals = await ref.read(goalsProvider.future); + final userStats = ref.read(userStatsProvider); + + // 2. Filter & Aggregate + final todayStats = dailyStatsList.firstWhere( + (s) => s.date == today.toIso8601String().split('T')[0], + orElse: () => DailyStats(date: '', minutes: 0, sessions: 0), + ); + + final todaySessions = sessions.where((s) { + final date = DateTime( + s.startTime.year, + s.startTime.month, + s.startTime.day, + ); + return date.isAtSameMomentAs(today); + }).toList(); + + // 3. Construct Detailed Prompt + final buffer = StringBuffer(); + buffer.writeln( + 'Merhaba Koç, benim "Learning Coach" asistanımsın. İşte bugünkü durumum:', + ); + + buffer.writeln('\n👤 **Kullanıcı Profili:**'); + buffer.writeln( + '- Seviye: ${userStats.level} (${userStats.stage.name.toUpperCase()})', + ); + buffer.writeln( + '- XP: ${userStats.xp} / ${userStats.xpRequiredForNextLevel}', + ); + buffer.writeln('- Toplam Altın: ${userStats.gold}'); + + buffer.writeln('\n📅 **Bugünkü Özet:**'); + buffer.writeln('- Toplam Çalışma: ${todayStats.minutes} dakika'); + buffer.writeln('- Oturum Sayısı: ${todayStats.sessions}'); + + if (todaySessions.isNotEmpty) { + buffer.writeln('\n📝 **Oturum Detayları:**'); + for (final session in todaySessions) { + final goal = goals.firstWhere( + (g) => g.id == session.goalId, + orElse: () => Goal(title: 'Bilinmeyen Hedef', description: ''), + ); + + final timeStr = + "${session.startTime.hour.toString().padLeft(2, '0')}:${session.startTime.minute.toString().padLeft(2, '0')}"; + + buffer.write('- **$timeStr** | ${goal.title}'); + buffer.write(' (${session.durationMinutes} dk)'); + + if (session.quizScore != null) { + buffer.write(' | Quiz Başarısı: %${session.quizScore}'); + } + + // Efficiency Check (if actual duration is tracked) + if (session.actualDurationSeconds != null) { + final actualMins = (session.actualDurationSeconds! / 60).round(); + if (actualMins < session.durationMinutes) { + buffer.write(' | ⚡ Verimli (Erken bitti)'); + } else if (actualMins > session.durationMinutes + 5) { + buffer.write(' | 🐢 Biraz uzadı'); + } + } + buffer.writeln(); + } + } else { + buffer.writeln('\nHenüz detaylı bir çalışma kaydım yok.'); + } + + buffer.writeln( + '\nLütfen bu verilere dayanarak bana özel, motive edici ve gelişim odaklı bir tavsiye ver. Eğer verimsiz geçtiyse nazikçe uyar, iyiyse kutla.', + ); + + if (!mounted) return; + + // 4. Navigate + context.push('/home/chat', extra: buffer.toString()); + } catch (e) { + debugPrint('Error preparing coach tip: $e'); + if (mounted) { + context.push('/home/chat'); // Fallback to empty chat + } + } finally { + if (mounted) { + setState(() => _isLoading = false); + } + } + } + @override Widget build(BuildContext context) { final locale = ref.watch(localeProvider); @@ -606,7 +713,7 @@ class _CoachTipCardState extends ConsumerState child: Material( color: Colors.transparent, child: InkWell( - onTap: () => context.push('/home/chat'), + onTap: _isLoading ? null : _handleTap, borderRadius: BorderRadius.circular(28), child: Padding( padding: const EdgeInsets.all(24.0), @@ -666,11 +773,20 @@ class _CoachTipCardState extends ConsumerState color: Colors.white.withOpacity(0.2), shape: BoxShape.circle, ), - child: const Icon( - Icons.auto_awesome_rounded, - color: Colors.white, - size: 16, - ), + child: _isLoading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + : const Icon( + Icons.auto_awesome_rounded, + color: Colors.white, + size: 16, + ), ), ], ), diff --git a/lib/shared/services/api_service.dart b/lib/shared/services/api_service.dart index d5b329e..64eebf2 100644 --- a/lib/shared/services/api_service.dart +++ b/lib/shared/services/api_service.dart @@ -216,6 +216,11 @@ class ApiService { static String get baseUrlLLM { // 1. Önce .env dosyasında tanımlı mı diye bakıyoruz final envUrl = dotenv.env['LLM_BASE_URL']; + final debugModeLLM = dotenv.env['DEBUG_MODE_LLM']; + + if (debugModeLLM == 'true') { + return 'http://127.0.0.1:8000'; + } if (envUrl != null && envUrl.isNotEmpty) { return envUrl; diff --git a/llm_backend/app/__init__.py b/llm_backend/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llm_backend/app/api/__init__.py b/llm_backend/app/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llm_backend/app/api/chat.py b/llm_backend/app/api/chat.py index bbaab72..f044d49 100644 --- a/llm_backend/app/api/chat.py +++ b/llm_backend/app/api/chat.py @@ -1,3 +1,4 @@ +import time from fastapi import APIRouter, HTTPException from app.models.chat_models import ChatRequest, ChatResponse from app.services.llm_service import ask_llama @@ -7,10 +8,25 @@ @router.post("", response_model=ChatResponse) def chat(req: ChatRequest): + start_time = time.time() try: - logger.info(f"Kullanıcı mesajı: {req.message}") + # Determine chat type based on message content + chat_type = "COACH_TIP" if "Merhaba Koç, benim \"Learning Coach\" asistanımsın" in req.message else "GENERAL_CHAT" + + logger.info(f"[{chat_type}] REQUEST: {req.message[:50]}...") + answer = ask_llama(req.message) + + duration_ms = (time.time() - start_time) * 1000 + logger.info(f"[{chat_type}] RESPONSE ({duration_ms:.2f}ms): {answer[:50]}...") + + # Explicitly log specifically for the test requirement + logger.info(f"TEST_LOG | {chat_type} | {duration_ms:.2f}ms | Q: {req.message[:100]}... | A: {answer[:100]}...") + return ChatResponse(answer=answer) + except Exception as e: + logger.error(f"Chat error: {str(e)}") + raise HTTPException(status_code=500, detail="LLM error") except Exception as e: logger.error(str(e)) diff --git a/llm_backend/app/core/__init__.py b/llm_backend/app/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llm_backend/app/core/logger.py b/llm_backend/app/core/logger.py index 58f7234..124f131 100644 --- a/llm_backend/app/core/logger.py +++ b/llm_backend/app/core/logger.py @@ -1,8 +1,25 @@ import logging +import os +from datetime import datetime +# Logs directory setup +LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs") +os.makedirs(LOG_DIR, exist_ok=True) + +# Generate a unique filename for this session +session_timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") +log_filename = f"chat_log_{session_timestamp}.txt" +log_filepath = os.path.join(LOG_DIR, log_filename) + +# Configure logging logging.basicConfig( level=logging.INFO, - format="%(asctime)s | %(levelname)s | %(message)s" + format="%(asctime)s | %(levelname)s | %(message)s", + handlers=[ + logging.StreamHandler(), # Console output + logging.FileHandler(log_filepath, encoding='utf-8') # File output + ] ) logger = logging.getLogger("AI-COACH") +logger.info(f"Logging started. Log file: {log_filepath}") diff --git a/llm_backend/app/models/__init__.py b/llm_backend/app/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llm_backend/app/services/__init__.py b/llm_backend/app/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llm_backend/logs/chat_log_20260216_020724.txt b/llm_backend/logs/chat_log_20260216_020724.txt new file mode 100644 index 0000000..718ae3d --- /dev/null +++ b/llm_backend/logs/chat_log_20260216_020724.txt @@ -0,0 +1 @@ +2026-02-16 02:07:24,308 | INFO | Logging started. Log file: /Users/utar/Documents/GitHub/LearningCoachApp/llm_backend/logs/chat_log_20260216_020724.txt diff --git a/llm_backend/logs/chat_log_20260216_020739.txt b/llm_backend/logs/chat_log_20260216_020739.txt new file mode 100644 index 0000000..3a935af --- /dev/null +++ b/llm_backend/logs/chat_log_20260216_020739.txt @@ -0,0 +1,7 @@ +2026-02-16 02:07:39,831 | INFO | Logging started. Log file: /Users/utar/Documents/GitHub/LearningCoachApp/llm_backend/logs/chat_log_20260216_020739.txt +2026-02-16 02:11:00,246 | INFO | [GENERAL_CHAT] REQUEST: Merhaba, nasılsın?... +2026-02-16 02:11:00,246 | INFO | LLAMA isteği gönderildi +2026-02-16 02:11:00,251 | ERROR | Chat error: HTTPConnectionPool(host='localhost', port=11434): Max retries exceeded with url: /api/chat (Caused by NewConnectionError("HTTPConnection(host='localhost', port=11434): Failed to establish a new connection: [Errno 61] Connection refused")) +2026-02-16 02:11:00,347 | INFO | [COACH_TIP] REQUEST: Merhaba Koç, benim "Learning Coach" asistanımsın. ... +2026-02-16 02:11:00,347 | INFO | LLAMA isteği gönderildi +2026-02-16 02:11:00,348 | ERROR | Chat error: HTTPConnectionPool(host='localhost', port=11434): Max retries exceeded with url: /api/chat (Caused by NewConnectionError("HTTPConnection(host='localhost', port=11434): Failed to establish a new connection: [Errno 61] Connection refused")) diff --git a/llm_backend/logs/chat_log_20260216_021428.txt b/llm_backend/logs/chat_log_20260216_021428.txt new file mode 100644 index 0000000..a244431 --- /dev/null +++ b/llm_backend/logs/chat_log_20260216_021428.txt @@ -0,0 +1,5 @@ +2026-02-16 02:14:28,764 | INFO | Logging started. Log file: /Users/utar/Documents/GitHub/LearningCoachApp/llm_backend/logs/chat_log_20260216_021428.txt +2026-02-16 02:14:44,040 | INFO | [GENERAL_CHAT] REQUEST: Merhaba, nasılsın?... +2026-02-16 02:14:44,040 | INFO | LLAMA isteği gönderildi +2026-02-16 02:14:45,292 | INFO | [GENERAL_CHAT] RESPONSE (1251.70ms): Nasım iyi. Ne soruyor musun?... +2026-02-16 02:14:45,292 | INFO | TEST_LOG | GENERAL_CHAT | 1251.70ms | Q: Merhaba, nasılsın?... | A: Nasım iyi. Ne soruyor musun?... diff --git a/llm_backend/logs/chat_log_20260216_021720.txt b/llm_backend/logs/chat_log_20260216_021720.txt new file mode 100644 index 0000000..f6ea3fd --- /dev/null +++ b/llm_backend/logs/chat_log_20260216_021720.txt @@ -0,0 +1 @@ +2026-02-16 02:17:20,330 | INFO | Logging started. Log file: /Users/utar/Documents/GitHub/LearningCoachApp/llm_backend/logs/chat_log_20260216_021720.txt diff --git a/pubspec.lock b/pubspec.lock index 1707247..10164c5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,34 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d url: "https://pub.dev" source: hosted - version: "85.0.0" + version: "91.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c + sha256: a40a0cee526a7e1f387c6847bd8a5ccbf510a75952ef8a28338e989558072cb0 url: "https://pub.dev" source: hosted - version: "7.6.0" + version: "8.4.0" analyzer_buffer: dependency: transitive description: name: analyzer_buffer - sha256: f7833bee67c03c37241c67f8741b17cc501b69d9758df7a5a4a13ed6c947be43 + sha256: aba2f75e63b3135fd1efaa8b6abefe1aa6e41b6bd9806221620fa48f98156033 url: "https://pub.dev" source: hosted - version: "0.1.10" + version: "0.1.11" analyzer_plugin: dependency: transitive description: name: analyzer_plugin - sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce + sha256: "08cfefa90b4f4dd3b447bda831cecf644029f9f8e22820f6ee310213ebe2dd53" url: "https://pub.dev" source: hosted - version: "0.13.4" + version: "0.13.10" args: dependency: transitive description: @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -221,26 +221,26 @@ packages: dependency: transitive description: name: custom_lint_core - sha256: cc4684d22ca05bf0a4a51127e19a8aea576b42079ed2bc9e956f11aaebe35dd1 + sha256: "85b339346154d5646952d44d682965dfe9e12cae5febd706f0db3aa5010d6423" url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.8.1" custom_lint_visitor: dependency: transitive description: name: custom_lint_visitor - sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" + sha256: "91f2a81e9f0abb4b9f3bb529f78b6227ce6050300d1ae5b1e2c69c66c7a566d8" url: "https://pub.dev" source: hosted - version: "1.0.0+7.7.0" + version: "1.0.0+8.4.0" dart_style: dependency: transitive description: name: dart_style - sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.3" dbus: dependency: transitive description: @@ -544,14 +544,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" json_annotation: dependency: "direct main" description: @@ -612,18 +604,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: @@ -644,10 +636,10 @@ packages: dependency: transitive description: name: mockito - sha256: "2314cbe9165bcd16106513df9cf3c3224713087f09723b128928dc11a4379f99" + sha256: a45d1aa065b796922db7b9e7e7e45f921aed17adf3a8318a1f47097e7e695566 url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "5.6.3" node_preamble: dependency: transitive description: @@ -897,10 +889,10 @@ packages: dependency: transitive description: name: source_gen - sha256: "7b19d6ba131c6eb98bfcbf8d56c1a7002eba438af2e7ae6f8398b2b0f4f381e3" + sha256: "1d562a3c1f713904ebbed50d2760217fd8a51ca170ac4b05b0db490699dbac17" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.2.0" source_helper: dependency: transitive description: @@ -985,26 +977,26 @@ packages: dependency: transitive description: name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" + sha256: "77cc98ea27006c84e71a7356cf3daf9ddbde2d91d84f77dbfe64cf0e4d9611ae" url: "https://pub.dev" source: hosted - version: "1.26.3" + version: "1.28.0" test_api: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "0.7.8" test_core: dependency: transitive description: name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" + sha256: f1072617a6657e5fc09662e721307f7fb009b4ed89b19f47175d11d5254a62d4 url: "https://pub.dev" source: hosted - version: "0.6.12" + version: "0.6.14" timing: dependency: transitive description: diff --git a/test_data/test_questions.md b/test_data/test_questions.md new file mode 100644 index 0000000..a16866f --- /dev/null +++ b/test_data/test_questions.md @@ -0,0 +1,79 @@ +# Test Soruları ve Senaryoları + +## Genel Chat Soruları +Bu soruların amacı genel bilgi ve sohbet yeteneğini test etmektir. +1. İstanbul'un fethi ne zaman gerçekleşti ve hangi padişah tarafından yapıldı? +2. Kuantum dolanıklığı nedir? Basitçe açıklar mısın? +3. Bana Python ile bir Fibonacci dizisi hesaplayan fonksiyon yazar mısın? +4. Motivasyonumu kaybettim, bana çalışmak için 3 neden söyler misin? +5. Dünyanın en derin çukuru neresidir ve derinliği ne kadardır? +6. Yapay zeka gelecekte meslekleri nasıl etkileyecek? +7. Sağlıklı beslenmek için günde kaç öğün yemeliyim? +8. Bana kısa ve komik bir fıkra anlatır mısın? +9. "Sefiller" kitabının yazarı kimdir? +10. Mars'a insanlı yolculuk ne zaman mümkün olabilir? + +--- + +## Koç Tavsiyesi (Coach Tip) Senaryoları +Aşağıdaki metinler, uygulamanın arka planda `CoachTipCard` üzerinden gönderdiği prompt yapılarını simüle eder. Test ederken bu metinleri Chat ekranına yapıştırarak veya API request body olarak kullanarak test edebilirsiniz. + +### Senaryo 1: Yeni Başlayan (Hiç Veri Yok) +```text +Merhaba Koç, benim "Learning Coach" asistanımsın. İşte bugünkü durumum: + +👤 **Kullanıcı Profili:** +- Seviye: 1 (TOHUM) +- XP: 0 / 100 +- Toplam Altın: 0 + +📅 **Bugünkü Özet:** +- Toplam Çalışma: 0 dakika +- Oturum Sayısı: 0 + +Henüz detaylı bir çalışma kaydım yok. + +Lütfen bu verilere dayanarak bana özel, motive edici ve gelişim odaklı bir tavsiye ver. Eğer verimsiz geçtiyse nazikçe uyar, iyiyse kutla. +``` + +### Senaryo 2: Verimli Bir Gün (Çok Çalışmış) +```text +Merhaba Koç, benim "Learning Coach" asistanımsın. İşte bugünkü durumum: + +👤 **Kullanıcı Profili:** +- Seviye: 5 (FİDAN) +- XP: 450 / 500 +- Toplam Altın: 320 + +📅 **Bugünkü Özet:** +- Toplam Çalışma: 180 dakika +- Oturum Sayısı: 4 + +📝 **Oturum Detayları:** +- **09:00** | Matematik Çalışması (50 dk) | Quiz Başarısı: %85 | ⚡ Verimli (Erken bitti) +- **11:00** | Tarih Okuması (40 dk) +- **14:00** | Fizik Problemleri (60 dk) | 🐢 Biraz uzadı +- **16:00** | İngilizce Kelime (30 dk) | Quiz Başarısı: %95 + +Lütfen bu verilere dayanarak bana özel, motive edici ve gelişim odaklı bir tavsiye ver. Eğer verimsiz geçtiyse nazikçe uyar, iyiyse kutla. +``` + +### Senaryo 3: Zorlanan Kullanıcı (Düşük Başarı) +```text +Merhaba Koç, benim "Learning Coach" asistanımsın. İşte bugünkü durumum: + +👤 **Kullanıcı Profili:** +- Seviye: 3 (FİLİZ) +- XP: 210 / 300 +- Toplam Altın: 150 + +📅 **Bugünkü Özet:** +- Toplam Çalışma: 45 dakika +- Oturum Sayısı: 2 + +📝 **Oturum Detayları:** +- **10:00** | Kimya Konu Anlatımı (30 dk) | Quiz Başarısı: %40 +- **13:30** | Biyoloji Testi (15 dk) | Quiz Başarısı: %30 + +Lütfen bu verilere dayanarak bana özel, motive edici ve gelişim odaklı bir tavsiye ver. Eğer verimsiz geçtiyse nazikçe uyar, iyiyse kutla. +```