From b40c135b7b214368c5e7ff0a4d4b0bc28fa365b2 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Fri, 21 Mar 2025 00:59:44 +0200 Subject: [PATCH 01/10] feat: add emergency button to (caregiver dashboard, stml_user_screen) and integrate notification service --- .vscode/launch.json | 88 ++++++++++ .vscode/settings.json | 4 + .../android/app/src/main/AndroidManifest.xml | 1 + .../lib/services/help_service.dart | 16 ++ .../lib/services/notification_service.dart | 71 ++++++++ .../presentation/caregiver-dashboard.dart | 154 +++++++++++------- .../presentation/stml_user_dashboard.dart | 11 +- STML/stml_application/lib/ui/help_screen.dart | 39 +++++ .../Flutter/GeneratedPluginRegistrant.swift | 2 + 9 files changed, 322 insertions(+), 64 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 STML/stml_application/lib/services/help_service.dart create mode 100644 STML/stml_application/lib/services/notification_service.dart create mode 100644 STML/stml_application/lib/ui/help_screen.dart diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..51a31a77 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,88 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "team_a", + "cwd": "team_a", + "request": "launch", + "type": "dart" + }, + { + "name": "team_a (profile mode)", + "cwd": "team_a", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "team_a (release mode)", + "cwd": "team_a", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "stml_application", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart" + }, + { + "name": "stml_application (profile mode)", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "stml_application (release mode)", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "teamA", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart" + }, + { + "name": "teamA (profile mode)", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "teamA (release mode)", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "yappy", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart" + }, + { + "name": "yappy (profile mode)", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "yappy (release mode)", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..88550be3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "cmake.ignoreCMakeListsMissing": true, + "dart.flutterSdkPath": "C:\\flutter_windows_3.29.0-stable\\flutter" +} \ No newline at end of file diff --git a/STML/stml_application/android/app/src/main/AndroidManifest.xml b/STML/stml_application/android/app/src/main/AndroidManifest.xml index a0f74233..1be5bf25 100644 --- a/STML/stml_application/android/app/src/main/AndroidManifest.xml +++ b/STML/stml_application/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ + sendHelpNotification() async { + // Remplacez 'caregiver_device_token' par le token du soignant + await _firebaseMessaging.sendMessage( + to: 'caregiver_device_token', + data: { + 'type': 'help_request', + 'message': 'The STML user has requested help.', + }, + ); + } +} diff --git a/STML/stml_application/lib/services/notification_service.dart b/STML/stml_application/lib/services/notification_service.dart new file mode 100644 index 00000000..616dc6d7 --- /dev/null +++ b/STML/stml_application/lib/services/notification_service.dart @@ -0,0 +1,71 @@ +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationService { + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; + final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + String? _caregiverToken; + + Future initialize() async { + // Récupérer le token FCM de l'appareil actuel + _caregiverToken = await _firebaseMessaging.getToken(); + print("Caregiver Token: $_caregiverToken"); + + // Écouter les nouveaux tokens (au cas où le token change) + _firebaseMessaging.onTokenRefresh.listen((newToken) { + _caregiverToken = newToken; + print("New Caregiver Token: $_caregiverToken"); + }); + + // Configurer les notifications locales + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('@mipmap/ic_launcher'); + final InitializationSettings initializationSettings = + InitializationSettings( + android: initializationSettingsAndroid, + ); + await _flutterLocalNotificationsPlugin.initialize(initializationSettings); + + // Écouter les messages entrants + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + print("Message reçu: ${message.notification?.title}"); + _showNotification(message); + }); + } + + Future _showNotification(RemoteMessage message) async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'your_channel_id', // ID du canal de notification + 'your_channel_name', // Nom du canal de notification + importance: Importance.max, + priority: Priority.high, + ); + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + await _flutterLocalNotificationsPlugin.show( + 0, // ID de la notification + message.notification?.title, // Titre de la notification + message.notification?.body, // Corps de la notification + platformChannelSpecifics, + ); + } + + Future sendHelpNotification() async { + if (_caregiverToken == null) { + print("Caregiver token is not available."); + return; + } + + // Envoyer une notification au soignant + await _firebaseMessaging.sendMessage( + to: _caregiverToken!, + data: { + 'type': 'help_request', + 'message': 'The STML user has requested help.', + }, + ); + } +} diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart index edc86df7..61e72326 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart @@ -14,6 +14,7 @@ import 'package:memoryminder/ui/profile_screen.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:url_launcher/url_launcher.dart'; // Main HomeScreen widget which is a stateless widget. class CaregiverDashboardScreen extends StatefulWidget { @@ -33,6 +34,16 @@ class _CaregiverDashboardScreen extends State { _careRecipientData = ManageCareRecipientService().getAllCareRecipients(); } + Future _callEmergencyNumber() async { + const phoneNumber = + 'tel:911'; // Remplacez par le numéro d'urgence approprié + if (await canLaunch(phoneNumber)) { + await launch(phoneNumber); + } else { + throw 'Could not launch $phoneNumber'; + } + } + @override void dispose() { NotificationStreamService().dispose(); @@ -47,7 +58,6 @@ class _CaregiverDashboardScreen extends State { appBar: const CustomAppBar( title: 'Caregiver Dashboard', ), - body: Container( decoration: BoxDecoration( image: DecorationImage( @@ -112,7 +122,6 @@ class _CaregiverDashboardScreen extends State { ), ), ), - const Divider( color: Colors.black54, thickness: 2, @@ -120,7 +129,33 @@ class _CaregiverDashboardScreen extends State { indent: 20, endIndent: 20, ), - + const Divider( + color: Colors.black54, + thickness: 2, + height: 10, + indent: 20, + endIndent: 20, + ), + ElevatedButton( + onPressed: _callEmergencyNumber, + style: ElevatedButton.styleFrom( + backgroundColor: + Colors.red, // Couleur rouge pour indiquer l'urgence + padding: + const EdgeInsets.symmetric(horizontal: 32, vertical: 16), + ), + child: const Text( + 'Emergency Call', + style: TextStyle(fontSize: 18, color: Colors.white), + ), + ), + const Divider( + color: Colors.black54, + thickness: 2, + height: 10, + indent: 20, + endIndent: 20, + ), Padding( padding: EdgeInsets.fromLTRB(2.0, 2, 2.0, 2), child: Column( @@ -138,7 +173,8 @@ class _CaregiverDashboardScreen extends State { onPressed: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => AddCareRecipientForm()), + MaterialPageRoute( + builder: (context) => AddCareRecipientForm()), ); }, icon: Icon( @@ -149,18 +185,17 @@ class _CaregiverDashboardScreen extends State { style: ElevatedButton.styleFrom( backgroundColor: Colors.green, foregroundColor: Colors.black, - padding: EdgeInsets.fromLTRB(2.0, 2, 16.0, 2), // Apply padding here + padding: EdgeInsets.fromLTRB( + 2.0, 2, 16.0, 2), // Apply padding here ), ), ], ), ), - - Expanded( - child: _buildCareRecipientsGrid( - context: context, - ), + child: _buildCareRecipientsGrid( + context: context, + ), ), const Divider( color: Colors.black, @@ -187,61 +222,64 @@ class _CaregiverDashboardScreen extends State { final data = snapshot.data!; return GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, // Adjust as needed - childAspectRatio: 1.0, - mainAxisSpacing: 3, - crossAxisSpacing: 3 - ), + crossAxisCount: 3, // Adjust as needed + childAspectRatio: 1.0, + mainAxisSpacing: 3, + crossAxisSpacing: 3), itemCount: data.length, itemBuilder: (context, index) { final item = data[index]; - final String labelText = '${item['firstName'].toString()} ${item['lastName'].toString()}'; + final String labelText = + '${item['firstName'].toString()} ${item['lastName'].toString()}'; final careRecipient = CareRecipient.fromMap(item); - return InkWell( // Or InkWell for ripple effect - onTap: () { - // Handle item click - print('Item ${item['firstName'].toString()} clicked'); - Navigator.push( - context, - MaterialPageRoute(builder: (context) => CareRecipientProfileScreen(careRecipientId: item['itemId'].toString(), careRecipientData: careRecipient.toMap())), - ); - }, - borderRadius: BorderRadius.circular(12.0), - child: Container( - decoration: BoxDecoration( - color: Colors.lightGreen[100], - borderRadius: BorderRadius.circular(12.0), - boxShadow: [ - BoxShadow( - color: Colors.lightGreen.withOpacity(0.5), - spreadRadius: 1, - blurRadius: 3, - offset: const Offset(0, 2), - ), - ], - ), - padding: const EdgeInsets.all(3.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.person, - size: 40.0, - color: Colors.green, - ), - const SizedBox(height: 8.0), - Text( - labelText, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Colors.black87, + return InkWell( + // Or InkWell for ripple effect + onTap: () { + // Handle item click + print('Item ${item['firstName'].toString()} clicked'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CareRecipientProfileScreen( + careRecipientId: item['itemId'].toString(), + careRecipientData: careRecipient.toMap())), + ); + }, + borderRadius: BorderRadius.circular(12.0), + child: Container( + decoration: BoxDecoration( + color: Colors.lightGreen[100], + borderRadius: BorderRadius.circular(12.0), + boxShadow: [ + BoxShadow( + color: Colors.lightGreen.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 2), + ), + ], + ), + padding: const EdgeInsets.all(3.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.person, + size: 40.0, + color: Colors.green, + ), + const SizedBox(height: 8.0), + Text( + labelText, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black87, ), ), ], ), - ) - ); + )); }, ); } else if (snapshot.hasError) { @@ -307,5 +345,3 @@ class _CaregiverDashboardScreen extends State { ); } } - - diff --git a/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart b/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart index 50dcb054..5bdc4c67 100644 --- a/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart +++ b/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart @@ -1,9 +1,11 @@ // ignore_for_file: avoid_print, prefer_const_constructors // Imported libraries and packages +import 'package:memoryminder/services/notification_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/app_bar.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart'; import 'package:memoryminder/ui/dementia_resources.dart'; +import 'package:memoryminder/ui/help_screen.dart'; import 'package:memoryminder/ui/response_screen.dart'; import 'package:memoryminder/ui/assistant_screen.dart'; import 'package:memoryminder/src/features/sensitive_information_detection/presentation/audio_screen.dart'; @@ -134,13 +136,12 @@ class _HomeScreenState extends State { const Color(0xFF000000).withOpacity(0.30)), _buildElevatedButton( context: context, - icon: Icon(Icons.location_history, - size: iconSize, color: Colors.black54), + icon: Icon(Icons.help_outline, + size: iconSize, color: Colors.white), text: 'HELP', - screen: LocationHistoryScreen(), + screen: HelpScreen(), keyName: "HelpButtonKey", - backgroundColor: - const Color(0xFFFFFFFF).withOpacity(0.30)), + backgroundColor: Colors.red.withOpacity(0.80)), _buildElevatedButton( context: context, icon: Icon(Icons.photo, diff --git a/STML/stml_application/lib/ui/help_screen.dart b/STML/stml_application/lib/ui/help_screen.dart new file mode 100644 index 00000000..1042db10 --- /dev/null +++ b/STML/stml_application/lib/ui/help_screen.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:memoryminder/services/notification_service.dart'; + +class HelpScreen extends StatelessWidget { + const HelpScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final notificationService = NotificationService(); + + return Scaffold( + appBar: AppBar( + title: const Text('Help'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Help is on the way!', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: () async { + await notificationService.sendHelpNotification(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Help request sent to caregiver.')), + ); + }, + child: const Text('Send Help Request'), + ), + ], + ), + ), + ); + } +} diff --git a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift index de20bf45..f1b66c4b 100644 --- a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import file_selector_macos import firebase_auth import firebase_core import firebase_messaging +import flutter_local_notifications import flutter_tts import geolocator_apple import local_auth_darwin @@ -27,6 +28,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) From e40f2a40fb624dca7454cd13c816f638ab4475ab Mon Sep 17 00:00:00 2001 From: Layersuza Date: Fri, 21 Mar 2025 02:23:15 +0200 Subject: [PATCH 02/10] feat: add emmergency call 911 logic to caregiver notification_service --- .vscode/launch.json | 6 + .../service/notification_service.dart | 129 ++++++++++++------ 2 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 51a31a77..a91a9154 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,12 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "Flutter", + "type": "dart", + "request": "launch", + "program": "lib/main.dart" + }, { "name": "team_a", "cwd": "team_a", diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart index 2742da48..a2a93695 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart @@ -7,29 +7,34 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_stream_service.dart'; - - +import 'package:url_launcher/url_launcher.dart'; class NotificationService { final FirebaseMessaging _messaging = FirebaseMessaging.instance; final FirebaseFirestore _firestore = FirebaseFirestore.instance; - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); Future initialize() async { await _messaging.subscribeToTopic("STML_USER_PRESSED_HELP"); - _messaging.requestPermission(alert: true, + _messaging.requestPermission( + alert: true, announcement: true, badge: true, carPlay: false, criticalAlert: true, provisional: false, - sound: true,); + sound: true, + ); FirebaseMessaging.onMessage.listen((RemoteMessage message) async { - print('---------------------------------------------------------------------'); - print('---Received a notification message: ${message.notification?.title}---'); - print('---------------------------------------------------------------------'); + print( + '---------------------------------------------------------------------'); + print( + '---Received a notification message: ${message.notification?.title}---'); + print( + '---------------------------------------------------------------------'); _storeMessage(message); await Future.delayed(Duration(seconds: 5)); @@ -38,25 +43,43 @@ class NotificationService { }); FirebaseMessaging.onBackgroundMessage(_backgroundMessageHandler); - const AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); - const DarwinInitializationSettings iOSinitializationSettings = DarwinInitializationSettings( + + const AndroidInitializationSettings androidInitializationSettings = + AndroidInitializationSettings('@mipmap/ic_launcher'); + const DarwinInitializationSettings iOSinitializationSettings = + DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); - const InitializationSettings initializationSettings = InitializationSettings(android: androidInitializationSettings, iOS: iOSinitializationSettings); - await flutterLocalNotificationsPlugin.initialize(initializationSettings); - + const InitializationSettings initializationSettings = + InitializationSettings( + android: androidInitializationSettings, + iOS: iOSinitializationSettings, + ); + await flutterLocalNotificationsPlugin.initialize( + initializationSettings, + onDidReceiveNotificationResponse: (NotificationResponse response) async { + if (response.actionId == 'emergency_call') { + const phoneNumber = 'tel:911'; + if (await canLaunch(phoneNumber)) { + await launch(phoneNumber); + } else { + throw 'Could not launch $phoneNumber'; + } + } + }, + ); // Handle initial message when the app is opened from a terminated state - RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); + RemoteMessage? initialMessage = + await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { _handleMessage(initialMessage); } // Handle when the app is opened from background state. FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); - } static void _handleMessage(RemoteMessage message) { @@ -65,72 +88,94 @@ class NotificationService { // Example: Navigator.of(navigatorKey.currentContext!).pushNamed('/details', arguments: message.data); } - - - Future _showLocalNotification(RemoteMessage message) async{ - const AndroidNotificationDetails androidChannelSpecifics = AndroidNotificationDetails('Help', 'Help', channelDescription: 'User pressed Help button', importance: Importance.max, priority: Priority.high, ticker: 'ticker'); - const NotificationDetails channelSpecifics = NotificationDetails(android: androidChannelSpecifics, iOS: const DarwinNotificationDetails()); - await flutterLocalNotificationsPlugin.show(0, message.notification?.title, message.notification?.title, channelSpecifics); - + Future _showLocalNotification(RemoteMessage message) async { + const AndroidNotificationDetails androidChannelSpecifics = + AndroidNotificationDetails( + 'Help', //Canal ID + 'Help Notifications', // canal name + channelDescription: + 'Notifications when the STML user presses the HELP button', + importance: Importance.max, + priority: Priority.high, + ticker: 'ticker', + enableVibration: true, //vibrations + playSound: true, // play tone + actions: [ + AndroidNotificationAction( + 'emergency_call', // action Id + 'Emergency Call', // action text + ), + ], + ); + const NotificationDetails channelSpecifics = NotificationDetails( + android: androidChannelSpecifics, + iOS: const DarwinNotificationDetails()); + await flutterLocalNotificationsPlugin.show(0, message.notification?.title, + message.notification?.body, channelSpecifics); } Future _storeMessage(RemoteMessage message) async { await _firestore.collection('notifications').add({ 'title': message.notification?.title, - 'read': false, //Flag to indicate if the message is read or not. + 'read': false, // Flag to indicate if the message is read or not. 'createdDate': FieldValue.serverTimestamp(), + 'stmlUserId': 'USER_ID', // Replaced by STML's userID }); } Future markNotificationAsRead(String messageId) async { try { - DocumentReference notificationRef = _firestore.collection('notifications').doc(messageId); - await notificationRef.update({'read':true}); + DocumentReference notificationRef = + _firestore.collection('notifications').doc(messageId); + await notificationRef.update({'read': true}); print('Notification updated as read'); getRecentNotifications(); - - } catch(e) { + } catch (e) { print('Error updating notification data: $e'); } } Future getRecentNotifications() async { try { - QuerySnapshot snapshot = await _firestore.collection('notifications') + QuerySnapshot snapshot = await _firestore + .collection('notifications') .orderBy('createdDate', descending: true) .limit(10) .get(); List> notifications = snapshot.docs.map((doc) { - return {'id': doc.id, + return { + 'id': doc.id, 'title': doc['title'], 'read': doc['read'], 'createDate': doc['createdDate'], }; }).toList(); NotificationStreamService().addData(notifications); - } catch(e) { + } catch (e) { print('Error fetching notifications $e'); } } -Future sendNotificationToFirestore(String title) async { - await FirebaseFirestore.instance.collection('notifications').add({ - 'title': title, - 'read': false, // Mark as unread by default - 'createdDate': FieldValue.serverTimestamp(), - }); - -} + Future sendNotificationToFirestore(String title) async { + await FirebaseFirestore.instance.collection('notifications').add({ + 'title': title, + 'read': false, // Mark as unread by default + 'createdDate': FieldValue.serverTimestamp(), + }); + } } Future _backgroundMessageHandler(RemoteMessage message) async { - print('---------------------------------------------------------------------'); - print('---Received a background data message----${message.notification?.title}---------------------------'); - print('---------------------------------------------------------------------'); + print( + '---------------------------------------------------------------------'); + print( + '---Received a background data message----${message.notification?.title}---------------------------'); + print( + '---------------------------------------------------------------------'); await Firebase.initializeApp(); NotificationService()._storeMessage(message); await Future.delayed(Duration(seconds: 5)); NotificationService().getRecentNotifications(); NotificationService()._showLocalNotification(message); -} \ No newline at end of file +} From 14990b428af34b17d20739a381c431ccb4f2df39 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Fri, 21 Mar 2025 00:59:44 +0200 Subject: [PATCH 03/10] feat: add emergency button to (caregiver dashboard, stml_user_screen) and integrate notification service --- .vscode/launch.json | 88 ++++++++++ .vscode/settings.json | 4 + .../android/app/src/main/AndroidManifest.xml | 1 + .../lib/services/help_service.dart | 16 ++ .../lib/services/notification_service.dart | 71 ++++++++ .../presentation/caregiver-dashboard.dart | 155 +++++++++++------- .../presentation/stml_user_dashboard.dart | 11 +- STML/stml_application/lib/ui/help_screen.dart | 39 +++++ 8 files changed, 320 insertions(+), 65 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 STML/stml_application/lib/services/help_service.dart create mode 100644 STML/stml_application/lib/services/notification_service.dart create mode 100644 STML/stml_application/lib/ui/help_screen.dart diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..51a31a77 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,88 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "team_a", + "cwd": "team_a", + "request": "launch", + "type": "dart" + }, + { + "name": "team_a (profile mode)", + "cwd": "team_a", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "team_a (release mode)", + "cwd": "team_a", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "stml_application", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart" + }, + { + "name": "stml_application (profile mode)", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "stml_application (release mode)", + "cwd": "STML\\stml_application", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "teamA", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart" + }, + { + "name": "teamA (profile mode)", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "teamA (release mode)", + "cwd": "team_a\\teamA", + "request": "launch", + "type": "dart", + "flutterMode": "release" + }, + { + "name": "yappy", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart" + }, + { + "name": "yappy (profile mode)", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "yappy (release mode)", + "cwd": "team_b\\yappy", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..88550be3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "cmake.ignoreCMakeListsMissing": true, + "dart.flutterSdkPath": "C:\\flutter_windows_3.29.0-stable\\flutter" +} \ No newline at end of file diff --git a/STML/stml_application/android/app/src/main/AndroidManifest.xml b/STML/stml_application/android/app/src/main/AndroidManifest.xml index a0f74233..1be5bf25 100644 --- a/STML/stml_application/android/app/src/main/AndroidManifest.xml +++ b/STML/stml_application/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ + sendHelpNotification() async { + // Remplacez 'caregiver_device_token' par le token du soignant + await _firebaseMessaging.sendMessage( + to: 'caregiver_device_token', + data: { + 'type': 'help_request', + 'message': 'The STML user has requested help.', + }, + ); + } +} diff --git a/STML/stml_application/lib/services/notification_service.dart b/STML/stml_application/lib/services/notification_service.dart new file mode 100644 index 00000000..616dc6d7 --- /dev/null +++ b/STML/stml_application/lib/services/notification_service.dart @@ -0,0 +1,71 @@ +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationService { + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; + final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + String? _caregiverToken; + + Future initialize() async { + // Récupérer le token FCM de l'appareil actuel + _caregiverToken = await _firebaseMessaging.getToken(); + print("Caregiver Token: $_caregiverToken"); + + // Écouter les nouveaux tokens (au cas où le token change) + _firebaseMessaging.onTokenRefresh.listen((newToken) { + _caregiverToken = newToken; + print("New Caregiver Token: $_caregiverToken"); + }); + + // Configurer les notifications locales + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('@mipmap/ic_launcher'); + final InitializationSettings initializationSettings = + InitializationSettings( + android: initializationSettingsAndroid, + ); + await _flutterLocalNotificationsPlugin.initialize(initializationSettings); + + // Écouter les messages entrants + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + print("Message reçu: ${message.notification?.title}"); + _showNotification(message); + }); + } + + Future _showNotification(RemoteMessage message) async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'your_channel_id', // ID du canal de notification + 'your_channel_name', // Nom du canal de notification + importance: Importance.max, + priority: Priority.high, + ); + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + await _flutterLocalNotificationsPlugin.show( + 0, // ID de la notification + message.notification?.title, // Titre de la notification + message.notification?.body, // Corps de la notification + platformChannelSpecifics, + ); + } + + Future sendHelpNotification() async { + if (_caregiverToken == null) { + print("Caregiver token is not available."); + return; + } + + // Envoyer une notification au soignant + await _firebaseMessaging.sendMessage( + to: _caregiverToken!, + data: { + 'type': 'help_request', + 'message': 'The STML user has requested help.', + }, + ); + } +} diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart index 26949d01..68c56b4d 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart @@ -14,6 +14,7 @@ import 'package:memoryminder/ui/profile_screen.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:url_launcher/url_launcher.dart'; // Main HomeScreen widget which is a stateless widget. class CaregiverDashboardScreen extends StatefulWidget { @@ -33,6 +34,16 @@ class _CaregiverDashboardScreen extends State { _careRecipientData = ManageCareRecipientService().getAllCareRecipients(); } + Future _callEmergencyNumber() async { + const phoneNumber = + 'tel:911'; // Remplacez par le numéro d'urgence approprié + if (await canLaunch(phoneNumber)) { + await launch(phoneNumber); + } else { + throw 'Could not launch $phoneNumber'; + } + } + @override void dispose() { NotificationStreamService().dispose(); @@ -47,7 +58,6 @@ class _CaregiverDashboardScreen extends State { appBar: const CustomAppBar( title: 'Caregiver Dashboard', ), - body: Container( /*decoration: BoxDecoration( image: DecorationImage( @@ -112,7 +122,6 @@ class _CaregiverDashboardScreen extends State { ), ), ), - const Divider( color: Colors.black54, thickness: 2, @@ -120,7 +129,33 @@ class _CaregiverDashboardScreen extends State { indent: 20, endIndent: 20, ), - + const Divider( + color: Colors.black54, + thickness: 2, + height: 10, + indent: 20, + endIndent: 20, + ), + ElevatedButton( + onPressed: _callEmergencyNumber, + style: ElevatedButton.styleFrom( + backgroundColor: + Colors.red, // Couleur rouge pour indiquer l'urgence + padding: + const EdgeInsets.symmetric(horizontal: 32, vertical: 16), + ), + child: const Text( + 'Emergency Call', + style: TextStyle(fontSize: 18, color: Colors.white), + ), + ), + const Divider( + color: Colors.black54, + thickness: 2, + height: 10, + indent: 20, + endIndent: 20, + ), Padding( padding: EdgeInsets.fromLTRB(2.0, 2, 2.0, 2), child: Column( @@ -138,7 +173,8 @@ class _CaregiverDashboardScreen extends State { onPressed: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => AddCareRecipientForm()), + MaterialPageRoute( + builder: (context) => AddCareRecipientForm()), ); }, icon: Icon( @@ -149,18 +185,17 @@ class _CaregiverDashboardScreen extends State { style: ElevatedButton.styleFrom( backgroundColor: Colors.green, foregroundColor: Colors.black, - padding: EdgeInsets.fromLTRB(2.0, 2, 16.0, 2), // Apply padding here + padding: EdgeInsets.fromLTRB( + 2.0, 2, 16.0, 2), // Apply padding here ), ), ], ), ), - - Expanded( - child: _buildCareRecipientsGrid( - context: context, - ), + child: _buildCareRecipientsGrid( + context: context, + ), ), const Divider( color: Colors.black, @@ -187,61 +222,64 @@ class _CaregiverDashboardScreen extends State { final data = snapshot.data!; return GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, // Adjust as needed - childAspectRatio: 1.30, - mainAxisSpacing: 10, - crossAxisSpacing: 10 - ), + crossAxisCount: 3, // Adjust as needed + childAspectRatio: 1.0, + mainAxisSpacing: 3, + crossAxisSpacing: 3), itemCount: data.length, itemBuilder: (context, index) { final item = data[index]; - final String labelText = '${item['firstName'].toString()} ${item['lastName'].toString()}'; + final String labelText = + '${item['firstName'].toString()} ${item['lastName'].toString()}'; final careRecipient = CareRecipient.fromMap(item); - return InkWell( // Or InkWell for ripple effect - onTap: () { - // Handle item click - print('Item ${item['firstName'].toString()} clicked'); - Navigator.push( - context, - MaterialPageRoute(builder: (context) => CareRecipientProfileScreen(careRecipientId: item['itemId'].toString(), careRecipientData: careRecipient.toMap())), - ); - }, - borderRadius: BorderRadius.circular(12.0), - child: Container( - decoration: BoxDecoration( - color: Colors.lightBlue[100], - borderRadius: BorderRadius.circular(12.0), - boxShadow: [ - BoxShadow( - color: Colors.lightBlueAccent, - spreadRadius: 1, - blurRadius: 3, - offset: const Offset(0, 2), - ), - ], - ), - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.person, - size: 40.0, - color: Color.fromARGB(255, 2, 63, 129), - ), - const SizedBox(height: 8.0), - Text( - labelText, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.w500, - color: Colors.black87, + return InkWell( + // Or InkWell for ripple effect + onTap: () { + // Handle item click + print('Item ${item['firstName'].toString()} clicked'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CareRecipientProfileScreen( + careRecipientId: item['itemId'].toString(), + careRecipientData: careRecipient.toMap())), + ); + }, + borderRadius: BorderRadius.circular(12.0), + child: Container( + decoration: BoxDecoration( + color: Colors.lightGreen[100], + borderRadius: BorderRadius.circular(12.0), + boxShadow: [ + BoxShadow( + color: Colors.lightGreen.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 2), + ), + ], + ), + padding: const EdgeInsets.all(3.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.person, + size: 40.0, + color: Colors.green, + ), + const SizedBox(height: 8.0), + Text( + labelText, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black87, ), ), ], ), - ) - ); + )); }, ); } else if (snapshot.hasError) { @@ -300,7 +338,6 @@ class _CaregiverDashboardScreen extends State { notificationService .markNotificationAsRead(notification['id']); }, - ); }, )); @@ -308,5 +345,3 @@ class _CaregiverDashboardScreen extends State { ); } } - - diff --git a/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart b/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart index 2534b94b..163c9bf4 100644 --- a/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart +++ b/STML/stml_application/lib/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart @@ -1,9 +1,11 @@ // ignore_for_file: avoid_print, prefer_const_constructors // Imported libraries and packages +import 'package:memoryminder/services/notification_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/app_bar.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart'; import 'package:memoryminder/ui/dementia_resources.dart'; +import 'package:memoryminder/ui/help_screen.dart'; import 'package:memoryminder/ui/response_screen.dart'; import 'package:memoryminder/ui/assistant_screen.dart'; import 'package:memoryminder/src/features/sensitive_information_detection/presentation/audio_screen.dart'; @@ -131,13 +133,12 @@ class _HomeScreenState extends State { const Color(0xFF000000).withOpacity(0.30)), _buildElevatedButton( context: context, - icon: Icon(Icons.location_history, - size: iconSize, color: Colors.black54), + icon: Icon(Icons.help_outline, + size: iconSize, color: Colors.white), text: 'HELP', - screen: LocationHistoryScreen(), + screen: HelpScreen(), keyName: "HelpButtonKey", - backgroundColor: - const Color(0xFFFFFFFF).withOpacity(0.30)), + backgroundColor: Colors.red.withOpacity(0.80)), _buildElevatedButton( context: context, icon: Icon(Icons.photo, diff --git a/STML/stml_application/lib/ui/help_screen.dart b/STML/stml_application/lib/ui/help_screen.dart new file mode 100644 index 00000000..1042db10 --- /dev/null +++ b/STML/stml_application/lib/ui/help_screen.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:memoryminder/services/notification_service.dart'; + +class HelpScreen extends StatelessWidget { + const HelpScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final notificationService = NotificationService(); + + return Scaffold( + appBar: AppBar( + title: const Text('Help'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Help is on the way!', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: () async { + await notificationService.sendHelpNotification(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Help request sent to caregiver.')), + ); + }, + child: const Text('Send Help Request'), + ), + ], + ), + ), + ); + } +} From fd58f55b4ded069c6419c90c7bb9349a11f4a323 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Fri, 21 Mar 2025 02:23:15 +0200 Subject: [PATCH 04/10] feat: add emmergency call 911 logic to caregiver notification_service --- .vscode/launch.json | 6 + .../service/notification_service.dart | 129 ++++++++++++------ 2 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 51a31a77..a91a9154 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,12 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "Flutter", + "type": "dart", + "request": "launch", + "program": "lib/main.dart" + }, { "name": "team_a", "cwd": "team_a", diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart index 2742da48..a2a93695 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/service/notification_service.dart @@ -7,29 +7,34 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_stream_service.dart'; - - +import 'package:url_launcher/url_launcher.dart'; class NotificationService { final FirebaseMessaging _messaging = FirebaseMessaging.instance; final FirebaseFirestore _firestore = FirebaseFirestore.instance; - final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); Future initialize() async { await _messaging.subscribeToTopic("STML_USER_PRESSED_HELP"); - _messaging.requestPermission(alert: true, + _messaging.requestPermission( + alert: true, announcement: true, badge: true, carPlay: false, criticalAlert: true, provisional: false, - sound: true,); + sound: true, + ); FirebaseMessaging.onMessage.listen((RemoteMessage message) async { - print('---------------------------------------------------------------------'); - print('---Received a notification message: ${message.notification?.title}---'); - print('---------------------------------------------------------------------'); + print( + '---------------------------------------------------------------------'); + print( + '---Received a notification message: ${message.notification?.title}---'); + print( + '---------------------------------------------------------------------'); _storeMessage(message); await Future.delayed(Duration(seconds: 5)); @@ -38,25 +43,43 @@ class NotificationService { }); FirebaseMessaging.onBackgroundMessage(_backgroundMessageHandler); - const AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); - const DarwinInitializationSettings iOSinitializationSettings = DarwinInitializationSettings( + + const AndroidInitializationSettings androidInitializationSettings = + AndroidInitializationSettings('@mipmap/ic_launcher'); + const DarwinInitializationSettings iOSinitializationSettings = + DarwinInitializationSettings( requestAlertPermission: true, requestBadgePermission: true, requestSoundPermission: true, ); - const InitializationSettings initializationSettings = InitializationSettings(android: androidInitializationSettings, iOS: iOSinitializationSettings); - await flutterLocalNotificationsPlugin.initialize(initializationSettings); - + const InitializationSettings initializationSettings = + InitializationSettings( + android: androidInitializationSettings, + iOS: iOSinitializationSettings, + ); + await flutterLocalNotificationsPlugin.initialize( + initializationSettings, + onDidReceiveNotificationResponse: (NotificationResponse response) async { + if (response.actionId == 'emergency_call') { + const phoneNumber = 'tel:911'; + if (await canLaunch(phoneNumber)) { + await launch(phoneNumber); + } else { + throw 'Could not launch $phoneNumber'; + } + } + }, + ); // Handle initial message when the app is opened from a terminated state - RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); + RemoteMessage? initialMessage = + await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) { _handleMessage(initialMessage); } // Handle when the app is opened from background state. FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); - } static void _handleMessage(RemoteMessage message) { @@ -65,72 +88,94 @@ class NotificationService { // Example: Navigator.of(navigatorKey.currentContext!).pushNamed('/details', arguments: message.data); } - - - Future _showLocalNotification(RemoteMessage message) async{ - const AndroidNotificationDetails androidChannelSpecifics = AndroidNotificationDetails('Help', 'Help', channelDescription: 'User pressed Help button', importance: Importance.max, priority: Priority.high, ticker: 'ticker'); - const NotificationDetails channelSpecifics = NotificationDetails(android: androidChannelSpecifics, iOS: const DarwinNotificationDetails()); - await flutterLocalNotificationsPlugin.show(0, message.notification?.title, message.notification?.title, channelSpecifics); - + Future _showLocalNotification(RemoteMessage message) async { + const AndroidNotificationDetails androidChannelSpecifics = + AndroidNotificationDetails( + 'Help', //Canal ID + 'Help Notifications', // canal name + channelDescription: + 'Notifications when the STML user presses the HELP button', + importance: Importance.max, + priority: Priority.high, + ticker: 'ticker', + enableVibration: true, //vibrations + playSound: true, // play tone + actions: [ + AndroidNotificationAction( + 'emergency_call', // action Id + 'Emergency Call', // action text + ), + ], + ); + const NotificationDetails channelSpecifics = NotificationDetails( + android: androidChannelSpecifics, + iOS: const DarwinNotificationDetails()); + await flutterLocalNotificationsPlugin.show(0, message.notification?.title, + message.notification?.body, channelSpecifics); } Future _storeMessage(RemoteMessage message) async { await _firestore.collection('notifications').add({ 'title': message.notification?.title, - 'read': false, //Flag to indicate if the message is read or not. + 'read': false, // Flag to indicate if the message is read or not. 'createdDate': FieldValue.serverTimestamp(), + 'stmlUserId': 'USER_ID', // Replaced by STML's userID }); } Future markNotificationAsRead(String messageId) async { try { - DocumentReference notificationRef = _firestore.collection('notifications').doc(messageId); - await notificationRef.update({'read':true}); + DocumentReference notificationRef = + _firestore.collection('notifications').doc(messageId); + await notificationRef.update({'read': true}); print('Notification updated as read'); getRecentNotifications(); - - } catch(e) { + } catch (e) { print('Error updating notification data: $e'); } } Future getRecentNotifications() async { try { - QuerySnapshot snapshot = await _firestore.collection('notifications') + QuerySnapshot snapshot = await _firestore + .collection('notifications') .orderBy('createdDate', descending: true) .limit(10) .get(); List> notifications = snapshot.docs.map((doc) { - return {'id': doc.id, + return { + 'id': doc.id, 'title': doc['title'], 'read': doc['read'], 'createDate': doc['createdDate'], }; }).toList(); NotificationStreamService().addData(notifications); - } catch(e) { + } catch (e) { print('Error fetching notifications $e'); } } -Future sendNotificationToFirestore(String title) async { - await FirebaseFirestore.instance.collection('notifications').add({ - 'title': title, - 'read': false, // Mark as unread by default - 'createdDate': FieldValue.serverTimestamp(), - }); - -} + Future sendNotificationToFirestore(String title) async { + await FirebaseFirestore.instance.collection('notifications').add({ + 'title': title, + 'read': false, // Mark as unread by default + 'createdDate': FieldValue.serverTimestamp(), + }); + } } Future _backgroundMessageHandler(RemoteMessage message) async { - print('---------------------------------------------------------------------'); - print('---Received a background data message----${message.notification?.title}---------------------------'); - print('---------------------------------------------------------------------'); + print( + '---------------------------------------------------------------------'); + print( + '---Received a background data message----${message.notification?.title}---------------------------'); + print( + '---------------------------------------------------------------------'); await Firebase.initializeApp(); NotificationService()._storeMessage(message); await Future.delayed(Duration(seconds: 5)); NotificationService().getRecentNotifications(); NotificationService()._showLocalNotification(message); -} \ No newline at end of file +} From 38d1bb4160bccef79f17955bddcb7401246b4137 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Wed, 26 Mar 2025 00:54:40 +0200 Subject: [PATCH 05/10] add flutter generated plugins --- .../macos/Flutter/GeneratedPluginRegistrant.swift | 4 ---- .../windows/flutter/generated_plugin_registrant.cc | 6 ------ .../windows/flutter/generated_plugins.cmake | 2 -- 3 files changed, 12 deletions(-) diff --git a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift index 20fb3502..cb306519 100644 --- a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,9 +5,7 @@ import FlutterMacOS import Foundation -import cloud_firestore import file_selector_macos -import firebase_auth import firebase_core import firebase_messaging import flutter_local_notifications @@ -25,9 +23,7 @@ import video_player_avfoundation import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) - FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) diff --git a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc index 14cd0546..b9a92ab2 100644 --- a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc +++ b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,7 @@ #include "generated_plugin_registrant.h" -#include #include -#include #include #include #include @@ -18,12 +16,8 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { - CloudFirestorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); - FirebaseAuthPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( diff --git a/STML/stml_application/windows/flutter/generated_plugins.cmake b/STML/stml_application/windows/flutter/generated_plugins.cmake index 03daf122..e59c92e8 100644 --- a/STML/stml_application/windows/flutter/generated_plugins.cmake +++ b/STML/stml_application/windows/flutter/generated_plugins.cmake @@ -3,9 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST - cloud_firestore file_selector_windows - firebase_auth firebase_core flutter_secure_storage_windows flutter_tts From abfee5ef5df019a1b65549aaba249a8e0e95e0bd Mon Sep 17 00:00:00 2001 From: Layersuza Date: Sat, 29 Mar 2025 02:04:13 +0200 Subject: [PATCH 06/10] Remove team_a and team_b folders --- team_a/.gitignore | 41 - team_a/LICENSE | 121 -- team_a/MoodlePlugin/.DS_Store | Bin 6148 -> 0 bytes team_a/MoodlePlugin/learninglens/.DS_Store | Bin 6148 -> 0 bytes .../learninglens/classes/.DS_Store | Bin 6148 -> 0 bytes .../classes/external/add_essay_override.php | 80 - .../classes/external/add_quiz_override.php | 80 - .../external/add_type_randoms_to_quiz.php | 65 - .../classes/external/create_assignment.php | 245 ---- .../classes/external/create_lesson.php | 245 ---- .../classes/external/create_quiz.php | 195 --- .../classes/external/delete_lesson_plan.php | 54 - .../classes/external/get_all_overrides.php | 99 -- .../external/get_lesson_plans_by_course.php | 65 - .../external/get_question_stats_from_quiz.php | 156 -- .../external/get_questions_from_quiz.php | 66 - .../classes/external/get_rubric.php | 102 -- .../classes/external/get_rubric_grades.php | 107 -- .../classes/external/import_questions.php | 92 -- .../classes/external/update_lesson_plan.php | 76 - .../classes/external/write_grades.php | 110 -- .../classes/external/write_rubric_grades.php | 199 --- team_a/MoodlePlugin/learninglens/db/.DS_Store | Bin 6148 -> 0 bytes .../MoodlePlugin/learninglens/db/access.php | 15 - .../MoodlePlugin/learninglens/db/services.php | 160 -- .../lang/en/local_learninglens.php | 23 - team_a/MoodlePlugin/learninglens/version.php | 8 - .../local_adminer_moodle45_2025021700.zip | Bin 365706 -> 0 bytes team_a/README.md | 14 - team_a/pubspec.yaml | 31 - team_a/teamA/.example.env | 11 - team_a/teamA/.gitignore | 51 - team_a/teamA/.gitkeep | 0 team_a/teamA/README.md | 18 - team_a/teamA/analysis_options.yaml | 14 - team_a/teamA/assets/criteria.json | 84 -- team_a/teamA/assets/login_image.png | Bin 209378 -> 0 bytes team_a/teamA/devtools_options.yaml | 3 - team_a/teamA/lib/Api/experimental/README.md | 1 - .../assistant/textbased_function_caller.dart | 109 -- .../textbased_function_caller_view.dart | 218 --- .../assistant/textbased_llm_client.dart | 135 -- team_a/teamA/lib/Api/llm/claudeai_api.dart | 106 -- team_a/teamA/lib/Api/llm/enum/llm_enum.dart | 8 - team_a/teamA/lib/Api/llm/grok_api.dart | 192 --- .../lib/Api/llm/llm_api_modules_base.dart | 17 - team_a/teamA/lib/Api/llm/openai_api.dart | 191 --- team_a/teamA/lib/Api/llm/perplexity_api.dart | 168 --- team_a/teamA/lib/Api/llm/prompt_engine.dart | 133 -- .../constants/learning_lens.constants.dart | 4 - .../lib/Api/lms/enum/assignee_mode_enum.dart | 6 - .../lib/Api/lms/enum/course_state_enum.dart | 8 - .../Api/lms/enum/course_work_state_enum.dart | 7 - .../Api/lms/enum/course_work_type_enum.dart | 7 - team_a/teamA/lib/Api/lms/enum/lms_enum.dart | 4 - .../Api/lms/enum/preview_version_enum.dart | 5 - .../lms/enum/submission_mod_mode_enum.dart | 6 - .../lib/Api/lms/factory/lms_factory.dart | 34 - .../google_classroom_api.dart | 747 ---------- .../google_classroom/google_lms_service.dart | 1098 -------------- team_a/teamA/lib/Api/lms/lms_interface.dart | 66 - .../lib/Api/lms/moodle/classroom_service.dart | 1 - .../Api/lms/moodle/moodle_lms_service.dart | 1298 ----------------- .../lib/Api/lms/template/api_singleton.dart | 236 --- .../lib/Controller/assessment_generator.dart | 26 - .../teamA/lib/Controller/custom_appbar.dart | 195 --- .../teamA/lib/Controller/essay_generator.dart | 223 --- team_a/teamA/lib/Controller/g_bean.dart | 787 ---------- .../teamA/lib/Controller/html_converter.dart | 17 - .../teamA/lib/Controller/main_controller.dart | 20 - .../teamA/lib/Controller/xml_converter.dart | 141 -- team_a/teamA/lib/TestFiles/allThree.xml | 166 --- team_a/teamA/lib/TestFiles/multipleChoice.xml | 93 -- team_a/teamA/lib/TestFiles/shortAnswer.xml | 29 - team_a/teamA/lib/TestFiles/trueFalse.xml | 77 - team_a/teamA/lib/Views/about_page.dart | 70 - team_a/teamA/lib/Views/analytics_page.dart | 1280 ---------------- team_a/teamA/lib/Views/assessments_view.dart | 405 ----- team_a/teamA/lib/Views/chat_screen.dart | 248 ---- team_a/teamA/lib/Views/course_content.dart | 114 -- team_a/teamA/lib/Views/course_list.dart | 149 -- team_a/teamA/lib/Views/dashboard.dart | 480 ------ team_a/teamA/lib/Views/edit_questions.dart | 212 --- team_a/teamA/lib/Views/essay_edit_page.dart | 176 --- team_a/teamA/lib/Views/essay_generation.dart | 604 -------- team_a/teamA/lib/Views/essays_view.dart | 333 ----- .../teamA/lib/Views/g_assignment_create.dart | 298 ---- team_a/teamA/lib/Views/g_lesson_plan.dart | 725 --------- .../teamA/lib/Views/g_quiz_question_page.dart | 300 ---- team_a/teamA/lib/Views/iep_page.dart | 681 --------- team_a/teamA/lib/Views/lesson.dart | 58 - team_a/teamA/lib/Views/lesson_plans.dart | 914 ------------ team_a/teamA/lib/Views/m_assessment_view.dart | 158 -- team_a/teamA/lib/Views/quiz_generator.dart | 397 ----- .../teamA/lib/Views/send_essay_to_moodle.dart | 586 -------- .../teamA/lib/Views/send_quiz_to_moodle.dart | 632 -------- team_a/teamA/lib/Views/template_view.dart | 59 - team_a/teamA/lib/Views/user_settings.dart | 332 ----- team_a/teamA/lib/Views/view_quiz.dart | 113 -- .../lib/Views/view_submission_detail.dart | 377 ----- team_a/teamA/lib/Views/view_submissions.dart | 638 -------- team_a/teamA/lib/beans/answer.dart | 45 - team_a/teamA/lib/beans/assignment.dart | 97 -- team_a/teamA/lib/beans/assignment_form.dart | 27 - team_a/teamA/lib/beans/course.dart | 70 - team_a/teamA/lib/beans/criterion.dart | 38 - .../teamA/lib/beans/file_name_and_bytes.dart | 14 - .../teamA/lib/beans/g_question_form_data.dart | 27 - team_a/teamA/lib/beans/grade.dart | 45 - .../lib/beans/learning_lens_interface.dart | 8 - team_a/teamA/lib/beans/lesson_plan.dart | 46 - team_a/teamA/lib/beans/level.dart | 38 - team_a/teamA/lib/beans/moodle_rubric.dart | 39 - .../lib/beans/moodle_rubric_criteria.dart | 31 - team_a/teamA/lib/beans/override.dart | 80 - team_a/teamA/lib/beans/participant.dart | 58 - team_a/teamA/lib/beans/question.dart | 141 -- .../teamA/lib/beans/question_stat_type.dart | 35 - team_a/teamA/lib/beans/quiz.dart | 120 -- team_a/teamA/lib/beans/quiz_override | 26 - team_a/teamA/lib/beans/quiz_type.dart | 42 - team_a/teamA/lib/beans/rubric.dart | 60 - team_a/teamA/lib/beans/rubric_criteria.dart | 40 - team_a/teamA/lib/beans/submission.dart | 122 -- team_a/teamA/lib/beans/submission_status.dart | 74 - .../lib/beans/submission_with_grade.dart | 12 - team_a/teamA/lib/beans/user.dart | 29 - team_a/teamA/lib/beans/xml_consts.dart | 40 - team_a/teamA/lib/content_carousel.dart | 334 ----- team_a/teamA/lib/main.dart | 177 --- .../teamA/lib/notifiers/login_notifier.dart | 255 ---- team_a/teamA/lib/notifiers/login_state.dart | 9 - .../teamA/lib/notifiers/theme_notifier.dart | 14 - team_a/teamA/lib/services/api_service.dart | 109 -- .../lib/services/local_storage_service.dart | 240 --- team_a/teamA/lib/stub/html_stub.dart | 45 - team_a/teamA/pubspec.yaml | 51 - team_a/teamA/test/Views/dashboard_test.dart | 43 - .../services/local_storage_service_test.dart | 71 - team_b/README.md | 9 - team_b/yappy/.gitignore | 54 - team_b/yappy/.metadata | 45 - team_b/yappy/.vscode/settings.json | 3 - team_b/yappy/README.md | 39 - team_b/yappy/analysis_options.yaml | 33 - team_b/yappy/android/.gitignore | 13 - team_b/yappy/android/app/build.gradle | 43 - .../android/app/src/debug/AndroidManifest.xml | 8 - .../android/app/src/main/AndroidManifest.xml | 55 - .../com/spring2025/yappy/MainActivity.java | 35 - .../kotlin/com/example/yappy/MainActivity.kt | 5 - .../res/drawable-v21/launch_background.xml | 12 - .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 8069 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 4724 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 11861 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 19936 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 28860 -> 0 bytes .../app/src/main/res/values-night/styles.xml | 18 - .../app/src/main/res/values/styles.xml | 18 - .../app/src/profile/AndroidManifest.xml | 8 - team_b/yappy/android/build.gradle | 32 - team_b/yappy/android/gradle.properties | 3 - .../gradle/wrapper/gradle-wrapper.properties | 5 - team_b/yappy/android/settings.gradle | 25 - team_b/yappy/assets/icon/app_icon.png | Bin 96286 -> 0 bytes team_b/yappy/assets/models_config.json | 68 - team_b/yappy/assets/test_document.txt | 1 - team_b/yappy/assets/yappy_database.db | Bin 49152 -> 0 bytes team_b/yappy/ios/.gitignore | 34 - .../yappy/ios/Flutter/AppFrameworkInfo.plist | 26 - team_b/yappy/ios/Flutter/Debug.xcconfig | 1 - team_b/yappy/ios/Flutter/Release.xcconfig | 1 - .../ios/Runner.xcodeproj/project.pbxproj | 616 -------- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 98 -- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - team_b/yappy/ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 1 - .../Icon-App-1024x1024@1x.png | Bin 230178 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 1678 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 3723 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 6295 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 2538 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 6021 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 10398 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 3723 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 9314 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 15766 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 4969 -> 0 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 12442 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 5905 -> 0 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 14682 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 15766 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 26482 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 8069 -> 0 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 19936 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 8633 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 21312 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 24060 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 - .../ios/Runner/Base.lproj/Main.storyboard | 26 - team_b/yappy/ios/Runner/Info.plist | 49 - .../yappy/ios/Runner/Runner-Bridging-Header.h | 1 - .../yappy/ios/RunnerTests/RunnerTests.swift | 12 - team_b/yappy/lib/audiowave_widget.dart | 76 - team_b/yappy/lib/contact_page.dart | 131 -- team_b/yappy/lib/env.dart | 12 - team_b/yappy/lib/help.dart | 144 -- team_b/yappy/lib/home_page.dart | 137 -- team_b/yappy/lib/industry_menu.dart | 823 ----------- team_b/yappy/lib/login_page.dart | 132 -- team_b/yappy/lib/main.dart | 73 - team_b/yappy/lib/mechanic.dart | 75 - team_b/yappy/lib/medical_doctor.dart | 70 - team_b/yappy/lib/medical_patient.dart | 70 - team_b/yappy/lib/restaurant.dart | 62 - team_b/yappy/lib/search_bar_widget.dart | 114 -- .../yappy/lib/services/database_helper.dart | 668 --------- team_b/yappy/lib/services/file_handler.dart | 155 -- .../lib/services/mechanic_api_module.dart | 102 -- .../lib/services/medical_api_module.dart | 95 -- team_b/yappy/lib/services/model_manager.dart | 578 -------- team_b/yappy/lib/services/offline_model.dart | 25 - team_b/yappy/lib/services/online_model.dart | 24 - team_b/yappy/lib/services/openai_helper.dart | 429 ------ .../lib/services/restaurant_api_module.dart | 83 -- team_b/yappy/lib/services/speaker_model.dart | 12 - team_b/yappy/lib/services/speech_isolate.dart | 326 ----- team_b/yappy/lib/services/speech_state.dart | 718 --------- team_b/yappy/lib/services/toast_service.dart | 67 - team_b/yappy/lib/services/utils.dart | 37 - team_b/yappy/lib/settings_page.dart | 253 ---- team_b/yappy/lib/sign_up_page.dart | 113 -- team_b/yappy/lib/toast_widget.dart | 146 -- team_b/yappy/lib/tool_bar.dart | 129 -- team_b/yappy/lib/transcription_box.dart | 78 - team_b/yappy/lib/tutorial_page.dart | 165 --- team_b/yappy/linux/.gitignore | 3 - team_b/yappy/linux/CMakeLists.txt | 128 -- team_b/yappy/linux/flutter/CMakeLists.txt | 88 -- team_b/yappy/linux/runner/CMakeLists.txt | 26 - team_b/yappy/linux/runner/main.cc | 6 - team_b/yappy/linux/runner/my_application.cc | 130 -- team_b/yappy/linux/runner/my_application.h | 18 - team_b/yappy/macos/.gitignore | 9 - .../macos/Flutter/Flutter-Debug.xcconfig | 1 - .../macos/Flutter/Flutter-Release.xcconfig | 1 - .../macos/Runner.xcodeproj/project.pbxproj | 705 --------- .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 98 -- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - team_b/yappy/macos/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 68 - .../AppIcon.appiconset/app_icon_1024.png | Bin 102994 -> 0 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 5680 -> 0 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 520 -> 0 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 14142 -> 0 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1066 -> 0 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 36406 -> 0 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2218 -> 0 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 ----- .../macos/Runner/Configs/AppInfo.xcconfig | 14 - .../yappy/macos/Runner/Configs/Debug.xcconfig | 2 - .../macos/Runner/Configs/Release.xcconfig | 2 - .../macos/Runner/Configs/Warnings.xcconfig | 13 - .../macos/Runner/DebugProfile.entitlements | 12 - team_b/yappy/macos/Runner/Info.plist | 32 - .../macos/Runner/MainFlutterWindow.swift | 15 - .../yappy/macos/Runner/Release.entitlements | 8 - .../yappy/macos/RunnerTests/RunnerTests.swift | 12 - team_b/yappy/pubspec.yaml | 112 -- team_b/yappy/test/audiowave_widget_test.dart | 58 - team_b/yappy/test/contact_page_test.dart | 45 - team_b/yappy/test/database_helper.mocks.dart | 514 ------- team_b/yappy/test/database_helper_test.dart | 67 - team_b/yappy/test/file_handler_test.dart | 89 -- team_b/yappy/test/help_test.dart | 108 -- team_b/yappy/test/home_page_test.dart | 50 - team_b/yappy/test/login_page_test.dart | 54 - team_b/yappy/test/main_test.dart | 77 - team_b/yappy/test/mechanic_test.dart | 36 - team_b/yappy/test/medical_doctor.dart | 36 - team_b/yappy/test/medical_doctor_test.dart | 48 - team_b/yappy/test/medical_patient_test.dart | 36 - team_b/yappy/test/restaurant_test.dart | 36 - team_b/yappy/test/sign_up_page_test.dart | 86 -- team_b/yappy/test/transcription_box_test.dart | 64 - team_b/yappy/test/tutorial_page_test.dart | 110 -- team_b/yappy/web/favicon.png | Bin 917 -> 0 bytes team_b/yappy/web/icons/Icon-192.png | Bin 5292 -> 0 bytes team_b/yappy/web/icons/Icon-512.png | Bin 8252 -> 0 bytes team_b/yappy/web/icons/Icon-maskable-192.png | Bin 5594 -> 0 bytes team_b/yappy/web/icons/Icon-maskable-512.png | Bin 20998 -> 0 bytes team_b/yappy/web/index.html | 38 - team_b/yappy/web/manifest.json | 35 - team_b/yappy/windows/.gitignore | 39 - team_b/yappy/windows/CMakeLists.txt | 108 -- team_b/yappy/windows/flutter/CMakeLists.txt | 109 -- team_b/yappy/windows/runner/CMakeLists.txt | 40 - team_b/yappy/windows/runner/Runner.rc | 121 -- .../yappy/windows/runner/flutter_window.cpp | 71 - team_b/yappy/windows/runner/flutter_window.h | 33 - team_b/yappy/windows/runner/main.cpp | 43 - team_b/yappy/windows/runner/resource.h | 16 - .../windows/runner/resources/app_icon.ico | Bin 33772 -> 0 bytes .../yappy/windows/runner/runner.exe.manifest | 14 - team_b/yappy/windows/runner/utils.cpp | 65 - team_b/yappy/windows/runner/utils.h | 19 - team_b/yappy/windows/runner/win32_window.cpp | 288 ---- team_b/yappy/windows/runner/win32_window.h | 102 -- 321 files changed, 34492 deletions(-) delete mode 100644 team_a/.gitignore delete mode 100644 team_a/LICENSE delete mode 100644 team_a/MoodlePlugin/.DS_Store delete mode 100644 team_a/MoodlePlugin/learninglens/.DS_Store delete mode 100644 team_a/MoodlePlugin/learninglens/classes/.DS_Store delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/add_essay_override.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/add_quiz_override.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/add_type_randoms_to_quiz.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/create_assignment.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/create_lesson.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/create_quiz.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/delete_lesson_plan.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_all_overrides.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_lesson_plans_by_course.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_question_stats_from_quiz.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_questions_from_quiz.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_rubric.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/get_rubric_grades.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/import_questions.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/update_lesson_plan.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/write_grades.php delete mode 100644 team_a/MoodlePlugin/learninglens/classes/external/write_rubric_grades.php delete mode 100644 team_a/MoodlePlugin/learninglens/db/.DS_Store delete mode 100644 team_a/MoodlePlugin/learninglens/db/access.php delete mode 100644 team_a/MoodlePlugin/learninglens/db/services.php delete mode 100644 team_a/MoodlePlugin/learninglens/lang/en/local_learninglens.php delete mode 100644 team_a/MoodlePlugin/learninglens/version.php delete mode 100644 team_a/MoodlePlugin/local_adminer_moodle45_2025021700.zip delete mode 100644 team_a/README.md delete mode 100644 team_a/pubspec.yaml delete mode 100644 team_a/teamA/.example.env delete mode 100644 team_a/teamA/.gitignore delete mode 100644 team_a/teamA/.gitkeep delete mode 100644 team_a/teamA/README.md delete mode 100644 team_a/teamA/analysis_options.yaml delete mode 100644 team_a/teamA/assets/criteria.json delete mode 100644 team_a/teamA/assets/login_image.png delete mode 100644 team_a/teamA/devtools_options.yaml delete mode 100644 team_a/teamA/lib/Api/experimental/README.md delete mode 100644 team_a/teamA/lib/Api/experimental/assistant/textbased_function_caller.dart delete mode 100644 team_a/teamA/lib/Api/experimental/assistant/textbased_function_caller_view.dart delete mode 100644 team_a/teamA/lib/Api/experimental/assistant/textbased_llm_client.dart delete mode 100644 team_a/teamA/lib/Api/llm/claudeai_api.dart delete mode 100644 team_a/teamA/lib/Api/llm/enum/llm_enum.dart delete mode 100644 team_a/teamA/lib/Api/llm/grok_api.dart delete mode 100644 team_a/teamA/lib/Api/llm/llm_api_modules_base.dart delete mode 100644 team_a/teamA/lib/Api/llm/openai_api.dart delete mode 100644 team_a/teamA/lib/Api/llm/perplexity_api.dart delete mode 100644 team_a/teamA/lib/Api/llm/prompt_engine.dart delete mode 100644 team_a/teamA/lib/Api/lms/constants/learning_lens.constants.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/assignee_mode_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/course_state_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/course_work_state_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/course_work_type_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/lms_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/preview_version_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/enum/submission_mod_mode_enum.dart delete mode 100644 team_a/teamA/lib/Api/lms/factory/lms_factory.dart delete mode 100644 team_a/teamA/lib/Api/lms/google_classroom/google_classroom_api.dart delete mode 100644 team_a/teamA/lib/Api/lms/google_classroom/google_lms_service.dart delete mode 100644 team_a/teamA/lib/Api/lms/lms_interface.dart delete mode 100644 team_a/teamA/lib/Api/lms/moodle/classroom_service.dart delete mode 100644 team_a/teamA/lib/Api/lms/moodle/moodle_lms_service.dart delete mode 100644 team_a/teamA/lib/Api/lms/template/api_singleton.dart delete mode 100644 team_a/teamA/lib/Controller/assessment_generator.dart delete mode 100644 team_a/teamA/lib/Controller/custom_appbar.dart delete mode 100644 team_a/teamA/lib/Controller/essay_generator.dart delete mode 100644 team_a/teamA/lib/Controller/g_bean.dart delete mode 100644 team_a/teamA/lib/Controller/html_converter.dart delete mode 100644 team_a/teamA/lib/Controller/main_controller.dart delete mode 100644 team_a/teamA/lib/Controller/xml_converter.dart delete mode 100644 team_a/teamA/lib/TestFiles/allThree.xml delete mode 100644 team_a/teamA/lib/TestFiles/multipleChoice.xml delete mode 100644 team_a/teamA/lib/TestFiles/shortAnswer.xml delete mode 100644 team_a/teamA/lib/TestFiles/trueFalse.xml delete mode 100644 team_a/teamA/lib/Views/about_page.dart delete mode 100644 team_a/teamA/lib/Views/analytics_page.dart delete mode 100644 team_a/teamA/lib/Views/assessments_view.dart delete mode 100644 team_a/teamA/lib/Views/chat_screen.dart delete mode 100644 team_a/teamA/lib/Views/course_content.dart delete mode 100644 team_a/teamA/lib/Views/course_list.dart delete mode 100644 team_a/teamA/lib/Views/dashboard.dart delete mode 100644 team_a/teamA/lib/Views/edit_questions.dart delete mode 100644 team_a/teamA/lib/Views/essay_edit_page.dart delete mode 100644 team_a/teamA/lib/Views/essay_generation.dart delete mode 100644 team_a/teamA/lib/Views/essays_view.dart delete mode 100644 team_a/teamA/lib/Views/g_assignment_create.dart delete mode 100644 team_a/teamA/lib/Views/g_lesson_plan.dart delete mode 100644 team_a/teamA/lib/Views/g_quiz_question_page.dart delete mode 100644 team_a/teamA/lib/Views/iep_page.dart delete mode 100644 team_a/teamA/lib/Views/lesson.dart delete mode 100644 team_a/teamA/lib/Views/lesson_plans.dart delete mode 100644 team_a/teamA/lib/Views/m_assessment_view.dart delete mode 100644 team_a/teamA/lib/Views/quiz_generator.dart delete mode 100644 team_a/teamA/lib/Views/send_essay_to_moodle.dart delete mode 100644 team_a/teamA/lib/Views/send_quiz_to_moodle.dart delete mode 100644 team_a/teamA/lib/Views/template_view.dart delete mode 100644 team_a/teamA/lib/Views/user_settings.dart delete mode 100644 team_a/teamA/lib/Views/view_quiz.dart delete mode 100644 team_a/teamA/lib/Views/view_submission_detail.dart delete mode 100644 team_a/teamA/lib/Views/view_submissions.dart delete mode 100644 team_a/teamA/lib/beans/answer.dart delete mode 100644 team_a/teamA/lib/beans/assignment.dart delete mode 100644 team_a/teamA/lib/beans/assignment_form.dart delete mode 100644 team_a/teamA/lib/beans/course.dart delete mode 100644 team_a/teamA/lib/beans/criterion.dart delete mode 100644 team_a/teamA/lib/beans/file_name_and_bytes.dart delete mode 100644 team_a/teamA/lib/beans/g_question_form_data.dart delete mode 100644 team_a/teamA/lib/beans/grade.dart delete mode 100644 team_a/teamA/lib/beans/learning_lens_interface.dart delete mode 100644 team_a/teamA/lib/beans/lesson_plan.dart delete mode 100644 team_a/teamA/lib/beans/level.dart delete mode 100644 team_a/teamA/lib/beans/moodle_rubric.dart delete mode 100644 team_a/teamA/lib/beans/moodle_rubric_criteria.dart delete mode 100644 team_a/teamA/lib/beans/override.dart delete mode 100644 team_a/teamA/lib/beans/participant.dart delete mode 100644 team_a/teamA/lib/beans/question.dart delete mode 100644 team_a/teamA/lib/beans/question_stat_type.dart delete mode 100644 team_a/teamA/lib/beans/quiz.dart delete mode 100644 team_a/teamA/lib/beans/quiz_override delete mode 100644 team_a/teamA/lib/beans/quiz_type.dart delete mode 100644 team_a/teamA/lib/beans/rubric.dart delete mode 100644 team_a/teamA/lib/beans/rubric_criteria.dart delete mode 100644 team_a/teamA/lib/beans/submission.dart delete mode 100644 team_a/teamA/lib/beans/submission_status.dart delete mode 100644 team_a/teamA/lib/beans/submission_with_grade.dart delete mode 100644 team_a/teamA/lib/beans/user.dart delete mode 100644 team_a/teamA/lib/beans/xml_consts.dart delete mode 100644 team_a/teamA/lib/content_carousel.dart delete mode 100644 team_a/teamA/lib/main.dart delete mode 100644 team_a/teamA/lib/notifiers/login_notifier.dart delete mode 100644 team_a/teamA/lib/notifiers/login_state.dart delete mode 100644 team_a/teamA/lib/notifiers/theme_notifier.dart delete mode 100644 team_a/teamA/lib/services/api_service.dart delete mode 100644 team_a/teamA/lib/services/local_storage_service.dart delete mode 100644 team_a/teamA/lib/stub/html_stub.dart delete mode 100644 team_a/teamA/pubspec.yaml delete mode 100644 team_a/teamA/test/Views/dashboard_test.dart delete mode 100644 team_a/teamA/test/services/local_storage_service_test.dart delete mode 100644 team_b/README.md delete mode 100644 team_b/yappy/.gitignore delete mode 100644 team_b/yappy/.metadata delete mode 100644 team_b/yappy/.vscode/settings.json delete mode 100644 team_b/yappy/README.md delete mode 100644 team_b/yappy/analysis_options.yaml delete mode 100644 team_b/yappy/android/.gitignore delete mode 100644 team_b/yappy/android/app/build.gradle delete mode 100644 team_b/yappy/android/app/src/debug/AndroidManifest.xml delete mode 100644 team_b/yappy/android/app/src/main/AndroidManifest.xml delete mode 100644 team_b/yappy/android/app/src/main/java/com/spring2025/yappy/MainActivity.java delete mode 100644 team_b/yappy/android/app/src/main/kotlin/com/example/yappy/MainActivity.kt delete mode 100644 team_b/yappy/android/app/src/main/res/drawable-v21/launch_background.xml delete mode 100644 team_b/yappy/android/app/src/main/res/drawable/launch_background.xml delete mode 100644 team_b/yappy/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 team_b/yappy/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 team_b/yappy/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 team_b/yappy/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 team_b/yappy/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 team_b/yappy/android/app/src/main/res/values-night/styles.xml delete mode 100644 team_b/yappy/android/app/src/main/res/values/styles.xml delete mode 100644 team_b/yappy/android/app/src/profile/AndroidManifest.xml delete mode 100644 team_b/yappy/android/build.gradle delete mode 100644 team_b/yappy/android/gradle.properties delete mode 100644 team_b/yappy/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 team_b/yappy/android/settings.gradle delete mode 100644 team_b/yappy/assets/icon/app_icon.png delete mode 100644 team_b/yappy/assets/models_config.json delete mode 100644 team_b/yappy/assets/test_document.txt delete mode 100644 team_b/yappy/assets/yappy_database.db delete mode 100644 team_b/yappy/ios/.gitignore delete mode 100644 team_b/yappy/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 team_b/yappy/ios/Flutter/Debug.xcconfig delete mode 100644 team_b/yappy/ios/Flutter/Release.xcconfig delete mode 100644 team_b/yappy/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 team_b/yappy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 team_b/yappy/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 team_b/yappy/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 team_b/yappy/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 team_b/yappy/ios/Runner/AppDelegate.swift delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 team_b/yappy/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 team_b/yappy/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 team_b/yappy/ios/Runner/Info.plist delete mode 100644 team_b/yappy/ios/Runner/Runner-Bridging-Header.h delete mode 100644 team_b/yappy/ios/RunnerTests/RunnerTests.swift delete mode 100644 team_b/yappy/lib/audiowave_widget.dart delete mode 100644 team_b/yappy/lib/contact_page.dart delete mode 100644 team_b/yappy/lib/env.dart delete mode 100644 team_b/yappy/lib/help.dart delete mode 100644 team_b/yappy/lib/home_page.dart delete mode 100644 team_b/yappy/lib/industry_menu.dart delete mode 100644 team_b/yappy/lib/login_page.dart delete mode 100644 team_b/yappy/lib/main.dart delete mode 100644 team_b/yappy/lib/mechanic.dart delete mode 100644 team_b/yappy/lib/medical_doctor.dart delete mode 100644 team_b/yappy/lib/medical_patient.dart delete mode 100644 team_b/yappy/lib/restaurant.dart delete mode 100644 team_b/yappy/lib/search_bar_widget.dart delete mode 100644 team_b/yappy/lib/services/database_helper.dart delete mode 100644 team_b/yappy/lib/services/file_handler.dart delete mode 100644 team_b/yappy/lib/services/mechanic_api_module.dart delete mode 100644 team_b/yappy/lib/services/medical_api_module.dart delete mode 100644 team_b/yappy/lib/services/model_manager.dart delete mode 100644 team_b/yappy/lib/services/offline_model.dart delete mode 100644 team_b/yappy/lib/services/online_model.dart delete mode 100644 team_b/yappy/lib/services/openai_helper.dart delete mode 100644 team_b/yappy/lib/services/restaurant_api_module.dart delete mode 100644 team_b/yappy/lib/services/speaker_model.dart delete mode 100644 team_b/yappy/lib/services/speech_isolate.dart delete mode 100644 team_b/yappy/lib/services/speech_state.dart delete mode 100644 team_b/yappy/lib/services/toast_service.dart delete mode 100644 team_b/yappy/lib/services/utils.dart delete mode 100644 team_b/yappy/lib/settings_page.dart delete mode 100644 team_b/yappy/lib/sign_up_page.dart delete mode 100644 team_b/yappy/lib/toast_widget.dart delete mode 100644 team_b/yappy/lib/tool_bar.dart delete mode 100644 team_b/yappy/lib/transcription_box.dart delete mode 100644 team_b/yappy/lib/tutorial_page.dart delete mode 100644 team_b/yappy/linux/.gitignore delete mode 100644 team_b/yappy/linux/CMakeLists.txt delete mode 100644 team_b/yappy/linux/flutter/CMakeLists.txt delete mode 100644 team_b/yappy/linux/runner/CMakeLists.txt delete mode 100644 team_b/yappy/linux/runner/main.cc delete mode 100644 team_b/yappy/linux/runner/my_application.cc delete mode 100644 team_b/yappy/linux/runner/my_application.h delete mode 100644 team_b/yappy/macos/.gitignore delete mode 100644 team_b/yappy/macos/Flutter/Flutter-Debug.xcconfig delete mode 100644 team_b/yappy/macos/Flutter/Flutter-Release.xcconfig delete mode 100644 team_b/yappy/macos/Runner.xcodeproj/project.pbxproj delete mode 100644 team_b/yappy/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 team_b/yappy/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 team_b/yappy/macos/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 team_b/yappy/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 team_b/yappy/macos/Runner/AppDelegate.swift delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png delete mode 100644 team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png delete mode 100644 team_b/yappy/macos/Runner/Base.lproj/MainMenu.xib delete mode 100644 team_b/yappy/macos/Runner/Configs/AppInfo.xcconfig delete mode 100644 team_b/yappy/macos/Runner/Configs/Debug.xcconfig delete mode 100644 team_b/yappy/macos/Runner/Configs/Release.xcconfig delete mode 100644 team_b/yappy/macos/Runner/Configs/Warnings.xcconfig delete mode 100644 team_b/yappy/macos/Runner/DebugProfile.entitlements delete mode 100644 team_b/yappy/macos/Runner/Info.plist delete mode 100644 team_b/yappy/macos/Runner/MainFlutterWindow.swift delete mode 100644 team_b/yappy/macos/Runner/Release.entitlements delete mode 100644 team_b/yappy/macos/RunnerTests/RunnerTests.swift delete mode 100644 team_b/yappy/pubspec.yaml delete mode 100644 team_b/yappy/test/audiowave_widget_test.dart delete mode 100644 team_b/yappy/test/contact_page_test.dart delete mode 100644 team_b/yappy/test/database_helper.mocks.dart delete mode 100644 team_b/yappy/test/database_helper_test.dart delete mode 100644 team_b/yappy/test/file_handler_test.dart delete mode 100644 team_b/yappy/test/help_test.dart delete mode 100644 team_b/yappy/test/home_page_test.dart delete mode 100644 team_b/yappy/test/login_page_test.dart delete mode 100644 team_b/yappy/test/main_test.dart delete mode 100644 team_b/yappy/test/mechanic_test.dart delete mode 100644 team_b/yappy/test/medical_doctor.dart delete mode 100644 team_b/yappy/test/medical_doctor_test.dart delete mode 100644 team_b/yappy/test/medical_patient_test.dart delete mode 100644 team_b/yappy/test/restaurant_test.dart delete mode 100644 team_b/yappy/test/sign_up_page_test.dart delete mode 100644 team_b/yappy/test/transcription_box_test.dart delete mode 100644 team_b/yappy/test/tutorial_page_test.dart delete mode 100644 team_b/yappy/web/favicon.png delete mode 100644 team_b/yappy/web/icons/Icon-192.png delete mode 100644 team_b/yappy/web/icons/Icon-512.png delete mode 100644 team_b/yappy/web/icons/Icon-maskable-192.png delete mode 100644 team_b/yappy/web/icons/Icon-maskable-512.png delete mode 100644 team_b/yappy/web/index.html delete mode 100644 team_b/yappy/web/manifest.json delete mode 100644 team_b/yappy/windows/.gitignore delete mode 100644 team_b/yappy/windows/CMakeLists.txt delete mode 100644 team_b/yappy/windows/flutter/CMakeLists.txt delete mode 100644 team_b/yappy/windows/runner/CMakeLists.txt delete mode 100644 team_b/yappy/windows/runner/Runner.rc delete mode 100644 team_b/yappy/windows/runner/flutter_window.cpp delete mode 100644 team_b/yappy/windows/runner/flutter_window.h delete mode 100644 team_b/yappy/windows/runner/main.cpp delete mode 100644 team_b/yappy/windows/runner/resource.h delete mode 100644 team_b/yappy/windows/runner/resources/app_icon.ico delete mode 100644 team_b/yappy/windows/runner/runner.exe.manifest delete mode 100644 team_b/yappy/windows/runner/utils.cpp delete mode 100644 team_b/yappy/windows/runner/utils.h delete mode 100644 team_b/yappy/windows/runner/win32_window.cpp delete mode 100644 team_b/yappy/windows/runner/win32_window.h diff --git a/team_a/.gitignore b/team_a/.gitignore deleted file mode 100644 index 25fd9094..00000000 --- a/team_a/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# See https://www.dartlang.org/guides/libraries/private-files - -# Files and directories created by pub -.dart_tool/ -.packages -build/ -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -doc/api/ - -# dotenv environment variables file -.env* - -# Avoid committing generated Javascript files: -*.dart.js -*.info.json # Produced by the --dump-info flag. -*.js # When generated by dart2js. Don't specify *.js if your - # project includes source files written in JavaScript. -*.js_ -*.js.deps -*.js.map - -.flutter-plugins -.flutter-plugins-dependencies -.vs/* -.vscode/ -.vs* -*/ios/ -linux/ -macos/ -web/ -windows/ -Flutter/ -teama/linux/* -teama/macos/* -teama/windows/* -teama/assets/api-keys.json -teama/android/ diff --git a/team_a/LICENSE b/team_a/LICENSE deleted file mode 100644 index 0e259d42..00000000 --- a/team_a/LICENSE +++ /dev/null @@ -1,121 +0,0 @@ -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. diff --git a/team_a/MoodlePlugin/.DS_Store b/team_a/MoodlePlugin/.DS_Store deleted file mode 100644 index e9963cd3c92eb05fcf33d228cffc88c7fe8991bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!Ab)$5S_HucBw)S3VK`cT5wwh5id)vKj4ZURO&8U>f)M|Zfg&vuy_3-f5h)` zCdn$L_ToXL%)sPLCNmrIvSbnf5S>Zf0%!n04VAFuVDp2}IO&pjaQWas$do)awZ0va-qExPIY*wpIwO+js9@R7$ zhvP}s2}ifoyHYBR3OkIhlm4{V*g02n944|q(g{i2$B?_5M8;~`Q4<+wIyW!_j#G1b zjs4lI<#}GyZJ!*?o9^tijrQ?rdp>t+y9bA7m%XR-S*lmVs=yym%eKV=-q2XNz?Wbo zQzZu&Q{)$UjLZNtzznQ01NO+P)z^59yfkKj8TcIobUwJKgucbxpguaVq3a`!R|rYa zrndy4Ytgru8^jS5VNwxIs<2NCVbam>+Bn~0ZqTHI&@gX;gq>i7R*68D$^W?-!t5S4Dw?ckDZZCzR%)mj(z0hNT}a)VzfXy{Um fu~drpP_>}nB?Hm7m>Wb73SR^?4cssTf6Blo3s6t0 diff --git a/team_a/MoodlePlugin/learninglens/.DS_Store b/team_a/MoodlePlugin/learninglens/.DS_Store deleted file mode 100644 index b69e9e2d3c4fc5ca0360774f16ec210d224dd46d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK&2G~`5T4Bsjuj#008+VG;##S02%w0I70L_XiXPf3*l`3F#v8>+bFd=$3_K9L z2+z}Rb~lys*JFgpPPF@t=V$HtZ0%-Ir}fZv@%Bg!bE0>6j%Cu4a2#FH#7X1@Pd)as4q6UT9#wsRYPm5Xo| z&E~}*nqKqOrIcB`(xdoOI$jJr&)&;?7Nz-ksuI#CfcFOvgE25zX;fPWCe;D}8!#(@&b41D1hx2I~5< z!{`5p{r&%XlD)DFSO)$p21Mf`ycnP)bGB|3$7ijF@fm}K<0_30DNxi=j95O3PcW3g Y?y&+43|1Opf!IF+iUvDb1`f)=JwPgrLI3~& diff --git a/team_a/MoodlePlugin/learninglens/classes/.DS_Store b/team_a/MoodlePlugin/learninglens/classes/.DS_Store deleted file mode 100644 index 6fc5268472768f72a65c5c8f175fdb6dbc079f3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5Z-O8O(;SS3OxqA7Ho@(#Y>3w1&ruHr6#6mFz%KlH9{%mtS{t~_&m<+ zZbgZn1d%cWGv9Q6Hr+2}x5F6Y-Yn`f)@F=Zpolda%r}C0)QZ$hqz=f{8YvSjU`beH z(@Hf3{v!kU?kqN8Pb>%f>HUR?3?cU#PLnvxd%ZVat2frxn@zjfYF_zwvhedDpJiT< zUf`!wDU)#N2jN*fDaP&1BPsGA7L!yp#L)ywF3)2T$-~Xs@pYI>^ zy3THYZ_#z;!vXrk!D3-sTiZK_C*%9%LC9xKCWqghk`04Pcmb!fuPD1oLinE8R7pPi zsYs-_h1_z{&)5O++SYp~R)+Zi{*2RBdVW9D?|${BYx zk|hR+fv*hU><7}u`~Udo`Ck>0AqI$n)ntG-M*hfyy_vhUvP-;c9nfn~6s#*Xezbt2 iu41UgtGENI1mX@lfUdz(BSb*xkAR|q3^DMh47>xe_fzKp diff --git a/team_a/MoodlePlugin/learninglens/classes/external/add_essay_override.php b/team_a/MoodlePlugin/learninglens/classes/external/add_essay_override.php deleted file mode 100644 index 87f6cc25..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/add_essay_override.php +++ /dev/null @@ -1,80 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_value; -use external_api; - -class add_essay_override extends external_api { - - /** - * Define parameters for the external function - */ - public static function execute_parameters() { - return new external_function_parameters([ - 'assignid' => new external_value(PARAM_INT, 'ID of the essay'), - 'userid' => new external_value(PARAM_INT, 'User ID (null if group override)', VALUE_DEFAULT, null), - 'groupid' => new external_value(PARAM_INT, 'Group ID (null if user override)', VALUE_DEFAULT, null), - 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'Time when essay opens (null for default)', VALUE_DEFAULT, null), - 'duedate' => new external_value(PARAM_INT, 'Time when essay closes (null for default)', VALUE_DEFAULT, null), - 'cutoffdate' => new external_value(PARAM_INT, 'Time when essay submission is no longer allowed (null for default)', VALUE_DEFAULT, null), - 'timelimit' => new external_value(PARAM_INT, 'Essay time limit in seconds (null for default)', VALUE_DEFAULT, null), - 'sortorder' => new external_value(PARAM_INT, 'Essay sort order (null for default)', VALUE_DEFAULT, null), - ]); - } - - /** - * Inserts a new quiz override record - */ - public static function execute($assignid, $userid = null, $groupid = null, $allowsubmissionsfromdate = null, $duedate = null, $cutoffdate = null, $timelimit = null, $sortorder = null) { - global $DB; - - // Validate parameters - $params = self::validate_parameters(self::execute_parameters(), [ - 'assignid' => $assignid, - 'userid' => $userid, - 'groupid' => $groupid, - 'allowsubmissionsfromdate' => $allowsubmissionsfromdate, - 'duedate' => $duedate, - 'cutoffdate' => $cutoffdate, - 'timelimit' => $timelimit, - 'sortorder' => $sortorder, - ]); - - // Ensure either a user or group ID is provided - if (empty($params['userid']) && empty($params['groupid'])) { - throw new \moodle_exception('invalidoverride', 'local_learninglens', '', 'Either a userid or groupid must be provided.'); - } - - // Prepare data for insertion - $record = new \stdClass(); - $record->assignid = $params['assignid']; - $record->userid = $params['userid']; - $record->groupid = $params['groupid']; - $record->allowsubmissionsfromdate = $params['allowsubmissionsfromdate']; - $record->duedate = $params['duedate']; - $record->cutoffdate = $params['cutoffdate']; - $record->timelimit = $params['timelimit']; - $record->sortorder = $params['sortorder']; - - // Insert into the database - $overrideid = $DB->insert_record('assign_overrides', $record); - - // Return the inserted override ID - return ['overrideid' => $overrideid]; - } - - /** - * Defines the return structure - */ - public static function execute_returns() { - return new external_single_structure([ - 'overrideid' => new external_value(PARAM_INT, 'ID of the created quiz override'), - ]); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/add_quiz_override.php b/team_a/MoodlePlugin/learninglens/classes/external/add_quiz_override.php deleted file mode 100644 index 0d9a9116..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/add_quiz_override.php +++ /dev/null @@ -1,80 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_value; -use external_api; - -class add_quiz_override extends external_api { - - /** - * Define parameters for the external function - */ - public static function execute_parameters() { - return new external_function_parameters([ - 'quizid' => new external_value(PARAM_INT, 'ID of the quiz'), - 'userid' => new external_value(PARAM_INT, 'User ID (null if group override)', VALUE_DEFAULT, null), - 'groupid' => new external_value(PARAM_INT, 'Group ID (null if user override)', VALUE_DEFAULT, null), - 'timeopen' => new external_value(PARAM_INT, 'Time when quiz opens (null for default)', VALUE_DEFAULT, null), - 'timeclose' => new external_value(PARAM_INT, 'Time when quiz closes (null for default)', VALUE_DEFAULT, null), - 'timelimit' => new external_value(PARAM_INT, 'Quiz time limit in seconds (null for default)', VALUE_DEFAULT, null), - 'attempts' => new external_value(PARAM_INT, 'Allowed attempts (null for default)', VALUE_DEFAULT, null), - 'password' => new external_value(PARAM_TEXT, 'Quiz password (null for default)', VALUE_DEFAULT, null), - ]); - } - - /** - * Inserts a new quiz override record - */ - public static function execute($quizid, $userid = null, $groupid = null, $timeopen = null, $timeclose = null, $timelimit = null, $attempts = null, $password = null) { - global $DB; - - // Validate parameters - $params = self::validate_parameters(self::execute_parameters(), [ - 'quizid' => $quizid, - 'userid' => $userid, - 'groupid' => $groupid, - 'timeopen' => $timeopen, - 'timeclose' => $timeclose, - 'timelimit' => $timelimit, - 'attempts' => $attempts, - 'password' => $password, - ]); - - // Ensure either a user or group ID is provided - if (empty($params['userid']) && empty($params['groupid'])) { - throw new \moodle_exception('invalidoverride', 'local_learninglens', '', 'Either a userid or groupid must be provided.'); - } - - // Prepare data for insertion - $record = new \stdClass(); - $record->quiz = $params['quizid']; - $record->userid = $params['userid']; - $record->groupid = $params['groupid']; - $record->timeopen = $params['timeopen']; - $record->timeclose = $params['timeclose']; - $record->timelimit = $params['timelimit']; - $record->attempts = $params['attempts']; - $record->password = $params['password']; - - // Insert into the database - $overrideid = $DB->insert_record('quiz_overrides', $record); - - // Return the inserted override ID - return ['overrideid' => $overrideid]; - } - - /** - * Defines the return structure - */ - public static function execute_returns() { - return new external_single_structure([ - 'overrideid' => new external_value(PARAM_INT, 'ID of the created quiz override'), - ]); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/add_type_randoms_to_quiz.php b/team_a/MoodlePlugin/learninglens/classes/external/add_type_randoms_to_quiz.php deleted file mode 100644 index 04ff2598..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/add_type_randoms_to_quiz.php +++ /dev/null @@ -1,65 +0,0 @@ -libdir . '/externallib.php'); -require_once($CFG->dirroot . '/mod/quiz/locallib.php'); - -use context_course; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_multiple_structure; -use core_external\external_single_structure; -use core_external\external_value; -use core_question\local\bank\question_edit_contexts; -use qformat_xml; - -class add_type_randoms_to_quiz extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'quizid' => new external_value(PARAM_INT, 'The quiz ID'), - 'categoryid' => new external_value(PARAM_INT, 'Question Category ID'), - 'numquestions' => new external_value(PARAM_INT, 'Number of Questions to add') - ]); - } - - public static function execute_returns() { - return new external_value(PARAM_BOOL, 'Returns TRUE if succesful'); - - } - - public static function execute(int $quizid, int $categoryid, int $numquestions): bool { - global $DB; - - $params = self::validate_parameters(self::execute_parameters(), [ - 'quizid' => $quizid, - 'categoryid' => $categoryid, - 'numquestions' => $numquestions, - ]); - - try { - // Fetch the quiz object. - $quiz = $DB->get_record('quiz', ['id' => $quizid], '*', MUST_EXIST); - - // Fetch the module context for the quiz. - $cm = get_coursemodule_from_instance('quiz', $quizid, $quiz->course, false, MUST_EXIST); - $context = \context_module::instance($cm->id); - - quiz_add_random_questions($quiz, $addonpage = 0, $categoryid, $numquestions, false); - - // Recalculate the sumgrades automatically using Moodle's built-in function - quiz_update_sumgrades($quiz); - quiz_grade_item_update($quiz); - - return true; // Return true on successful addition. - - } catch (Exception $e) { - // Log the error message or handle the error as needed. - debugging('Error adding random questions to quiz: ' . $e->getMessage()); - return false; // Return false if an error occurs. - } - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/create_assignment.php b/team_a/MoodlePlugin/learninglens/classes/external/create_assignment.php deleted file mode 100644 index f708f6ac..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/create_assignment.php +++ /dev/null @@ -1,245 +0,0 @@ -libdir . '/externallib.php'); -require_once($CFG->dirroot . '/course/modlib.php'); -require_once($CFG->dirroot . '/mod/assign/lib.php'); -require_once($CFG->dirroot.'/grade/grading/lib.php'); -require_once($CFG->dirroot.'/grade/grading/form/rubric/lib.php'); -require_once($CFG->dirroot.'/course/lib.php'); // For course functions - - -use external_function_parameters; -use external_single_structure; -use external_value; -use context_course; -use context_module; -use coding_exception; -use external_api; - -class create_assignment extends external_api { - - // Define the input parameters for the web service - public static function execute_parameters() { - return new external_function_parameters( - array( - 'courseid' => new external_value(PARAM_INT, 'Course ID'), - 'sectionid' => new external_value(PARAM_INT, 'Section ID'), - 'assignmentName' => new external_value(PARAM_TEXT, 'Assignment name'), - 'startdate' => new external_value(PARAM_TEXT, 'Start date (timestamp)'), - 'enddate' => new external_value(PARAM_TEXT, 'End date (timestamp)'), - 'rubricJson' => new external_value(PARAM_RAW, 'Rubric JSON', VALUE_DEFAULT, ''), - 'description' => new external_value(PARAM_RAW, 'Assignment description', VALUE_DEFAULT, '') - ) - ); - } - - // The actual function that performs the task - public static function execute($courseid, $sectionid, $assignmentName, $startdate, $enddate, $rubricJson = '', $description = '') { - global $USER, $DB; - - // Validate the parameters - $params = self::validate_parameters( - self::execute_parameters(), - array( - 'courseid' => $courseid, - 'sectionid' => $sectionid, - 'assignmentName' => $assignmentName, - 'startdate' => $startdate, - 'enddate' => $enddate, - 'rubricJson' => $rubricJson, - 'description' => $description - ) - ); - - // Convert date strings to timestamps - $startdate_timestamp = strtotime($startdate); - $enddate_timestamp = strtotime($enddate); - - // Validate the conversion - if ($startdate_timestamp === false) { - throw new invalid_parameter_exception('Invalid start date format.'); - } - if ($enddate_timestamp === false) { - throw new invalid_parameter_exception('Invalid end date format.'); - } - - // Capability check - $context = context_course::instance($courseid); - require_capability('mod/assign:addinstance', $context); - - // Prepare the course module data - $moduleid = $DB->get_field('modules', 'id', ['name' => 'assign']); - $cm = new \stdClass(); - $cm->course = $courseid; - $cm->module = $moduleid; - $cm->section = $sectionid; - $cm->visible = 1; - - // Add the course module entry - $cmid = add_course_module($cm); - - // Prepare the assignment data - $assignment_data = new \stdClass(); - $assignment_data->course = $courseid; - $assignment_data->name = $assignmentName; - $assignment_data->intro = $description; - $assignment_data->introformat = FORMAT_HTML; - $assignment_data->duedate = $enddate_timestamp; - $assignment_data->allowsubmissionsfromdate = $startdate_timestamp; - $assignment_data->grade = 100; - $assignment_data->coursemodule = $cmid; - - // Required fields that must be set - $assignment_data->submissiondrafts = 0; // Allow submission drafts: 0 = No, 1 = Yes - $assignment_data->requiresubmissionstatement = 0; // Require submission statement - $assignment_data->sendnotifications = 1; // Send notifications to graders - $assignment_data->sendlatenotifications = 1; // Send notifications about late submissions - $assignment_data->sendstudentnotifications = 1; // Notify students - $assignment_data->teamsubmission = 0; // Team submissions - $assignment_data->requireallteammemberssubmit = 0; // Require all team members to submit - $assignment_data->blindmarking = 0; // Blind marking - $assignment_data->attemptreopenmethod = 'none'; // Attempt reopen method: 'none', 'manual', 'untilpass' - $assignment_data->maxattempts = -1; // Max attempts (-1 for unlimited) - $assignment_data->markingworkflow = 0; // Marking workflow - $assignment_data->markingallocation = 0; // Marking allocation - $assignment_data->cutoffdate = $enddate_timestamp; // Cut-off date - $assignment_data->gradingduedate = 0; // Grading due date - $assignment_data->grade = 100; // Maximum grade - $assignment_data->completionsubmit = 0; // Completion tracking - $assignment_data->alwaysshowdescription = 1; // Always show description - - // Initialize submission plugin settings - $assignment_data->assignsubmission_onlinetext_enabled = 1; // Enable online text submissions - $assignment_data->assignsubmission_file_enabled = 0; // Disable file submissions - - // Create the assignment instance - $assignment_instance = assign_add_instance($assignment_data); - - // Update the course module with the correct instance ID - $DB->set_field('course_modules', 'instance', $assignment_instance, ['id' => $cmid]); - - // Add the course module to the section - course_add_cm_to_section($courseid, $cmid, $sectionid); - - // Set the assignment to use advanced grading (rubric) if rubricJson is provided - if (!empty($rubricJson)) { - // Create the context_module object - $module_context = context_module::instance($cmid); - - require_capability('moodle/grade:managegradingforms', $module_context); - - // Initialize the grading manager - $grading_manager = get_grading_manager($module_context); - $grading_manager->set_area('submissions'); - $grading_manager->set_component('mod_assign'); - $grading_manager->set_active_method('rubric'); - - // Get the controller for the 'rubric' grading method - $rubric_controller = $grading_manager->get_controller('rubric'); - - // Create the rubric definition using the custom function - $rubric_definition = self::create_rubric_definition_from_json($rubricJson); - - $rubric_controller->update_definition($rubric_definition); - $rubricid = $rubric_controller->get_definition()->id; - } - - return array('assignmentid' => $assignment_instance, 'assignmentname' => $assignmentName, 'rubricid' => $rubricid); - } - - public static function execute_returns() { - return new external_single_structure( - array( - 'assignmentid' => new external_value(PARAM_INT, 'Assignment ID'), - 'assignmentname' => new external_value(PARAM_TEXT, 'Assignment name'), - 'rubricid' => new external_value(PARAM_TEXT, 'Rubric ID') - ) - ); - } - - public static function create_rubric_definition_from_json($rubricJson) { - // Decode the JSON input into an associative array - $rubric_data = json_decode($rubricJson, true); - - // Check if the JSON is valid - if (json_last_error() !== JSON_ERROR_NONE) { - throw new coding_exception('Invalid JSON format.'); - } - - // Validate that the required fields (criteria and levels) exist in the JSON - if (!isset($rubric_data['criteria']) || !is_array($rubric_data['criteria'])) { - throw new coding_exception('Invalid rubric format: missing criteria.'); - } - - // Initialize the rubric definition object (stdClass) - $rubric_definition = new \stdClass(); - $rubric_definition->status = 20; // 20 represents 'active' - $rubric_definition->description = ''; // Optional: Add rubric description if needed - $rubric_definition->name = 'Rubric Name'; // Optional: Set the rubric name - - // Initialize the 'rubric' property with 'criteria' and 'options' - $rubric_definition->rubric = array( - 'criteria' => array(), - 'options' => array( - 'sortlevelsasc' => 1, - 'allowscoreoverrides' => 0, - 'showdescriptionteacher' => 1, - 'showdescriptionstudent' => 0, - // Add other options as required - ), - ); - - // Variables to keep track of criterion and level IDs - $criterion_id = 0; - $level_id = 0; - - // Loop through each criterion in the JSON data - foreach ($rubric_data['criteria'] as $criterion_data) { - // Each criterion will be an associative array with 'levels' as an array - $criterion_array = array(); - $criterion_array['id'] = $criterion_id; - $criterion_array['description'] = $criterion_data['description']; - $criterion_array['sortorder'] = $criterion_id; // Sort order starts at 0 - $criterion_array['levels'] = array(); - - // Validate that the levels field exists - if (!isset($criterion_data['levels']) || !is_array($criterion_data['levels'])) { - throw new coding_exception('Invalid rubric format: missing levels for criterion.'); - } - - // Level counter for keys - $level_key = 0; - - // Loop through each level in the criterion - foreach ($criterion_data['levels'] as $level_data) { - // Each level is an associative array with a definition (name) and score (points) - $level_array = array(); - $level_array['id'] = $level_id; // ID is integer - $level_array['definition'] = $level_data['definition']; - $level_array['score'] = $level_data['score']; - - // Assign the level array to the criterion's levels array with 'NEWID' keys - // This is required for the update_definition method to see them as new levels - $criterion_array['levels']['NEWID' . $level_key] = $level_array; - - $level_id++; - $level_key++; - } - - // Assign the criterion array to the rubric_definition's rubric['criteria'] array with 'NEWID' keys - $rubric_definition->rubric['criteria']['NEWID' . $criterion_id] = $criterion_array; - $criterion_id++; - } - - // Add the description_editor property - $rubric_definition->description_editor = array( - 'text' => $rubric_definition->description, - 'format' => FORMAT_HTML, - ); - - return $rubric_definition; - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/create_lesson.php b/team_a/MoodlePlugin/learninglens/classes/external/create_lesson.php deleted file mode 100644 index 1f4628c4..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/create_lesson.php +++ /dev/null @@ -1,245 +0,0 @@ -libdir . '/externallib.php'); -require_once($CFG->dirroot . '/mod/lesson/lib.php'); -require_once($CFG->dirroot . '/course/lib.php'); // For rebuild_course_cache - -use external_function_parameters; -use external_single_structure; -use external_value; -use context_course; -use moodle_exception; -use external_api; -use stdClass; - -/** - * Create a lesson and link it to the course module. - * Allows for advanced configuration (password, showdescription, completion, etc.). - */ -class create_lesson extends external_api { - - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'courseid' => new external_value(PARAM_INT, 'Course ID in which to create the lesson'), - 'name' => new external_value(PARAM_TEXT, 'Lesson name/title'), - - 'intro' => new external_value(PARAM_RAW, 'Lesson description/intro', VALUE_OPTIONAL, ''), - 'introformat' => new external_value(PARAM_INT, 'Intro format (1=HTML, 0=MOODLE, etc.)', VALUE_OPTIONAL, FORMAT_HTML), - - // Visibility of intro on course page - 'showdescription' => new external_value( - PARAM_INT, - 'Display description on course page? (1=yes,0=no)', - VALUE_OPTIONAL, - 1 // default to showing description - ), - - // Lesson availability fields - 'available' => new external_value( - PARAM_INT, - 'Timestamp when the lesson opens (defaults to now if 0)', - VALUE_OPTIONAL, - 0 - ), - 'deadline' => new external_value( - PARAM_INT, - 'Timestamp for lesson deadline (0=no deadline)', - VALUE_OPTIONAL, - 0 - ), - 'timelimit' => new external_value( - PARAM_INT, - 'Time limit (seconds). 0 means no limit', - VALUE_OPTIONAL, - 0 - ), - - // Attempts/retakes - 'retake' => new external_value( - PARAM_INT, - 'Allow retakes? (1=yes,0=no)', - VALUE_OPTIONAL, - 1 - ), - 'maxattempts' => new external_value( - PARAM_INT, - 'Maximum number of attempts allowed', - VALUE_OPTIONAL, - 3 - ), - - // Lesson password - 'usepassword' => new external_value( - PARAM_INT, - '1 if a password is required, 0 otherwise', - VALUE_OPTIONAL, - 0 - ), - 'password' => new external_value( - PARAM_RAW, - 'Lesson password if usepassword=1', - VALUE_OPTIONAL, - '' - ), - - // Activity completion in course_modules - 'completion' => new external_value( - PARAM_INT, - 'Enable completion tracking? (1=yes,0=no)', - VALUE_OPTIONAL, - 1 - ), - ]); - } - - public static function execute( - $courseid, - $name, - $intro = '', - $introformat = FORMAT_HTML, - $showdescription = 1, - - $available = 0, - $deadline = 0, - $timelimit = 0, - - $retake = 1, - $maxattempts = 3, - - $usepassword = 0, - $password = '', - - $completion = 1 - ) { - global $DB; - - // 1. Validate parameters - $params = self::validate_parameters( - self::execute_parameters(), - [ - 'courseid' => $courseid, - 'name' => $name, - 'intro' => $intro, - 'introformat' => $introformat, - 'showdescription' => $showdescription, - 'available' => $available, - 'deadline' => $deadline, - 'timelimit' => $timelimit, - 'retake' => $retake, - 'maxattempts' => $maxattempts, - 'usepassword' => $usepassword, - 'password' => $password, - 'completion' => $completion - ] - ); - - // 2. Check if course exists - if (!$DB->record_exists('course', ['id' => $params['courseid']])) { - throw new moodle_exception('invalidcourseid', 'error', '', $params['courseid']); - } - - // 3. Validate context/capability - $context = context_course::instance($params['courseid']); - self::validate_context($context); - require_capability('mod/lesson:addinstance', $context); - - // 4. Create lesson record - $lesson = new stdClass(); - $lesson->course = $params['courseid']; - $lesson->name = $params['name']; - $lesson->intro = $params['intro']; - $lesson->introformat = $params['introformat']; - - // If 'available' is 0, we can default to now => time() - $lesson->available = ($params['available'] == 0) ? time() : $params['available']; - - $lesson->deadline = $params['deadline']; - $lesson->timelimit = $params['timelimit']; - $lesson->retake = $params['retake']; - $lesson->maxattempts = $params['maxattempts']; - - // Lesson password usage - $lesson->usepassword = $params['usepassword']; // field typically in lesson table - $lesson->password = $params['password']; - - $lesson->timecreated = time(); - $lesson->timemodified = time(); - - // If your version of Moodle requires conditions => store empty JSON - $lesson->conditions = '[]'; - - // Insert into mdl_lesson - $lessonid = $DB->insert_record('lesson', $lesson); - if (!$lessonid) { - throw new moodle_exception('errorcreatinglesson', 'local_learninglens'); - } - - // 5. Link lesson to the course modules - // 5a. Get module ID for 'lesson' - $module = $DB->get_record('modules', ['name' => 'lesson'], 'id'); - if (!$module) { - throw new moodle_exception('modulenotfound', 'error'); - } - - // 5b. Find default course section (assuming section=1) - $section = $DB->get_record('course_sections', [ - 'course' => $params['courseid'], - 'section' => 1 - ], 'id,sequence'); - - if (!$section) { - throw new moodle_exception('sectionnotfound', 'error'); - } - - // 5c. Insert a record in mdl_course_modules - $cm = new stdClass(); - $cm->course = $params['courseid']; - $cm->module = $module->id; - $cm->instance = $lessonid; - $cm->section = $section->id; - $cm->added = time(); - $cm->visible = 1; // show the lesson - $cm->visibleold = 1; - $cm->groupmode = 0; - $cm->groupingid = 0; - - // Activity completion - $cm->completion = $params['completion']; - - // "Display description on course page" - $cm->showdescription = $params['showdescription']; - - $courseModuleId = $DB->insert_record('course_modules', $cm); - if (!$courseModuleId) { - throw new moodle_exception('erroraddingmodule', 'local_learninglens'); - } - - // 5d. Update the course section sequence - $sequence = trim($section->sequence . ',' . $courseModuleId, ','); - $section->sequence = $sequence; - $DB->update_record('course_sections', $section); - - // 6. Rebuild cache - rebuild_course_cache($params['courseid'], true); - - // 7. Return lessonId + courseModuleId - return [ - 'lessonId' => $lessonid, - 'courseModuleId' => $courseModuleId, - ]; - } - - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'lessonId' => new external_value( - PARAM_INT, 'ID of the newly created lesson' - ), - 'courseModuleId' => new external_value( - PARAM_INT, 'ID of the newly inserted course module record' - ), - ]); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/create_quiz.php b/team_a/MoodlePlugin/learninglens/classes/external/create_quiz.php deleted file mode 100644 index a601f08f..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/create_quiz.php +++ /dev/null @@ -1,195 +0,0 @@ -libdir . '/externallib.php'); -require_once($CFG->dirroot . '/mod/quiz/lib.php'); -require_once($CFG->dirroot . '/mod/quiz/locallib.php'); -require_once($CFG->libdir . '/gradelib.php'); -require_once($CFG->dirroot . '/question/editlib.php'); -require_once($CFG->dirroot . '/question/engine/lib.php'); -require_once($CFG->dirroot . '/question/lib.php'); -require_once($CFG->dirroot . '/course/lib.php'); -require_once($CFG->dirroot . '/course/modlib.php'); -require_once($CFG->dirroot . '/mod/quiz/report/statistics/report.php'); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use context_system; -use context_course; -use context_module; -use moodle_exception; -use coding_exception; -use required_capability_exception; -use access_manager; -use external_api; -use qformat_xml; -use question_bank; -use question_edit_contexts; - - -class create_quiz extends \external_api { - -public static function execute_parameters(): external_function_parameters { - return new external_function_parameters( - array( - 'courseid' => new external_value(PARAM_INT, 'ID of the course'), - 'name' => new external_value(PARAM_TEXT, 'Name of the quiz'), - 'intro' => new external_value(PARAM_RAW, 'Introductory text for the quiz'), - 'sectionid' => new external_value(PARAM_INT, 'Section ID', VALUE_DEFAULT, 1), - 'timeopen' => new external_value(PARAM_TEXT, 'Time when the quiz opens', VALUE_DEFAULT, '0'), - 'timeclose' => new external_value(PARAM_TEXT, 'Time when the quiz closes', VALUE_DEFAULT, '0'), - ) - ); -} - -public static function execute_returns(): external_single_structure { - return new external_single_structure( - array( - 'quizid' => new external_value(PARAM_INT, 'ID of the created quiz') - ) - ); -} - -public static function execute($courseid, $name, $intro, $sectionid=1, $timeopen='0', $timeclose='0'): array { - global $DB, $USER; - - // validate params - $params = self::validate_parameters(self::execute_parameters(), array( - 'courseid' => $courseid, - 'name' => $name, - 'intro' => $intro, - 'sectionid' => $sectionid, - 'timeopen' => $timeopen, - 'timeclose' => $timeclose - )); - - // set context - $context = context_course::instance($params['courseid']); - - // ensure the user has permission to create a quiz - self::validate_context($context); - require_capability('mod/quiz:addinstance', $context); - require_capability('mod/quiz:manage', $context); - - // create the course module - $module = new \stdClass(); - $module->course = $params['courseid']; - $module->module = $DB->get_field('modules', 'id', array('name' => 'quiz')); - $module->instance = 0; - $module->section = $params['sectionid']; - $module->visible = 1; - $module->visibleold = 1; - $module->groupmode = 0; - $module->groupingid = 0; - $module->completion = 0; - $module->idnumber = $params['sectionid']; - $module->added = time(); - - // add the course module - $module->coursemodule = add_course_module($module); - if (!$module->coursemodule) { - throw new moodle_exception('Could not create course module'); - } - - // update module ID - $module->id = $module->coursemodule; - - // add course module to section - \course_add_cm_to_section($params['courseid'], $module->id, $params['sectionid']); - - - // Convert date strings to Unix timestamps - $timeopen = strtotime($params['timeopen']); // Convert '12 January 2024' to Unix timestamp - $timeclose = strtotime($params['timeclose']); - - // create the quiz module - $quiz = new \stdClass(); - $quiz->course = $params['courseid']; - $quiz->name = $params['name']; - $quiz->intro = '

' . $params['intro'] . '

'; - $quiz->introformat = FORMAT_HTML; - $quiz->timeopen = $timeopen; - $quiz->timeclose = $timeclose; - $quiz->preferredbehaviour = 'deferredfeedback'; - $quiz->attempts = 0; - $quiz->grade = 100; - $quiz->sumgrades = 1; // this get updated in the add_type_randoms_to_quiz to propertly calculate the sum based on the number of questions. - $quiz->timelimit = 0; - $quiz->overduehandling = 'autosubmit'; - $quiz->graceperiod = 0; - $quiz->timecreated = time(); - $quiz->timemodified = time(); - $quiz->quizpassword = ''; - $quiz->coursemodule = $module->id; - $quiz->feedbackboundarycount = 0; - $quiz->feedbacktext = []; - $quiz->questionsperpage = 1; - $quiz->shuffleanswers = 1; - $quiz->browsersecurity = '-'; - - // process the options from the form. - $result = quiz_process_options($quiz); - if ($result && is_string($result)) { - throw new moodle_exception($result); - } - - // insert the quiz into the database - $quiz->id = $DB->insert_record('quiz', $quiz); - - // update the course module with the quiz instance ID - $DB->set_field('course_modules', 'instance', $quiz->id, array('id' => $module->id)); - - // create the first section for this quiz. - $DB->insert_record('quiz_sections', ['quizid' => $quiz->id, 'firstslot' => 1, 'heading' => '', 'shufflequestions' => 0]); - - // clear feedback - $DB->delete_records('quiz_feedback', ['quizid' => $quiz->id]); - - // set feedback - for ($i = 0; $i <= $quiz->feedbackboundarycount; $i++) { - if (isset($quiz->feedbacktext[$i])) { - $feedback = new \stdClass(); - $feedback->quizid = $quiz->id; - $feedback->feedbacktext = $quiz->feedbacktext[$i]['text'] ?? ''; - $feedback->feedbacktextformat = $quiz->feedbacktext[$i]['format'] ?? FORMAT_HTML; - $feedback->mingrade = $quiz->feedbackboundaries[$i] ?? 0; - $feedback->maxgrade = $quiz->feedbackboundaries[$i - 1] ?? 100; - $feedback->id = $DB->insert_record('quiz_feedback', $feedback); - $feedbacktext = file_save_draft_area_files((int)$quiz->feedbacktext[$i]['itemid'] ?? 0, - $context->id, 'mod_quiz', 'feedback', $feedback->id, - ['subdirs' => false, 'maxfiles' => -1, 'maxbytes' => 0], - $quiz->feedbacktext[$i]['text'] ?? ''); - $DB->set_field('quiz_feedback', 'feedbacktext', $feedbacktext, ['id' => $feedback->id]); - } - } - - // store settings belonging to the access rules - \mod_quiz\access_manager::save_settings($quiz); - - // update events related to this quiz - quiz_update_events($quiz); - $completionexpected = (!empty($quiz->completionexpected)) ? $quiz->completionexpected : null; - \core_completion\api::update_completion_date_event($quiz->coursemodule, 'quiz', $quiz->id, $completionexpected); - - // update related grade item. - quiz_grade_item_update($quiz); - - // update quiz review fields - $quiz->reviewattempt = 69888; - $quiz->reviewcorrectness = 4352; - $quiz->reviewmaxmarks = 69888; - $quiz->reviewmarks = 4352; - $quiz->reviewspecificfeedback = 4352; - $quiz->reviewgeneralfeedback = 4352; - $quiz->reviewrightanswer = 4352; - $quiz->reviewoverallfeedback = 4352; - $DB->update_record('quiz', $quiz); - - // return quiz ID - return array('quizid' => $quiz->id); -} -}; \ No newline at end of file diff --git a/team_a/MoodlePlugin/learninglens/classes/external/delete_lesson_plan.php b/team_a/MoodlePlugin/learninglens/classes/external/delete_lesson_plan.php deleted file mode 100644 index 98a1f965..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/delete_lesson_plan.php +++ /dev/null @@ -1,54 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_value; -use external_api; -use context_module; -use context_course; - -class delete_lesson_plan extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'lessonid' => new external_value(PARAM_INT, 'ID of the lesson plan to delete'), - ]); - } - - public static function execute($lessonid) { - global $DB, $USER; - - $params = self::validate_parameters(self::execute_parameters(), ['lessonid' => $lessonid]); - - // Check if the lesson plan exists - if (!$lesson = $DB->get_record('lesson', ['id' => $lessonid], '*', IGNORE_MISSING)) { - throw new \moodle_exception('invalidlessonid', 'error', '', $lessonid); - } - - // Get course context - $context = context_course::instance($lesson->course); - - // Ensure user has permission to delete lesson plans - require_capability('mod/lesson:manage', $context); - - // Delete the lesson plan - $DB->delete_records('lesson', ['id' => $lessonid]); - - // Clear cache for the lesson plan - purge_all_caches(); - - return ['status' => 'success', 'message' => 'Lesson plan deleted successfully']; - } - - public static function execute_returns() { - return new external_single_structure([ - 'status' => new external_value(PARAM_TEXT, 'Status of the request'), - 'message' => new external_value(PARAM_TEXT, 'Message about the operation result'), - ]); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_all_overrides.php b/team_a/MoodlePlugin/learninglens/classes/external/get_all_overrides.php deleted file mode 100644 index 5fbe0192..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_all_overrides.php +++ /dev/null @@ -1,99 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use external_api; - -class get_all_overrides extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([]); - } - - public static function execute() { - global $DB; - - $questions = self::get_overrides(); - - return $questions; - } - - private static function get_overrides() { - global $DB; - - $sql = " - SELECT - qo.id AS override_id, - 'quiz' AS assignment_type, - qo.quiz AS assignment_id, - q.name AS assignment_name, - q.course AS course_id, - c.fullname AS course_name, - qo.userid, - CONCAT(u.firstname, ' ', u.lastname) AS fullname, - qo.timeopen AS start_time, - qo.timeclose AS end_time, - qo.timelimit, - NULL AS cutoff_time, - qo.attempts, - qo.password, - NULL AS sortorder - FROM mdl_quiz_overrides qo - LEFT JOIN mdl_quiz q ON qo.quiz = q.id - LEFT JOIN mdl_course c ON q.course = c.id - LEFT JOIN mdl_user u ON qo.userid = u.id - UNION ALL - SELECT - ao.id AS override_id, - 'essay' AS assignment_type, - ao.assignid AS assignment_id, - a.name AS assignment_name, - a.course AS course_id, - c.fullname AS course_name, - ao.userid, - CONCAT(u.firstname, ' ', u.lastname) AS fullname, - ao.allowsubmissionsfromdate AS start_time, - ao.duedate AS end_time, - ao.timelimit, - ao.cutoffdate AS cutoff_time, - NULL AS attempts, - NULL AS password, - ao.sortorder - FROM mdl_assign_overrides ao - LEFT JOIN mdl_assign a ON ao.assignid = a.id - LEFT JOIN mdl_course c ON a.course = c.id - LEFT JOIN mdl_user u ON ao.userid = u.id; - "; - - return $DB->get_records_sql($sql); - } - - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure([ - 'override_id' => new external_value(PARAM_INT, 'Override ID'), - 'assignment_type' => new external_value(PARAM_TEXT, 'Assignment Type'), - 'assignment_id' => new external_value(PARAM_INT, 'Assignment ID'), - 'assignment_name' => new external_value(PARAM_TEXT, 'Assignment Name'), - 'course_id' => new external_value(PARAM_INT, 'Course ID'), - 'course_name' => new external_value(PARAM_TEXT, 'Course Name'), - 'userid' => new external_value(PARAM_INT, 'User ID'), - 'fullname' => new external_value(PARAM_TEXT, 'Full name'), - 'start_time' => new external_value(PARAM_INT, 'Time Open'), - 'end_time' => new external_value(PARAM_INT, 'Time Close'), - 'timelimit' => new external_value(PARAM_INT, 'Time Limit'), - 'cutoff_time' => new external_value(PARAM_INT, 'Cutoff Time (Essay only)'), - 'attempts' => new external_value(PARAM_INT, 'Attempts (Quiz only)'), - 'password' => new external_value(PARAM_TEXT, 'Password (Quiz only)'), - 'sortorder' => new external_value(PARAM_INT, 'Sortorder (Essay only)'), - ]) - ); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_lesson_plans_by_course.php b/team_a/MoodlePlugin/learninglens/classes/external/get_lesson_plans_by_course.php deleted file mode 100644 index 43f7ce32..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_lesson_plans_by_course.php +++ /dev/null @@ -1,65 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use external_api; -use context_course; - -class get_lesson_plans_by_course extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'courseid' => new external_value(PARAM_INT, 'ID of the course'), - ]); - } - - public static function execute($courseid) { - global $DB; - - $params = self::validate_parameters(self::execute_parameters(), ['courseid' => $courseid]); - - // Ensure course exists - if (!$DB->record_exists('course', ['id' => $courseid])) { - throw new \moodle_exception('invalidcourseid', 'error', '', $courseid); - } - - // Ensure user has the correct capability to view lessons - $context = context_course::instance($courseid); - require_capability('mod/lesson:view', $context); - - // Fetch lesson plans - $lessonplans = self::get_lessons_by_course($courseid); - - return array_values($lessonplans); - } - - private static function get_lessons_by_course($courseid) { - global $DB; - - $sql = " - SELECT id, name, intro, timemodified - FROM {lesson} - WHERE course = :courseid - "; - - return $DB->get_records_sql($sql, ['courseid' => $courseid]); - } - - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Lesson Plan ID'), - 'name' => new external_value(PARAM_TEXT, 'Lesson Plan Name'), - 'intro' => new external_value(PARAM_RAW, 'Lesson Plan Description'), - 'timemodified' => new external_value(PARAM_INT, 'Last Modified Timestamp'), - ]) - ); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_question_stats_from_quiz.php b/team_a/MoodlePlugin/learninglens/classes/external/get_question_stats_from_quiz.php deleted file mode 100644 index 7ee2df98..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_question_stats_from_quiz.php +++ /dev/null @@ -1,156 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use external_api; - -class get_question_stats_from_quiz extends external_api { - - /** - * Define parameter structure for the function. - */ - public static function execute_parameters() { - return new external_function_parameters([ - 'quizid' => new external_value(PARAM_INT, 'ID of the quiz'), - ]); - } - - /** - * Main execution function. This is what gets called by the web service. - */ - public static function execute($quizid) { - // Validate incoming parameters. - $params = self::validate_parameters( - self::execute_parameters(), - ['quizid' => $quizid] - ); - - // *Optional*: permission checks (capabilities, context, etc.) - - // Actually fetch data. - $records = self::get_question_stats_by_quiz($params['quizid']); - - // Return the array of data. - return $records; - } - - /** - * The real logic. Query for questions (similar to your existing logic) - * but also compute correct/incorrect stats or any other analytics. - */ - private static function get_question_stats_by_quiz($quizid) { - global $DB; - - // 1) Gather the questions (same as before) - $sql_questions = " - SELECT q.id, - q.name, - q.questiontext, - q.qtype - FROM {question} q - WHERE q.id IN ( - SELECT qbe.id - FROM {question_bank_entries} qbe - WHERE qbe.questioncategoryid = ( - SELECT qc.id - FROM {question_categories} qc - WHERE ( - SELECT quiz.intro - FROM {quiz} quiz - WHERE quiz.id = :quizid - ) LIKE CONCAT('%', qc.name, '%') - LIMIT 1 - ) - ) - "; - - $questions = $DB->get_records_sql($sql_questions, ['quizid' => $quizid]); - if (!$questions) { - return []; - } - - // 2) Gather attempt stats by looking for 'gradedright', 'gradedwrong', 'gradedpartial' - // instead of 'complete' or fraction-based checks - $sql_stats = " - SELECT - qa.questionid, - SUM(CASE WHEN qs.state = 'gradedright' THEN 1 ELSE 0 END) AS numcorrect, - SUM(CASE WHEN qs.state = 'gradedwrong' THEN 1 ELSE 0 END) AS numincorrect, - SUM(CASE WHEN qs.state = 'gradedpartial' THEN 1 ELSE 0 END) AS numpartial, - COUNT(*) AS totalattempts - FROM {quiz_attempts} quiza - JOIN {question_usages} qu ON qu.id = quiza.uniqueid - JOIN {question_attempts} qa ON qa.questionusageid = qu.id - JOIN {question_attempt_steps} qs ON qs.questionattemptid = qa.id - AND qs.sequencenumber = ( - SELECT MAX(qs2.sequencenumber) - FROM {question_attempt_steps} qs2 - WHERE qs2.questionattemptid = qa.id - ) - WHERE quiza.quiz = :quizid2 - GROUP BY qa.questionid - "; - - $statsrecords = $DB->get_records_sql($sql_stats, ['quizid2' => $quizid]); - - // 3) Merge stats with the question array - $results = []; - foreach ($questions as $q) { - $qid = $q->id; - - // Default zeros - $correct = 0; - $incorrect = 0; - $partial = 0; - $total = 0; - - if (isset($statsrecords[$qid])) { - $record = $statsrecords[$qid]; - $correct = (int) $record->numcorrect; - $incorrect = (int) $record->numincorrect; - $partial = (int) $record->numpartial; - $total = (int) $record->totalattempts; - } - - $results[] = [ - 'id' => $qid, - 'name' => $q->name, - 'questiontext' => $q->questiontext, - 'qtype' => $q->qtype, - 'numcorrect' => $correct, - 'numincorrect' => $incorrect, - 'numpartial' => $partial, - 'totalattempts'=> $total, - ]; - } - - return $results; - } - - - /** - * Define the return structure. - */ - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Question ID'), - 'name' => new external_value(PARAM_TEXT, 'Question name'), - 'questiontext' => new external_value(PARAM_RAW, 'Question text'), - 'qtype' => new external_value(PARAM_ALPHANUMEXT, 'Question type'), - 'numcorrect' => new external_value(PARAM_INT, 'Number of fully correct attempts'), - 'numincorrect' => new external_value(PARAM_INT, 'Number of fully incorrect attempts'), - 'numpartial' => new external_value(PARAM_INT, 'Number of partially correct attempts'), - 'totalattempts' => new external_value(PARAM_INT, 'Total attempts (final steps)'), - ]) - ); - } - -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_questions_from_quiz.php b/team_a/MoodlePlugin/learninglens/classes/external/get_questions_from_quiz.php deleted file mode 100644 index b884c1e0..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_questions_from_quiz.php +++ /dev/null @@ -1,66 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use external_api; - -class get_questions_from_quiz extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'quizid' => new external_value(PARAM_INT, 'ID of the quiz'), - ]); - } - - public static function execute($quizid) { - global $DB; - - $params = self::validate_parameters(self::execute_parameters(), ['quizid' => $quizid]); - - $questions = self::get_questions_by_quiz($quizid); - - return $questions; - } - - private static function get_questions_by_quiz($quizid) { - global $DB; - - $sql = " - SELECT q.id, q.name, q.questiontext, q.qtype - FROM {question} q - WHERE q.id IN ( - SELECT qbe.id - FROM {question_bank_entries} qbe - WHERE qbe.questioncategoryid = ( - SELECT qc.id - FROM {question_categories} qc - WHERE ( - SELECT quiz.intro - FROM {quiz} quiz - WHERE quiz.id = :quizid - ) LIKE CONCAT('%', qc.name, '%') - LIMIT 1 - ) - )"; - - return $DB->get_records_sql($sql, ['quizid' => $quizid]); - } - - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Question ID'), - 'name' => new external_value(PARAM_TEXT, 'Question name'), - 'questiontext' => new external_value(PARAM_RAW, 'Question text'), - 'qtype' => new external_value(PARAM_ALPHANUMEXT, 'Question type'), - ]) - ); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_rubric.php b/team_a/MoodlePlugin/learninglens/classes/external/get_rubric.php deleted file mode 100644 index 256bfb4c..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_rubric.php +++ /dev/null @@ -1,102 +0,0 @@ -libdir . '/externallib.php'); -require_once("$CFG->dirroot/grade/grading/lib.php"); -require_once("$CFG->dirroot/mod/assign/locallib.php"); - -use external_function_parameters; -use external_single_structure; -use external_multiple_structure; -use external_value; -use context_module; -use external_api; - -class get_rubric extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'assignmentid' => new external_value(PARAM_INT, 'ID of the assignment'), - ]); - } - - public static function execute($assignmentid) { - global $USER; - - // Validate the parameters. - $params = self::validate_parameters(self::execute_parameters(), [ - 'assignmentid' => $assignmentid, - ]); - - // Fetch the definition ID for the given assignment. - // $definitionid = self::get_definitionid_from_assignmentid($assignmentid); - $rubricdata[] = self::get_definitionid_from_assignmentid($assignmentid); - return $rubricdata; - } - - public static function get_definitionid_from_assignmentid($assignmentid) { - global $DB; - - //Get the course module ID (`cmid`) for the assignment. - $cmid = $DB->get_field_sql(" - SELECT cm.id - FROM {course_modules} cm - JOIN {modules} m ON m.id = cm.module - JOIN {assign} a ON a.id = cm.instance - WHERE m.name = 'assign' AND a.id = ?", [$assignmentid]); - - if (!$cmid) { - throw new \moodle_exception('invalidassignmentid', 'error', '', $assignmentid); - } - - //Fetch the context of the assignment using the `cmid`. - $context = context_module::instance($cmid); - - //Identify the component. For assignments, it is usually 'mod_assign'. - $component = 'mod_assign'; - - //Initialize the grading manager without context first. - $gradingmanager = new \grading_manager(); - $gradingmanager->set_context($context); - $gradingmanager->set_component($component); - - //Get available grading areas for the specified component and context. - $areas = $gradingmanager->get_available_areas(); - if (!in_array('submissions', array_keys($areas))) { - return null; // 'submissions' grading area not found. - } - $gradingmanager->set_area('submissions'); - - //Get the controller for the 'submissions' grading area. - $controller = $gradingmanager->get_controller('rubric'); - - //Check if the grading method is 'rubric' and get the definition ID. - if (!is_null($controller)) { - return $controller->get_definition(); - } - return null; - } - - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Instance ID'), - 'rubric_criteria' => new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Criterion ID'), - 'description' => new external_value(PARAM_TEXT, 'Criterion description'), - 'levels' => new external_multiple_structure( - new external_single_structure([ - 'id' => new external_value(PARAM_INT, 'Level ID'), - 'score' => new external_value(PARAM_FLOAT, 'Level score'), - 'definition' => new external_value(PARAM_TEXT, 'Level definition'), - ]) - ), - ]) - ), - ]) - ); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/get_rubric_grades.php b/team_a/MoodlePlugin/learninglens/classes/external/get_rubric_grades.php deleted file mode 100644 index 5c50f84e..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/get_rubric_grades.php +++ /dev/null @@ -1,107 +0,0 @@ -libdir . '/externallib.php'); - require_once("$CFG->dirroot/grade/grading/lib.php"); - require_once("$CFG->dirroot/mod/assign/locallib.php"); - - use external_function_parameters; - use external_single_structure; - use external_multiple_structure; - use external_value; - use context_module; - use external_api; - -class get_rubric_grades extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'assignmentid' => new external_value(PARAM_INT, 'ID of the assignment'), - 'userid' => new external_value(PARAM_INT, 'ID of the user') - ]); - } - - // Define the return structure for the function. - public static function execute_returns() { - return new external_multiple_structure( - new external_single_structure( - array( - 'criterionid' => new external_value(PARAM_INT, 'The ID of the criterion'), - 'criterion_description' => new external_value(PARAM_TEXT, 'The description of the criterion'), - 'levelid' => new external_value(PARAM_INT, 'The ID of the level'), - 'level_description' => new external_value(PARAM_TEXT, 'The description of the level in the criterion'), - 'score' => new external_value(PARAM_FLOAT, 'The score for the criterion'), - 'remark' => new external_value(PARAM_RAW, 'Remarks by the grader') - ) - ) - ); - } - public static function execute($assignmentid, $userid) { - global $USER; - - // Validate the parameters. - $params = self::validate_parameters(self::execute_parameters(), [ - 'assignmentid' => $assignmentid, - 'userid' => $userid - ]); - - global $DB; - - // Get the assignment's grading instance ID. - $itemid = $DB->get_field('assign_grades', 'id', ['assignment' => $assignmentid, 'userid' => $userid], MUST_EXIST); - - // Add conditions to ensure you get only one grading instance. - $gradinginstances = $DB->get_records('grading_instances', ['itemid' => $itemid]); - - - $valid_gradinginstance = null; - // Loop through grading instances to find the one with status = 1 and method = 'rubric'. - foreach ($gradinginstances as $instance) { - if ($instance->status == 1) { - // Get the definition for the grading instance. - $definition = $DB->get_record('grading_definitions', ['id' => $instance->definitionid], '*', IGNORE_MISSING); - if ($definition && $definition->method === 'rubric') { - $valid_gradinginstance = $instance; - break; // Stop once we find the valid instance. - } - } - } - - if (!$valid_gradinginstance) { - throw new moodle_exception('norubricinstance', 'error', '', $assignmentid); - } - - // Query the rubric fillings for this submission. - $rubricgrades = $DB->get_records('gradingform_rubric_fillings', ['instanceid' => $valid_gradinginstance->id]); - - $rubricdata = []; - - foreach ($rubricgrades as $grade) { - $criterion = $DB->get_record('gradingform_rubric_criteria', ['id' => $grade->criterionid], '*', MUST_EXIST); - $level = $DB->get_record('gradingform_rubric_levels', ['id' => $grade->levelid], '*', MUST_EXIST); - $rubricdata[] = [ - 'criterion_description' => $criterion->description, - 'level_description' => $level->definition, - 'score' => $level->score, - 'remark' => $grade->remark, - 'criterionid' => $criterion->id, - 'levelid' => $level->id - ]; - } - - return $rubricdata; - - } -} \ No newline at end of file diff --git a/team_a/MoodlePlugin/learninglens/classes/external/import_questions.php b/team_a/MoodlePlugin/learninglens/classes/external/import_questions.php deleted file mode 100644 index 13e9455b..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/import_questions.php +++ /dev/null @@ -1,92 +0,0 @@ - new external_value(PARAM_INT, 'The course ID'), - 'questionxml' => new external_value(PARAM_RAW, 'Question XML'), - ]); - } - - /** - * Defines function return values - * @return external_single_structure - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure( - array( - 'categoryid' => new external_value(PARAM_INT, 'ID of the created category') - ) - ); - } - - /** - * Execute the function. - * @param $courseid - * @param $questionxml - * @return array - * @throws \invalid_parameter_exception - * @throws \moodle_exception - */ - public static function execute($courseid, $questionxml) { - global $CFG; - require_once("$CFG->dirroot/lib/questionlib.php"); - require_once("$CFG->dirroot/lib/datalib.php"); - require_once("$CFG->dirroot/question/format/xml/format.php"); - - $params = self::validate_parameters(self::execute_parameters(), [ - 'courseid' => $courseid, - 'questionxml' => $questionxml, - ]); - - // write XML data to temp file - $tmpfile = tmpfile(); - fwrite($tmpfile, $questionxml); - $metadata = stream_get_meta_data($tmpfile); - $tmpfilename = $metadata['uri']; - - // Set up the import formatter - $qformat = new qformat_xml(); - $qformat->setContexts((new question_edit_contexts(context_course::instance($courseid)))->all()); - $qformat->setCourse(get_course($courseid)); - $qformat->setFilename($tmpfilename); - $qformat->setMatchgrades('error'); - $qformat->setCatfromfile(1); - $qformat->setContextfromfile(1); - $qformat->setStoponerror(1); - $qformat->setCattofile(1); - $qformat->setContexttofile(1); - $qformat->set_display_progress(false); - - // Do the import - $imported = $qformat->importprocess(); - - // // Return list of question IDs - // $retval = array(); - // for ($i = 0; $i < count($qformat->questionids); $i++) { - // $retval[$i] = ['questionid' => $qformat->questionids[$i]]; - // } - // return $retval; - - // Return Category ID - return array('categoryid' => $qformat->category->id); - - } -} \ No newline at end of file diff --git a/team_a/MoodlePlugin/learninglens/classes/external/update_lesson_plan.php b/team_a/MoodlePlugin/learninglens/classes/external/update_lesson_plan.php deleted file mode 100644 index b33f8087..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/update_lesson_plan.php +++ /dev/null @@ -1,76 +0,0 @@ -libdir . '/externallib.php'); - -use external_function_parameters; -use external_single_structure; -use external_value; -use external_api; -use context_course; - -class update_lesson_plan extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'lessonid' => new external_value(PARAM_INT, 'ID of the lesson plan to update'), - 'name' => new external_value(PARAM_TEXT, 'Updated lesson plan name', VALUE_OPTIONAL), - 'intro' => new external_value(PARAM_RAW, 'Updated lesson plan description', VALUE_OPTIONAL), - 'available' => new external_value(PARAM_INT, 'Updated available timestamp', VALUE_OPTIONAL), - 'deadline' => new external_value(PARAM_INT, 'Updated deadline timestamp', VALUE_OPTIONAL), - ]); - } - - public static function execute($lessonid, $name = null, $intro = null, $available = null, $deadline = null) { - global $DB, $USER; - - $params = self::validate_parameters(self::execute_parameters(), [ - 'lessonid' => $lessonid, - 'name' => $name, - 'intro' => $intro, - 'available' => $available, - 'deadline' => $deadline - ]); - - // Check if the lesson plan exists - if (!$lesson = $DB->get_record('lesson', ['id' => $lessonid], '*', IGNORE_MISSING)) { - throw new \moodle_exception('invalidlessonid', 'error', '', $lessonid); - } - - // Get course context - $context = context_course::instance($lesson->course); - - // Ensure user has permission to update lesson plans - require_capability('mod/lesson:manage', $context); - - // Prepare update data - $updateData = ['id' => $lessonid]; - - if (!is_null($name)) { - $updateData['name'] = $name; - } - if (!is_null($intro)) { - $updateData['intro'] = $intro; - } - if (!is_null($available)) { - $updateData['available'] = $available; - } - if (!is_null($deadline)) { - $updateData['deadline'] = $deadline; - } - - // Perform update - $DB->update_record('lesson', (object)$updateData); - - return ['status' => 'success', 'message' => 'Lesson plan updated successfully']; - } - - public static function execute_returns() { - return new external_single_structure([ - 'status' => new external_value(PARAM_TEXT, 'Status of the request'), - 'message' => new external_value(PARAM_TEXT, 'Message about the operation result'), - ]); - } -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/write_grades.php b/team_a/MoodlePlugin/learninglens/classes/external/write_grades.php deleted file mode 100644 index 38e39737..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/write_grades.php +++ /dev/null @@ -1,110 +0,0 @@ -libdir . '/externallib.php'); -require_once("$CFG->dirroot/grade/grading/lib.php"); -require_once("$CFG->dirroot/mod/assign/locallib.php"); - -use external_function_parameters; -use external_single_structure; -use external_value; -use context_module; -use external_api; - -class write_grades extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'assignmentid' => new external_value(PARAM_INT, 'ID of the assignment'), - 'userid' => new external_value(PARAM_INT, 'ID of the user'), - 'grade' => new external_value(PARAM_INT, 'Raw grade value') - ]); - } - - // Define the return structure for the function. - public static function execute_returns() { - return new external_value(PARAM_BOOL, 'True if the grades were successfully written.'); - } - - public static function execute($assignmentid, $userid, $grade, $comment = '') { - global $DB, $USER; - - // Validate the parameters. - $params = self::validate_parameters(self::execute_parameters(), [ - 'assignmentid' => $assignmentid, - 'userid' => $userid, - 'grade' => $grade - ]); - - - // Check if there is already a record in the assign_grades table for this user and assignment. - $grade_record = $DB->get_record('assign_grades', ['assignment' => $assignmentid, 'userid' => $userid]); - - // If no grade record exists, insert a new one. - if (!$grade_record) { - $new_grade = new \stdClass(); - $new_grade->assignment = $assignmentid; - $new_grade->userid = $userid; - $new_grade->grader = $USER->id; // Set the current user as the grader. - $new_grade->timecreated = time(); - $new_grade->timemodified = time(); - $new_grade->grade = -1; // Initial placeholder grade (to be updated later). - $new_grade->attemptnumber = 0; // Assuming this is the first attempt. - $new_grade->id = $DB->insert_record('assign_grades', $new_grade); - $itemid = $new_grade->id; // Use the newly inserted record's ID as the itemid. - } else { - // Use the existing grade record's ID as the itemid. - $itemid = $grade_record->id; - } - - // Get the course module for the assignment. - $course_module_id = $DB->get_field('course_modules', 'id', [ - 'instance' => $assignmentid, - 'module' => $DB->get_field('modules', 'id', ['name' => 'assign']) - ]); - - if (!$course_module_id) { - throw new \moodle_exception('nocoursemodule', 'error', '', 'Course module not found for assignment.'); - } - - // Get the assignment's grading rubric controller. - $context = context_module::instance($course_module_id); - $gradingmanager = get_grading_manager($context, 'mod_assign', 'submissions'); - - - - // Update the grade in the assign_grades table to reflect the final state. - $finalgrade = $DB->get_record('assign_grades', ['id' => $itemid], '*', MUST_EXIST); - $finalgrade->grader = $USER->id; - $finalgrade->grade = $grade; - $finalgrade->timemodified = time(); - $DB->update_record('assign_grades', $finalgrade); - - - $gradeupdate = new \stdClass(); - $gradeupdate->id = $finalgrade->id; - $gradeupdate->assignment = $assignmentid; - $gradeupdate->userid = $userid; - $gradeupdate->grade = $grade; - $gradeupdate->rawgrade = $grade; - $gradeupdate->grader = $USER->id; - $gradeupdate->timecreated = $finalgrade->timecreated; - $gradeupdate->timemodified = time(); - $assign = new \assign($context, null, null); - $assign->update_grade($gradeupdate); - - return true; - } - -} diff --git a/team_a/MoodlePlugin/learninglens/classes/external/write_rubric_grades.php b/team_a/MoodlePlugin/learninglens/classes/external/write_rubric_grades.php deleted file mode 100644 index 856a8120..00000000 --- a/team_a/MoodlePlugin/learninglens/classes/external/write_rubric_grades.php +++ /dev/null @@ -1,199 +0,0 @@ -libdir . '/externallib.php'); -require_once("$CFG->dirroot/grade/grading/lib.php"); -require_once("$CFG->dirroot/mod/assign/locallib.php"); -require_once($CFG->dirroot . '/grade/grading/form/rubric/lib.php'); - -use external_function_parameters; -use external_single_structure; -use external_value; -use context_module; -use external_api; - -class write_rubric_grades extends external_api { - - public static function execute_parameters() { - return new external_function_parameters([ - 'assignmentid' => new external_value(PARAM_INT, 'ID of the assignment'), - 'userid' => new external_value(PARAM_INT, 'ID of the user'), - 'rubricgrades' => new external_value(PARAM_RAW, 'Rubric grading data in JSON string format') - ]); - } - - // Define the return structure for the function. - public static function execute_returns() { - return new external_value(PARAM_BOOL, 'True if the rubric grades were successfully written.'); - } - - public static function execute($assignmentid, $userid, $rubricgrades, $comment = '') { - global $DB, $USER; - - // Validate the parameters. - $params = self::validate_parameters(self::execute_parameters(), [ - 'assignmentid' => $assignmentid, - 'userid' => $userid, - 'rubricgrades' => $rubricgrades - ]); - - // Decode the JSON string into an array. - $rubricgrades_array = json_decode($rubricgrades, true); - - // Check if the JSON decoding was successful. - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \moodle_exception('invalidjson', 'error', '', json_last_error_msg()); - } - - // Check if there is already a record in the assign_grades table for this user and assignment. - $grade_record = $DB->get_record('assign_grades', ['assignment' => $assignmentid, 'userid' => $userid]); - - // If no grade record exists, insert a new one. - if (!$grade_record) { - $new_grade = new \stdClass(); - $new_grade->assignment = $assignmentid; - $new_grade->userid = $userid; - $new_grade->grader = $USER->id; // Set the current user as the grader. - $new_grade->timecreated = time(); - $new_grade->timemodified = time(); - $new_grade->grade = -1; // Initial placeholder grade (to be updated later). - $new_grade->attemptnumber = 0; // Assuming this is the first attempt. - $new_grade->id = $DB->insert_record('assign_grades', $new_grade); - $itemid = $new_grade->id; // Use the newly inserted record's ID as the itemid. - } else { - // Use the existing grade record's ID as the itemid. - $itemid = $grade_record->id; - } - - // Get the course module for the assignment. - $course_module_id = $DB->get_field('course_modules', 'id', [ - 'instance' => $assignmentid, - 'module' => $DB->get_field('modules', 'id', ['name' => 'assign']) - ]); - - if (!$course_module_id) { - throw new \moodle_exception('nocoursemodule', 'error', '', 'Course module not found for assignment.'); - } - - // Get the assignment's grading rubric controller. - $context = context_module::instance($course_module_id); - $gradingmanager = get_grading_manager($context, 'mod_assign', 'submissions'); - - // Check if the assignment is using the rubric grading method. - if (!$gradingmanager->get_active_method() || $gradingmanager->get_active_method() !== 'rubric') { - throw new \moodle_exception('norubriccontroller', 'error', '', 'This assignment is not using the rubric grading method.'); - } - - $controller = $gradingmanager->get_controller('rubric'); - - // Check if there's already an existing grading instance for the rater and item. - $gradinginstance = $controller->get_current_instance($USER->id, $itemid); - - - if (!$gradinginstance) { - // If no instance exists, create a new one. - $gradinginstance = $controller->create_instance($USER->id, $itemid); - } - - // Get the instance ID for further operations. - $instanceid = $gradinginstance->get_data('id'); - - // Initialize variables to calculate the total score and maximum score. - $total_score = 0; - $max_score = 0; - - // Get the rubric definition from the grading controller, which contains the criteria and levels. - $rubricdefinition = $controller->get_definition(); - // Now get the criteria from the rubric definition. - $rubriccriteria = $DB->get_records('gradingform_rubric_criteria', ['definitionid' => $rubricdefinition->id]); - - - // Calculate the maximum possible score based on the full rubric definition. - foreach ($rubriccriteria as $criterion) { - $maxlevel = $DB->get_record_sql( - 'SELECT MAX(score) as maxscore FROM {gradingform_rubric_levels} WHERE criterionid = ?', - [$criterion->id] - ); - $max_score += $maxlevel->maxscore; - } - - // Write rubric grades for each criterion and calculate the total score for the graded criteria. - foreach ($rubricgrades_array as $grade) { - // Ensure the criterion and level exist. - $criterion = $DB->get_record('gradingform_rubric_criteria', ['id' => $grade['criterionid']], '*', MUST_EXIST); - $level = $DB->get_record('gradingform_rubric_levels', ['id' => $grade['levelid'], 'criterionid' => $criterion->id], '*', MUST_EXIST); - - // Add the selected level score to the total score. - $total_score += $level->score; - - // Check if there's already an entry for this instance and criterion, update or insert as necessary. - $existinggrade = $DB->get_record('gradingform_rubric_fillings', ['instanceid' => $gradinginstance->get_data('id'), 'criterionid' => $criterion->id]); - - if ($existinggrade) { - // Update existing grade. - $existinggrade->levelid = $grade['levelid']; - $existinggrade->remark = $grade['remark']; - $existinggrade->raterid = $USER->id; // Assuming the current user is the rater. - $DB->update_record('gradingform_rubric_fillings', $existinggrade); - } else { - // Insert new grade. - $newgrade = new \stdClass(); - $newgrade->instanceid = $gradinginstance->get_data('id'); // Use correct instanceid - $newgrade->criterionid = $criterion->id; - $newgrade->levelid = $grade['levelid']; - $newgrade->remark = $grade['remark']; - $newgrade->raterid = $USER->id; // Assuming the current user is the rater. - $DB->insert_record('gradingform_rubric_fillings', $newgrade); - } - } - - // Create a new object for updating the grading instance's status. - $instanceupdate = new \stdClass(); - $instanceupdate->id = $gradinginstance->get_data('id'); - $instanceupdate->status = 1; // 1 means "finalized". - $DB->update_record('grading_instances', $instanceupdate); - - // Delete any unsubmitted (status = 0) grading instances for this user and item. - $DB->delete_records('grading_instances', ['itemid' => $itemid, 'raterid' => $USER->id, 'status' => 0]); - - // Get the maximum grade for the assignment - $assignment = $DB->get_record('assign', ['id' => $assignmentid], '*', MUST_EXIST); - $maxgrade = $assignment->grade; // Maximum possible grade - - // Calculate the final grade as a proportion of the total score to the maximum possible score. - $finalgradevalue = ($total_score / $max_score) * $maxgrade; - - // Update the grade in the assign_grades table to reflect the final state. - $finalgrade = $DB->get_record('assign_grades', ['id' => $itemid], '*', MUST_EXIST); - $finalgrade->grader = $USER->id; - $finalgrade->grade = $finalgradevalue; - $finalgrade->timemodified = time(); - $DB->update_record('assign_grades', $finalgrade); - - $gradeupdate = new \stdClass(); - $gradeupdate->id = $finalgrade->id; - $gradeupdate->assignment = $assignmentid; - $gradeupdate->userid = $userid; - $gradeupdate->grade = $finalgradevalue; - $gradeupdate->rawgrade = $finalgradevalue; - $gradeupdate->grader = $USER->id; - $gradeupdate->timecreated = $finalgrade->timecreated; - $gradeupdate->timemodified = time(); - $assign = new \assign($context, null, null); - $assign->update_grade($gradeupdate); - - return true; - } - -} diff --git a/team_a/MoodlePlugin/learninglens/db/.DS_Store b/team_a/MoodlePlugin/learninglens/db/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 array( - 'riskbitmask' => RISK_SPAM | RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - ), - ), -); \ No newline at end of file diff --git a/team_a/MoodlePlugin/learninglens/db/services.php b/team_a/MoodlePlugin/learninglens/db/services.php deleted file mode 100644 index bb94928c..00000000 --- a/team_a/MoodlePlugin/learninglens/db/services.php +++ /dev/null @@ -1,160 +0,0 @@ - [ - 'classname' => 'local_learninglens\external\create_quiz', - 'description' => 'Create a quiz in a specified course', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/quiz:addinstance', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - - 'local_learninglens_import_questions' => [ - 'classname' => 'local_learninglens\external\import_questions', - 'description' => 'Import XML questions to a course question bank', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'moodle/question:add', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_add_type_randoms_to_quiz' => [ - 'classname' => 'local_learninglens\external\add_type_randoms_to_quiz', - 'description' => 'Add questions of type random to quiz from category', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/quiz:manage', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_get_rubric' => [ - 'classname' => 'local_learninglens\external\get_rubric', - 'description' => 'Returns instances of grading forms including rubrics.', - 'type' => 'read', - 'ajax' => true, - 'capabilities' => 'moodle/grade:view', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_create_assignment' => [ - 'classname' => 'local_learninglens\external\create_assignment', - 'description' => 'Creates an assignment and optionally attach a rubric.', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'moodle/course:manageactivities', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_get_rubric_grades' => [ - 'classname' => 'local_learninglens\external\get_rubric_grades', - 'description' => 'Gets rubric grades for a specific submission.', - 'type' => 'read', - 'ajax' => true, - 'capabilities' => 'mod/assign:grade', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_write_rubric_grades' => [ - 'classname' => 'local_learninglens\external\write_rubric_grades', - 'description' => 'Sets rubric grades for a specific submission.', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/assign:grade', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_write_grades' => [ - 'classname' => 'local_learninglens\external\write_grades', - 'description' => 'Sets grades for a specific submission.', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/assign:grade', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_create_lesson' => [ - 'classname' => 'local_learninglens\external\create_lesson', - 'description' => 'Creates a new lesson in a Moodle course and links it to the course modules', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/lesson:addinstance', - 'services' => [ - MOODLE_OFFICIAL_MOBILE_SERVICE, - ] - ], - 'local_learninglens_get_questions_from_quiz' => [ - 'classname' => 'local_learninglens\external\get_questions_from_quiz', - 'description' => 'Fetches questions linked to a quiz ID', - 'type' => 'read', - 'ajax' => true, - 'capabilities'=> 'mod/quiz:view', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], - ], - 'local_learninglens_add_quiz_override' => [ - 'classname' => 'local_learninglens\external\add_quiz_override', - 'description' => 'Adds an override to a quiz for a user or group.', - 'type' => 'write', - 'ajax' => true, - 'capabilities'=> 'mod/quiz:manage', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], - ], - 'local_learninglens_add_essay_override' => [ - 'classname' => 'local_learninglens\external\add_essay_override', - 'description' => 'Adds an override to a essay for a user or group.', - 'type' => 'write', - 'ajax' => true, - 'capabilities'=> 'mod/assign:manage', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], - ], - 'local_learninglens_get_lesson_plans_by_course' => [ - 'classname' => 'local_learninglens\external\get_lesson_plans_by_course', - 'description' => 'Retrieves lesson plans associated with a given course ID.', - 'type' => 'read', - 'ajax' => true, - 'capabilities' => 'mod/lesson:view', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] // Enables use in the Moodle Mobile App - ], - 'local_learninglens_delete_lesson_plan' => [ - 'classname' => 'local_learninglens\external\delete_lesson_plan', - 'description' => 'Deletes a lesson plan by ID.', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/lesson:manage', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] - ], - 'local_learninglens_update_lesson_plan' => [ - 'classname' => 'local_learninglens\external\update_lesson_plan', - 'description' => 'Updates an existing lesson plan by ID.', - 'type' => 'write', - 'ajax' => true, - 'capabilities' => 'mod/lesson:manage', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] - ], - 'local_learninglens_get_all_overrides' => [ - 'classname' => 'local_learninglens\external\get_all_overrides', - 'description' => 'Gets overrides for both quiz and essay', - 'type' => 'read', - 'ajax' => true, - 'capabilities' => 'mod/quiz:view, mod/assign:view', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] - ], - 'local_learninglens_get_question_stats_from_quiz' => [ - 'classname' => 'local_learninglens\external\get_question_stats_from_quiz', - 'description' => 'Fetches questions + stats (correct/incorrect counts) for a quiz', - 'type' => 'read', - 'ajax' => true, - 'capabilities'=> 'mod/quiz:view', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], - ], -]; \ No newline at end of file diff --git a/team_a/MoodlePlugin/learninglens/lang/en/local_learninglens.php b/team_a/MoodlePlugin/learninglens/lang/en/local_learninglens.php deleted file mode 100644 index 05c1c472..00000000 --- a/team_a/MoodlePlugin/learninglens/lang/en/local_learninglens.php +++ /dev/null @@ -1,23 +0,0 @@ -version = 2025031414; // YYYYMMDDHH (Year Month Day 24-hr time). -$plugin->requires = 2022112800; // YYYYMMDDHH (The release version of Moodle 4.1). -$plugin->component = 'local_learninglens'; // Name of your plugin (used for diagnostics). -$plugin->maturity = MATURITY_ALPHA; -?> \ No newline at end of file diff --git a/team_a/MoodlePlugin/local_adminer_moodle45_2025021700.zip b/team_a/MoodlePlugin/local_adminer_moodle45_2025021700.zip deleted file mode 100644 index 63ab56c5113b0b92496b2b4babdf400cb877dacd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 365706 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 O92u>KxKb(FLQNpthCb?zK+Lr=-M3d$a$ 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

AhJYp0@p5gnG^ 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 diff --git a/team_a/README.md b/team_a/README.md deleted file mode 100644 index 28196599..00000000 --- a/team_a/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# spring2025 -Fall SWEN 670 Cohort - -Team A (Learning Lens) - LLM Integrated Software Application for K-12 Education - - -Members: -Kevin Watts (Team Lead, Technical Writer) -Dusty McKinnon (Technical Writer, Lead QA Engineer) -Derek Sappington (Business Analyst, Software Engineer) -Daniel Diep (Software Engineer / Programmer, Testing) -Andrew Hammes (Business Analyst, Software Developer) -Dinesh Ghimire (Software Developer, Tester) -Nathaniel Boyd (Test Server Operator, System Admin) diff --git a/team_a/pubspec.yaml b/team_a/pubspec.yaml deleted file mode 100644 index 72ae07f9..00000000 --- a/team_a/pubspec.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: learninglens_app -description: A new Flutter project. - -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -version: 0.0.1+1 - -environment: - sdk: ^3.1.1 - -dependencies: - flutter: - sdk: flutter - flutter_dotenv: ^5.1.0 - xml: ^6.2.2 - http: ^1.2.1 - flutter_quill: ^10.8.0 - - english_words: ^4.0.0 - provider: ^6.0.0 - shared_preferences: ^2.2.0 - - -dev_dependencies: - flutter_test: - sdk: flutter - - flutter_lints: ^2.0.0 - -flutter: - uses-material-design: true \ No newline at end of file diff --git a/team_a/teamA/.example.env b/team_a/teamA/.example.env deleted file mode 100644 index 06c3adc5..00000000 --- a/team_a/teamA/.example.env +++ /dev/null @@ -1,11 +0,0 @@ -# This file contains the required environment variables for the application. -# To configure your environment, create a new `.env` file in the project root, -# copy these variables, and populate them with the appropriate values. - -openai_apikey= -MOODLE_USERNAME= -MOODLE_PASSWORD= -MOODLE_URL= -claudeApiKey= -perplexity_apikey= -GOOGLE_CLIENT_ID= \ No newline at end of file diff --git a/team_a/teamA/.gitignore b/team_a/teamA/.gitignore deleted file mode 100644 index 3af0d322..00000000 --- a/team_a/teamA/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# .metadata file from flutter create -.metadata - -# widget_test.dart file from flutter create -test/widget_test.dart - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -/assets/api-keys.json - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json -macos/* -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/team_a/teamA/.gitkeep b/team_a/teamA/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/team_a/teamA/README.md b/team_a/teamA/README.md deleted file mode 100644 index a35fcbf3..00000000 --- a/team_a/teamA/README.md +++ /dev/null @@ -1,18 +0,0 @@ -#learninglens_app - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. - -Test \ No newline at end of file diff --git a/team_a/teamA/analysis_options.yaml b/team_a/teamA/analysis_options.yaml deleted file mode 100644 index fd6dbde2..00000000 --- a/team_a/teamA/analysis_options.yaml +++ /dev/null @@ -1,14 +0,0 @@ -analyzer: - errors: - deprecated_member_use: ignore -include: package:flutter_lints/flutter.yaml - -linter: - rules: - avoid_print: false - prefer_const_constructors_in_immutables: false - prefer_const_constructors: false - prefer_const_literals_to_create_immutables: false - prefer_final_fields: false - unnecessary_breaks: true - use_key_in_widget_constructors: false diff --git a/team_a/teamA/assets/criteria.json b/team_a/teamA/assets/criteria.json deleted file mode 100644 index b2a4a34a..00000000 --- a/team_a/teamA/assets/criteria.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "Criteria": [ - { - "Name": "Introduction Effectiveness", - "Description": "clarity and effectiveness in the introductory paragraph by presenting the essay's main argument or focus." - }, - { - "Name": "Thesis Statement Strength", - "Description": "precision, clarity, and relevance in the thesis statement, effectively guiding the essay." - }, - { - "Name": "Conclusion Quality", - "Description": "effectiveness in the conclusion by summarizing key points and reinforcing the thesis." - }, - { - "Name": "Depth of Analysis", - "Description": "depth and complexity in analyzing the topic or themes within the essay." - }, - { - "Name": "Understanding of Context", - "Description": "understanding of the historical, cultural, or social context related to the essay's topic." - }, - { - "Name": "Logical Flow", - "Description": "logical progression of ideas and arguments throughout the essay." - }, - { - "Name": "Paragraph Structure", - "Description": "coherence and clarity in individual paragraphs, with clear topic sentences and supporting details." - }, - { - "Name": "Transition Between Ideas", - "Description": "effectiveness in transitioning between ideas or paragraphs within the essay." - }, - { - "Name": "Originality of Thought", - "Description": "originality and creativity in their analysis or argument throughout the essay." - }, - { - "Name": "Use of Literary Devices", - "Description": "identification and discussion of literary devices such as symbolism, metaphors, or imagery." - }, - { - "Name": "Grammar and Syntax", - "Description": "use of grammar, punctuation, and sentence structure throughout the essay." - }, - { - "Name": "Adherence to Assignment Guidelines", - "Description": "adherence to the assignment's requirements, including length, topic, and formatting." - }, - { - "Name": "Cohesion of Argument", - "Description": "strength and consistency in the main argument across all sections of the essay." - }, - { - "Name": "Relevance of Evidence", - "Description": "relevance and appropriateness in the supporting evidence used to back up claims." - }, - { - "Name": "Critical Thinking", - "Description": "critical thinking skills in evaluating texts, arguments, or perspectives." - }, - { - "Name": "Depth of Research", - "Description": "quality and depth of research, using credible sources where applicable." - }, - { - "Name": "Word Choice", - "Description": "precision, sophistication, and appropriateness in their vocabulary use throughout the essay." - }, - { - "Name": "Persuasiveness", - "Description": "persuasiveness in convincing the reader of their argument or perspective." - }, - { - "Name": "Citation and Referencing", - "Description": "use of citation formats and accuracy in referencing sources (APA, MLA, etc.)." - }, - { - "Name": "Engagement with Counterarguments", - "Description": "ability to acknowledge, engage with, and refute opposing viewpoints or counterarguments." - } - ] -} \ No newline at end of file diff --git a/team_a/teamA/assets/login_image.png b/team_a/teamA/assets/login_image.png deleted file mode 100644 index b56d6551a5cd1f87d51f88677be5646574933b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209378 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 callFunctionByName( - String functionName, Map args) async { - print('${functionName}, ${args}'); - try { - switch (functionName) { - case "getUserCourses": - final courses = await lmsService.getUserCourses(); - return _formatCourses(courses); - - case "getQuizzes": - if (!args.containsKey("courseID")) { - return "Error: Missing 'courseID'."; - } - // Try parse courseID - final courseID = int.tryParse(args["courseID"]); - if (courseID == null) { - return "Error: 'courseID' must be an integer."; - } - - // Check if quizTopicId was provided - if (!args.containsKey("quizTopicId") || - args["quizTopicId"] == null || - args["quizTopicId"].isEmpty) { - // Not provided => pass null to getQuizzes - final quizzes = await lmsService.getQuizzes(courseID, topicId: null); - return _formatQuizzes(quizzes); - } else { - // Provided => parse it - final int? quizTopicId = int.tryParse(args["quizTopicId"]); - if (quizTopicId == null) { - return "Error: 'quizTopicId' must be an integer if provided."; - } - final quizzes = - await lmsService.getQuizzes(courseID, topicId: quizTopicId); - return _formatQuizzes(quizzes); - } - - case "getQuizGradesForParticipants": - if (!args.containsKey("courseId") || !args.containsKey("quizId")) { - return "Error: Missing courseId or quizId."; - } - final courseId = args["courseId"]; - final quizId = int.parse(args["quizId"]); - final participants = - await lmsService.getQuizGradesForParticipants(courseId, quizId); - return _formatGrades(participants); - - case "getCourseParticipants": - if (!args.containsKey("courseId")) { - return "Error: Missing courseId."; - } - final courseId = args["courseId"]; - final participants = await lmsService.getCourseParticipants(courseId); - return _formatParticipants(participants); - - default: - return "Error: Unknown function '$functionName'."; - } - } catch (e) { - // For your real app, handle or log the exception in detail - return "Error: Exception occurred calling '$functionName': $e"; - } - } - - // Helper: format a list of courses - String _formatCourses(List courses) { - if (courses.isEmpty) return "No enrolled courses found."; - return courses - .map((c) => - "Course: ${c.fullName} (ID: ${c.id}, quizTopicId: ${c.quizTopicId})") - .join("\n"); - } - - // Helper: format a list of quizzes - String _formatQuizzes(List quizzes) { - if (quizzes.isEmpty) return "No quizzes found."; - return quizzes.map((q) => "Quiz: ${q.name} (ID: ${q.id})").join("\n"); - } - - // Helper: format quiz grades for participants - String _formatGrades(List participants) { - if (participants.isEmpty) return "No participants or grades found."; - return participants.map((p) { - final gradeStr = - (p.avgGrade != null) ? p.avgGrade.toString() : "No grade"; - return "Student: ${p.fullname} (ID: ${p.id}), Grade: $gradeStr"; - }).join("\n"); - } - - // Helper: format participants list - String _formatParticipants(List participants) { - if (participants.isEmpty) return "No participants found."; - return participants - .map((p) => - "Student: ${p.fullname} (ID: ${p.id}) Roles: ${p.roles.join(', ')}") - .join("\n"); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/experimental/assistant/textbased_function_caller_view.dart b/team_a/teamA/lib/Api/experimental/assistant/textbased_function_caller_view.dart deleted file mode 100644 index e2cb08c5..00000000 --- a/team_a/teamA/lib/Api/experimental/assistant/textbased_function_caller_view.dart +++ /dev/null @@ -1,218 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/experimental/assistant/textbased_function_caller.dart'; -import 'package:learninglens_app/Api/experimental/assistant/textbased_llm_client.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/llm_api_modules_base.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -class TextBasedFunctionCallerView extends StatefulWidget { - const TextBasedFunctionCallerView({Key? key}) : super(key: key); - - @override - _TextBasedFunctionCallerViewState createState() => - _TextBasedFunctionCallerViewState(); -} - -class _TextBasedFunctionCallerViewState - extends State { - final TextEditingController _controller = TextEditingController(); - final FocusNode _focusNode = FocusNode(); - final List> _messages = []; - late TextBasedLLMClient _chatGPT; - bool _isThinking = false; // Tracks if the bot is thinking - - LlmType selectedLLM = LlmType.GROK; //default to chatgpt - late LLM llm; - - @override - void initState() { - super.initState(); - - llm = getLLM(); - - _chatGPT = TextBasedLLMClient( - llm, - TextBasedFunctionCaller(LmsFactory.getLmsService()), - ); - } - - // grabs the selected LLM. - LLM getLLM() { - final aiModel; - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else if (selectedLLM == LlmType.PERPLEXITY) { - // aiModel = OpenAiLLM(perplexityApiKey); - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } else { - // default - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } - return aiModel; - } - - void _sendMessage() async { - if (_controller.text.isEmpty) return; - - setState(() { - _messages.add({"sender": "user", "text": _controller.text}); - _isThinking = true; // Show thinking dots - }); - - final userMessage = _controller.text; - _controller.clear(); - - // Add a "thinking" message - // setState(() { - // _messages.add({"sender": "bot", "text": "..."}); - // }); - - String response = await _chatGPT.sendMessage(userMessage); - - setState(() { - // _messages.removeLast(); // Remove "thinking" message - _messages.add({"sender": "bot", "text": response}); - _isThinking = false; // Bot has finished responding - }); - - _focusNode.requestFocus(); // Refocus input field - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'EduLense Assistant (Beta textbased)', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Column( - children: [ - Expanded( - child: ListView.builder( - itemCount: _messages.length, - itemBuilder: (context, index) { - final message = _messages[index]; - bool isUser = message["sender"] == "user"; - - return Padding( - padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10), - child: Row( - mainAxisAlignment: isUser - ? MainAxisAlignment.end - : MainAxisAlignment.start, - children: [ - if (!isUser) ...[ - CircleAvatar( - backgroundColor: Colors.grey[200], - child: Icon(Icons.android, color: Colors.blueAccent), - ), - SizedBox(width: 8), - ], - Flexible( - child: Container( - padding: EdgeInsets.all(12), - decoration: BoxDecoration( - color: - isUser ? Colors.blueAccent : Colors.grey[300], - borderRadius: BorderRadius.circular(15), - ), - child: Text( - message["text"]!, - style: TextStyle( - color: isUser ? Colors.white : Colors.black, - fontSize: 16, - ), - ), - ), - ), - if (isUser) ...[ - SizedBox(width: 8), - CircleAvatar( - backgroundColor: Colors.grey[200], - child: Icon(Icons.person, color: Colors.blueAccent), - ), - ], - ], - ), - ); - }, - ), - ), - if (_isThinking) - Padding( - padding: const EdgeInsets.all(8.0), - child: CircularProgressIndicator(), // Loading indicator - ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Row( - children: [ - Expanded( - child: TextField( - controller: _controller, - focusNode: _focusNode, - decoration: InputDecoration( - hintText: "Ask ${selectedLLM.displayName}...", - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - ), - ), - onSubmitted: (value) => _sendMessage(), - ), - ), - SizedBox(width: 8), - ClipOval( - child: Material( - color: Colors.blueAccent, - child: InkWell( - onTap: _sendMessage, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Icon(Icons.send, color: Colors.white), - ), - ), - ), - ), - DropdownButton( - value: selectedLLM, - onChanged: (LlmType? newValue) { - setState(() { - selectedLLM = newValue!; - llm = getLLM(); - - _chatGPT = TextBasedLLMClient( - llm, - TextBasedFunctionCaller(LmsFactory.getLmsService()), - ); - - }); - }, - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text( - llm.displayName, - style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) - ? Colors.black87 - : Colors.grey, - ), - ), - ); - }).toList()), - ], - ), - ), - ], - ), - ); - } -} diff --git a/team_a/teamA/lib/Api/experimental/assistant/textbased_llm_client.dart b/team_a/teamA/lib/Api/experimental/assistant/textbased_llm_client.dart deleted file mode 100644 index 6e781877..00000000 --- a/team_a/teamA/lib/Api/experimental/assistant/textbased_llm_client.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/Api/experimental/assistant/textbased_function_caller.dart'; -import 'package:learninglens_app/Api/llm/llm_api_modules_base.dart'; -import 'package:learninglens_app/Api/llm/prompt_engine.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -// Replicate the functionality used in chatgpt_client, but swap over to prompt engineering instead of the function caller. -// This code gears the development for the assistant to be more generic in terms of which llm is used rather than relying on -// functionality developement by OpenAI. -class TextBasedLLMClient { - final LLM llm; - final TextBasedFunctionCaller functionCaller; - - /// Maintains the entire conversation (system, user, assistant). - final List> _conversation = []; - - TextBasedLLMClient(this.llm, this.functionCaller) { - // Add system instructions once at the beginning - _conversation.add({ - "role": "system", - "content": PromptEngine.prompt_assistant - }); - } - - /// Send a user message (multi-turn). If the LLM keeps calling functions, - /// we'll keep looping until we get a plain text answer. - Future sendMessage(String userMessage) async { - // 1) Add the user's message to conversation - _conversation.add({ - "role": "user", - "content": userMessage, - }); - - // 2) Multi-turn loop: keep calling the LLM until we get a non-CALL response - while (true) { - final llmReply = await _callLLM(_conversation); - if (llmReply == null || llmReply.isEmpty) { - return "No response from the LLM."; - } - - final trimmedReply = llmReply.trim(); - - // If the model requests a function call - if (trimmedReply.startsWith("CALL ")) { - // Handle the function call and add the result to the conversation - final functionResult = await _handleFunctionCall(trimmedReply); - - // Insert the function result as an "assistant" message - _conversation.add({ - "role": "assistant", - "content": functionResult, - }); - - // Then loop again so the LLM can see that result and possibly call another function - } else { - // It's a final textual answer - _conversation.add({ - "role": "assistant", - "content": trimmedReply, - }); - return trimmedReply; - } - } - } - - /// Calls the OpenAI Chat Completion API with the entire conversation so far - Future _callLLM(List> conversation) async { - - - final response = await ApiService().httpPost( - Uri.parse(llm.url), - headers: { - "Authorization": 'Bearer ${llm.apiKey}', - "Content-Type": "application/json", - }, - body: jsonEncode({ - "model": llm.model, - "messages": conversation.map((m) { - return {"role": m["role"], "content": m["content"]}; - }).toList(), - "temperature": 0.7, - "top_p": 0.9, - }), - ); - - if (response.statusCode != 200) { - return "Error from LLM: ${response.statusCode} => ${response.body}"; - } - - final jsonData = jsonDecode(response.body); - if (jsonData["choices"] == null || jsonData["choices"].isEmpty) { - return null; - } - - return jsonData["choices"][0]["message"]["content"]; - } - - /// Parses a "CALL functionName(...)" string, calls the local function, returns its result - Future _handleFunctionCall(String callString) async { - // Example: "CALL getQuizzes(courseID=101, quizTopicId=201)" - final afterCall = callString.substring(5).trim(); // remove "CALL " - final openParenIndex = afterCall.indexOf("("); - if (openParenIndex == -1) { - return "Error: malformed function call, missing '('"; - } - - final functionName = afterCall.substring(0, openParenIndex).trim(); - - final closeParenIndex = afterCall.indexOf(")", openParenIndex); - if (closeParenIndex == -1) { - return "Error: malformed function call, missing ')'"; - } - - final argsString = afterCall.substring(openParenIndex + 1, closeParenIndex).trim(); - - // Parse key=value pairs - final Map argsMap = {}; - if (argsString.isNotEmpty) { - final pairs = argsString.split(","); - for (final pair in pairs) { - final parts = pair.split("="); - if (parts.length == 2) { - final key = parts[0].trim(); - final val = parts[1].trim(); - argsMap[key] = val; // Keep as string; parse to int if you like - } - } - } - - // Actually call the function - final result = await functionCaller.callFunctionByName(functionName, argsMap); - return result; - } -} diff --git a/team_a/teamA/lib/Api/llm/claudeai_api.dart b/team_a/teamA/lib/Api/llm/claudeai_api.dart deleted file mode 100644 index c93714b7..00000000 --- a/team_a/teamA/lib/Api/llm/claudeai_api.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'package:learninglens_app/services/api_service.dart'; - -class ClaudeAiAPI { - final String claudeAiKey; - ClaudeAiAPI(this.claudeAiKey); - - Map convertHttpRespToJson(String httpResponseString) { - return (json.decode(httpResponseString) as Map); - } - - String getPostBody(String queryMessage) { - return jsonEncode({ - 'model': 'claude-3-5-sonnet-20240620', - 'max_tokens': 1024, - 'system': 'Be precise and concise', - 'messages': [ - {'role': 'user', 'content': queryMessage} - ] - }); - } - - Map getPostHeaders() { - return ({ - 'anthropic-version': '2023-06-01', - 'content-type': 'application/json', - 'anthropic-dangerous-direct-browser-access': 'true', - 'x-api-key': claudeAiKey, - }); - } - - Uri getPostUrl() => Uri.https('api.anthropic.com', '/v1/messages'); - - Future postMessage( - Uri url, Map postHeaders, Object postBody) async { - final httpPackageResponse = - await ApiService().httpPost(url, headers: postHeaders, body: postBody); - - if (httpPackageResponse.statusCode != 200) { - print('Failed to retrieve the http package!'); - print('statusCode : ${httpPackageResponse.statusCode}'); - print('Reason: ${httpPackageResponse.body}'); - - return ""; - } - - return httpPackageResponse.body; - } - - List parseQueryResponse(String resp) { - // ignore: prefer_adjacent_string_concatenation - String quizRegExp = - // r'(<\?xml.*?\?>\s*(\s*.*?\s*.*?\s*(.*?)\s*.*?(\s*.*?)+\s*\s*.*?\s*(.*?)\s*.*?)+\s*)'; - r'(<\?xml.*?\?>\s*.*?)'; - - RegExp exp = RegExp(quizRegExp); - String respNoNewlines = resp.replaceAll('\n', ''); - Iterable matches = exp.allMatches(respNoNewlines); - List parsedResp = []; - - print("Parsing the query response - matches: $matches"); - - for (final m in matches) { - if (m.group(0) != null) { - parsedResp.add(m.group(0)!); - - print("This is a match : ${m.group(0)}"); - print("Number of groups in the match: ${m.groupCount}"); - print("parsedResp : $parsedResp"); - } - } - - return parsedResp; - } - - Future postToLlm(String queryPrompt) async { - var resp = ""; - - // use the following test query so Perplexity doesn't charge - // 'How many stars are there in our galaxy?' - if (queryPrompt.isNotEmpty) { - resp = await queryAI(queryPrompt); - } - return resp; - } - - Future queryAI(String query) async { - final postHeaders = getPostHeaders(); - final postBody = getPostBody(query); - final httpPackageUrl = getPostUrl(); - - final httpPackageRespString = - await postMessage(httpPackageUrl, postHeaders, postBody); - - final httpPackageResponseJson = - convertHttpRespToJson(httpPackageRespString); - - var retResponse = ""; - for (var respChoice in httpPackageResponseJson['content']) { - retResponse += respChoice['text']; - } - // print("In queryAI - content : $retResponse"); - return retResponse; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/llm/enum/llm_enum.dart b/team_a/teamA/lib/Api/llm/enum/llm_enum.dart deleted file mode 100644 index fc48cf81..00000000 --- a/team_a/teamA/lib/Api/llm/enum/llm_enum.dart +++ /dev/null @@ -1,8 +0,0 @@ -enum LlmType { - CHATGPT('ChatGPT'), - PERPLEXITY('Perplexity'), - GROK('Grok'); - - final String displayName; - const LlmType(this.displayName); -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/llm/grok_api.dart b/team_a/teamA/lib/Api/llm/grok_api.dart deleted file mode 100644 index f197b933..00000000 --- a/team_a/teamA/lib/Api/llm/grok_api.dart +++ /dev/null @@ -1,192 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/Api/llm/llm_api_modules_base.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -class GrokLLM implements LLM { - @override - final String apiKey; - @override - final String url = 'https://api.x.ai/v1/chat/completions'; - @override - final String model = 'grok-2-latest'; - - GrokLLM(this.apiKey); - - Map convertHttpRespToJson(String httpResponseString) { - return (json.decode(httpResponseString) as Map); - } - - /// - /// - /// - String getPostBody(String queryMessage) { - return jsonEncode({ - 'model': model, - 'messages': [ - {'role': 'system', 'content': 'Be precise and concise'}, - {'role': 'user', 'content': queryMessage} - ] - }); - } - - /// - /// - /// - Map getPostHeaders() { - return ({ - 'accept': 'application/json', - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $apiKey', - }); - } - - /// - /// - /// - Uri getPostUrl() => Uri.https('api.x.ai', '/v1/chat/completions'); - - /// - /// - /// - Future postMessage( - Uri url, Map postHeaders, Object postBody) async { - final httpPackageResponse = - await ApiService().httpPost(url, headers: postHeaders, body: postBody); - - print(url); - print(postHeaders); - print(postBody); - - if (httpPackageResponse.statusCode != 200) { - print('Failed to retrieve the http package!'); - print('statusCode : ${httpPackageResponse.statusCode}'); - print('Reason: ${httpPackageResponse.body}'); - - return ""; - } - - print("In postmessage : ${httpPackageResponse.body}"); - return httpPackageResponse.body; - } - - List parseQueryResponse(String resp) { - // ignore: prefer_adjacent_string_concatenation - String quizRegExp = - // r'(<\?xml.*?\?>\s*(\s*.*?\s*.*?\s*(.*?)\s*.*?(\s*.*?)+\s*\s*.*?\s*(.*?)\s*.*?)+\s*)'; - r'(<\?xml.*?\?>\s*.*?)'; - - RegExp exp = RegExp(quizRegExp); - String respNoNewlines = resp.replaceAll('\n', ''); - Iterable matches = exp.allMatches(respNoNewlines); - List parsedResp = []; - - print("Parsing the query response - matches: $matches"); - - for (final m in matches) { - if (m.group(0) != null) { - parsedResp.add(m.group(0)!); - - print("This is a match : ${m.group(0)}"); - print("Number of groups in the match: ${m.groupCount}"); - print("parsedResp : $parsedResp"); - } - } - - return parsedResp; - } - - /// - /// - /// - Future postToLlm(String queryPrompt) async { - var resp = ""; - - // use the following test query so Perplexity doesn't charge - // 'How many stars are there in our galaxy?' - if (queryPrompt.isNotEmpty) { - resp = await queryAI(queryPrompt); - } - return resp; - } - - /// - /// - /// - Future queryAI(String query) async { - final postHeaders = getPostHeaders(); - final postBody = getPostBody(query); - final httpPackageUrl = getPostUrl(); - - final httpPackageRespString = - await postMessage(httpPackageUrl, postHeaders, postBody); - - final httpPackageResponseJson = - convertHttpRespToJson(httpPackageRespString); - - var retResponse = ""; - for (var respChoice in httpPackageResponseJson['choices']) { - retResponse += respChoice['message']['content']; - } - print("In queryAI - content : $retResponse"); - return retResponse; - } - - Future getChatResponse(String prompt) async { - - final postHeaders = getPostHeaders(); - final postBody = getPostBody(prompt); - final httpPackageUrl = getPostUrl(); - - try { - // Make the POST request to the chat completions endpoint - var response = await ApiService().httpPost(httpPackageUrl, headers: postHeaders, body: postBody); - - // Check for successful response - if (response.statusCode == 200) { - var data = jsonDecode(response.body); - return data['choices'][0]['message']['content'] - .trim(); // Return the chat response - } else { - // Log the error response and handle failure cases - print('Failed to fetch response. Status code: ${response.statusCode}'); - print('Response body: ${response.body}'); - return 'Sorry, I couldn’t fetch a response. Please try again.'; - } - } catch (error) { - // Log and handle connection or parsing errors - print('Error occurred: $error'); - return 'An error occurred. Please check your internet connection and try again.'; - } - } - - - - - @override - Future generate(String prompt) async { - final url = Uri.parse(this.url); // Hypothetical endpoint - final headers = { - 'Authorization': 'Bearer $apiKey', - 'Content-Type': 'application/json', - }; - final body = jsonEncode({ - 'model': model, // Use the configurable model - 'messages': [ - {'role': 'user', 'content': prompt}, - ], - 'max_tokens': 500, // Limit response length - }); - - final response = await http.post(url, headers: headers, body: body); - if (response.statusCode != 200) { - throw Exception('Grok API error: ${response.statusCode} - ${response.body}'); - } - - final data = jsonDecode(response.body); - return data['choices'][0]['message']['content'].trim(); // Adjust based on actual response structure - } - - -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/llm/llm_api_modules_base.dart b/team_a/teamA/lib/Api/llm/llm_api_modules_base.dart deleted file mode 100644 index bbb6bdf9..00000000 --- a/team_a/teamA/lib/Api/llm/llm_api_modules_base.dart +++ /dev/null @@ -1,17 +0,0 @@ -// TODO: Put public facing types in this file. - -/// Checks if you are awesome. Spoiler: you are. -class Awesome { - bool get isAwesome => true; -} -//This is the abstract class for the LLM API module -//It has a single method called generate which takes a string prompt and returns a string -abstract class LLM { - final String apiKey; - String get url; - String get model; - - LLM(this.apiKey); - - Future generate(String prompt); -} diff --git a/team_a/teamA/lib/Api/llm/openai_api.dart b/team_a/teamA/lib/Api/llm/openai_api.dart deleted file mode 100644 index e5e96b1c..00000000 --- a/team_a/teamA/lib/Api/llm/openai_api.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/Api/llm/llm_api_modules_base.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -class OpenAiLLM implements LLM { - @override - final String apiKey; - @override - final String url = 'https://api.openai.com/v1/chat/completions'; - @override - final String model = 'gpt-4o-mini'; - OpenAiLLM(this.apiKey); - - Map convertHttpRespToJson(String httpResponseString) { - return (json.decode(httpResponseString) as Map); - } - - /// - /// - /// - String getPostBody(String queryMessage) { - return jsonEncode({ - 'model': model, - 'messages': [ - {'role': 'system', 'content': 'Be precise and concise'}, - {'role': 'user', 'content': queryMessage} - ] - }); - } - - /// - /// - /// - Map getPostHeaders() { - return ({ - 'accept': 'application/json', - 'content-type': 'application/json', - 'authorization': 'Bearer $apiKey', - }); - } - - /// - /// - /// - Uri getPostUrl() => Uri.https('api.openai.com', '/v1/chat/completions'); - - /// - /// - /// - Future postMessage( - Uri url, Map postHeaders, Object postBody) async { - final httpPackageResponse = - await ApiService().httpPost(url, headers: postHeaders, body: postBody); - - print(url); - print(postHeaders); - print(postBody); - - if (httpPackageResponse.statusCode != 200) { - print('Failed to retrieve the http package!'); - print('statusCode : ${httpPackageResponse.statusCode}'); - print('Reason: ${httpPackageResponse.body}'); - - return ""; - } - - print("In postmessage : ${httpPackageResponse.body}"); - return httpPackageResponse.body; - } - - List parseQueryResponse(String resp) { - // ignore: prefer_adjacent_string_concatenation - String quizRegExp = - // r'(<\?xml.*?\?>\s*(\s*.*?\s*.*?\s*(.*?)\s*.*?(\s*.*?)+\s*\s*.*?\s*(.*?)\s*.*?)+\s*)'; - r'(<\?xml.*?\?>\s*.*?)'; - - RegExp exp = RegExp(quizRegExp); - String respNoNewlines = resp.replaceAll('\n', ''); - Iterable matches = exp.allMatches(respNoNewlines); - List parsedResp = []; - - print("Parsing the query response - matches: $matches"); - - for (final m in matches) { - if (m.group(0) != null) { - parsedResp.add(m.group(0)!); - - print("This is a match : ${m.group(0)}"); - print("Number of groups in the match: ${m.groupCount}"); - print("parsedResp : $parsedResp"); - } - } - - return parsedResp; - } - - /// - /// - /// - Future postToLlm(String queryPrompt) async { - var resp = ""; - - // use the following test query so Perplexity doesn't charge - // 'How many stars are there in our galaxy?' - if (queryPrompt.isNotEmpty) { - resp = await queryAI(queryPrompt); - } - return resp; - } - - /// - /// - /// - Future queryAI(String query) async { - final postHeaders = getPostHeaders(); - final postBody = getPostBody(query); - final httpPackageUrl = getPostUrl(); - - final httpPackageRespString = - await postMessage(httpPackageUrl, postHeaders, postBody); - - final httpPackageResponseJson = - convertHttpRespToJson(httpPackageRespString); - - var retResponse = ""; - for (var respChoice in httpPackageResponseJson['choices']) { - retResponse += respChoice['message']['content']; - } - print("In queryAI - content : $retResponse"); - return retResponse; - } - - Future getChatResponse(String prompt) async { - - final postHeaders = getPostHeaders(); - final postBody = getPostBody(prompt); - final httpPackageUrl = getPostUrl(); - - try { - // Make the POST request to the chat completions endpoint - var response = await ApiService().httpPost(httpPackageUrl, headers: postHeaders, body: postBody); - - // Check for successful response - if (response.statusCode == 200) { - var data = jsonDecode(response.body); - return data['choices'][0]['message']['content'] - .trim(); // Return the chat response - } else { - // Log the error response and handle failure cases - print('Failed to fetch response. Status code: ${response.statusCode}'); - print('Response body: ${response.body}'); - return 'Sorry, I couldn’t fetch a response. Please try again.'; - } - } catch (error) { - // Log and handle connection or parsing errors - print('Error occurred: $error'); - return 'An error occurred. Please check your internet connection and try again.'; - } - } - - @override - Future generate(String prompt) async { - print("In generate - prompt : $prompt"); - -final url = Uri.parse(this.url); - final headers = { - 'Authorization': 'Bearer $apiKey', - 'Content-Type': 'application/json', - }; - final body = jsonEncode({ - 'model': model, - 'messages': [ - {'role': 'system', 'content': 'You are a helpful assistant.'}, - {'role': 'user', 'content': prompt}, - ], - 'max_tokens': 500, // Limit response length - }); - - final response = await http.post(url, headers: headers, body: body); - if (response.statusCode != 200) { - throw Exception('OpenAI API error: ${response.statusCode} - ${response.body}'); - } - - final data = jsonDecode(response.body); - return data['choices'][0]['message']['content'].trim(); - - } - -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/llm/perplexity_api.dart b/team_a/teamA/lib/Api/llm/perplexity_api.dart deleted file mode 100644 index 49aae50a..00000000 --- a/team_a/teamA/lib/Api/llm/perplexity_api.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'package:learninglens_app/Api/llm/llm_api_modules_base.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -class PerplexityLLM implements LLM -{ - @override - final String apiKey; - @override - final String url = 'https://api.perplexity.ai/chat/completions'; - @override - final String model = 'llama-3.1-sonar-large-128k-online'; - - PerplexityLLM(this.apiKey); - - Map convertHttpRespToJson(String httpResponseString) - { - return (json.decode(httpResponseString) as Map); - } - - // - String getPostBody(String queryMessage) - { - return jsonEncode({ - // 'model': 'llama-3-sonar-large-32k-online', - //'model': 'llama-3.1-sonar-large-128k-chat', - 'model': model, - 'messages': [ - {'role': 'system', 'content': 'Be precise and concise'}, - {'content': queryMessage, 'role': 'user'} - ] - }); - } - - // - Map getPostHeaders() - { - return ({ - 'accept': 'application/json', - 'content-type': 'application/json', - 'authorization': 'Bearer $apiKey', - }); - } - - // - Uri getPostUrl() => Uri.https(this.url); - - // - Future postMessage( - Uri url, Map postHeaders, Object postBody) async - { - final httpPackageResponse = - await ApiService().httpPost(url, headers: postHeaders, body: postBody); - - if (httpPackageResponse.statusCode != 200) { - print('Failed to retrieve the http package!'); - print('statusCode : ${httpPackageResponse.statusCode}'); - print('body: ${httpPackageResponse.body}'); - return ""; - } - - print("In postmessage : ${httpPackageResponse.body}"); - return httpPackageResponse.body; - } - - List parseQueryResponse(String resp) - { - // ignore: prefer_adjacent_string_concatenation - String quizRegExp = - // r'(<\?xml.*?\?>\s*(\s*.*?\s*.*?\s*(.*?)\s*.*?(\s*.*?)+\s*\s*.*?\s*(.*?)\s*.*?)+\s*)'; - r'(<\?xml.*?\?>\s*.*?)'; - - RegExp exp = RegExp(quizRegExp); - String respNoNewlines = resp.replaceAll('\n', ''); - Iterable matches = exp.allMatches(respNoNewlines); - List parsedResp = []; - - print("Parsing the query response - matches: $matches"); - - for (final m in matches) { - if (m.group(0) != null) { - parsedResp.add(m.group(0)!); - - print("This is a match : ${m.group(0)}"); - print("Number of groups in the match: ${m.groupCount}"); - print("parsedResp : $parsedResp"); - } - } - - return parsedResp; - } - - // - Future postToLlm(String queryPrompt) async - { - var resp = ""; - - // use the following test query so Perplexity doesn't charge - // 'How many stars are there in our galaxy?' - if (queryPrompt.isNotEmpty) { - resp = await queryAI(queryPrompt); - } - return resp; - } - - // - Future queryAI(String query) async - { - final postHeaders = getPostHeaders(); - final postBody = getPostBody(query); - final httpPackageUrl = getPostUrl(); - - final httpPackageRespString = - await postMessage(httpPackageUrl, postHeaders, postBody); - - final httpPackageResponseJson = - convertHttpRespToJson(httpPackageRespString); - - var retResponse = ""; - for (var respChoice in httpPackageResponseJson['choices']) { - retResponse += respChoice['message']['content']; - } - // print("In queryAI - content : $retResponse"); - return retResponse; - } - - Future getChatResponse(String prompt) async { - - final postHeaders = getPostHeaders(); - final postBody = getPostBody(prompt); - final httpPackageUrl = getPostUrl(); - - try { - // Make the POST request to the chat completions endpoint - var response = await ApiService().httpPost(httpPackageUrl, headers: postHeaders, body: postBody); - - // Check for successful response - if (response.statusCode == 200) { - var data = jsonDecode(response.body); - return data['choices'][0]['message']['content'] - .trim(); // Return the chat response - } else { - // Log the error response and handle failure cases - print('Failed to fetch response. Status code: ${response.statusCode}'); - print('Response body: ${response.body}'); - return 'Sorry, I couldn’t fetch a response. Please try again.'; - } - } catch (error) { - // Log and handle connection or parsing errors - print('Error occurred: $error'); - return 'An error occurred. Please check your internet connection and try again.'; - } - } - - @override - Future generate(String prompt) async { - print('Generating response for prompt Perplexity: $prompt'); - - final postHeaders = getPostHeaders(); - final postBody = getPostBody(prompt); - final url = getPostUrl(); - final responseString = await postMessage(url, postHeaders, postBody); - final responseJson = jsonDecode(responseString); - return responseJson['choices'][0]['message']['content'].trim(); - } - -} diff --git a/team_a/teamA/lib/Api/llm/prompt_engine.dart b/team_a/teamA/lib/Api/llm/prompt_engine.dart deleted file mode 100644 index 95d338af..00000000 --- a/team_a/teamA/lib/Api/llm/prompt_engine.dart +++ /dev/null @@ -1,133 +0,0 @@ -import 'package:learninglens_app/beans/assignment_form.dart'; - -class PromptEngine { - - static const prompt_quizgen_college = - 'Generate a quiz in XML format ' - 'that is compatible with Moodle XML import. The quiz is to be on the subject of ' - '[subject] and should be related to [topic]. ' - 'The quiz should be the same level of difficulty for college [gradelevel] students of the ' - 'English-speaking language. '; - - static const prompt_quizgen_high_school = - 'Generate a quiz in XML format ' - 'that is compatible with Moodle XML import. The quiz is to be on the subject of ' - '[subject] and should be related to [topic]. ' - 'The quiz should be the same level of difficulty for high school [gradelevel] students of the ' - 'English-speaking language. '; - - static const prompt_quizgen_other = - 'Generate a quiz in XML format ' - 'that is compatible with Moodle XML import. The quiz is to be on the subject of ' - '[subject] and should be related to [topic]. ' - 'The quiz should be the same level of difficulty for [gradelevel] grade students of the ' - 'English-speaking language. '; - - - static const prompt_quizgen_xmlonly = - 'Provide only the XML in your response. '; - - static const prompt_quizgen_choice_example = - 'Please use this XML sample as a template for your response: Question 1 What does CPU stand for? Central Processing Unit Correct! The CPU is the primary component of a computer that processes instructions. Computer Processing Unit Incorrect. While close, this is not the correct term. Central Program Unit Incorrect. This is not the correct term for CPU. Control Processing Unit Incorrect. While the CPU does involve processing, this is not the correct term. Question 2 Which of the following is not a programming paradigm? Object-Oriented Programming Incorrect. Object-Oriented Programming is a valid programming paradigm. Functional Programming Incorrect. Functional Programming is a valid programming paradigm. Quantum Programming Correct! While quantum computing exists, "Quantum Programming" is not a standard programming paradigm. Procedural Programming Incorrect. Procedural Programming is a valid programming paradigm. Question 3 What is the primary function of an operating system? Manage computer hardware and software resources Correct! The operating system acts as an intermediary between programs and the computer hardware. Create documents and spreadsheets Incorrect. This is the function of application software, not the operating system. Browse the internet Incorrect. Web browsing is a function of web browser applications, not the operating system itself. Play video games Incorrect. Playing games is a function of game software, not the primary function of an operating system. Question 4 Which of the following is an example of a high-level programming language? Assembly Incorrect. Assembly is a low-level programming language. Machine Code Incorrect. Machine code is the lowest-level programming language. Python Correct! Python is an example of a high-level programming language. Binary Incorrect. Binary is not a programming language, but a number system used in computing. Question 5 What does HTML stand for? Hypertext Markup Language Correct! HTML is used to structure content on the web. Hyperlinks and Text Markup Language Incorrect. While HTML does involve hyperlinks, this is not the correct expansion of the acronym. Home Tool Markup Language Incorrect. This is not what HTML stands for. Hyper Transfer Markup Language Incorrect. This is not the correct expansion of HTML. '; - static const prompt_quizgen_truefalse_example = - 'Please use this XML sample as a template for your response: World War 2 Question 1The Normandy landings, also known as D-Day, took place on June 6, 1944.TrueCorrect! The Normandy landings, codenamed Operation Neptune, indeed took place on June 6, 1944, marking the beginning of the Allied invasion of Nazi-occupied Western Europe.FalseIncorrect. The Normandy landings, also known as D-Day, did occur on June 6, 1944. This date marks a crucial turning point in World War 2.World War 2 Question 2The atomic bombs dropped on Hiroshima and Nagasaki were codenamed "Little Boy" and "Fat Man" respectively.TrueCorrect! "Little Boy" was the codename for the bomb dropped on Hiroshima on August 6, 1945, while "Fat Man" was dropped on Nagasaki on August 9, 1945.FalseIncorrect. The atomic bombs were indeed codenamed "Little Boy" (Hiroshima) and "Fat Man" (Nagasaki). These were the only two nuclear weapons ever used in warfare.World War 2 Question 3The Battle of Stalingrad ended with a decisive Soviet victory, marking a turning point on the Eastern Front.TrueCorrect! The Battle of Stalingrad, which lasted from August 23, 1942, to February 2, 1943, ended in a decisive Soviet victory and is considered a major turning point in World War 2.FalseIncorrect. The Battle of Stalingrad did indeed end with a decisive Soviet victory, which marked a crucial turning point on the Eastern Front and in World War 2 as a whole. '; - static const prompt_quizgen_shortanswer_example = - 'Please use this XML sample as a template for your response: Combinatorics Question 1In how many ways can 5 distinct books be arranged on a shelf?1205!Combinatorics Question 2How many different 4-digit numbers can be formed using the digits 1, 2, 3, 4, 5, 6 if no digit can be repeated?360 '; - static const prompt_quizgen_essay_example = - 'Please use this XML sample as a template for your response: American Revolution Essay Write a well-structured essay analyzing the key factors that led to the American Revolution and its long-term impact on the formation of the United States. Your essay should address the following points:

  • Discuss at least three major events or policies that contributed to growing tensions between the American colonies and Great Britain in the decade leading up to 1776.
  • Explain the significance of the Declaration of Independence, both as a philosophical document and as a catalyst for revolutionary action.
  • Analyze the role of key figures such as George Washington, Thomas Jefferson, and Benjamin Franklin in shaping the course of the revolution.
  • Evaluate the impact of the American Revolution on the political, social, and economic structures of the newly formed United States.
  • Consider how the ideals of the American Revolution influenced later democratic movements both in the United States and around the world.

Your essay should be approximately 1000-1200 words in length. Use specific historical examples to support your arguments, and be sure to cite any sources you use.

]]> This essay requires you to demonstrate your understanding of the causes and consequences of the American Revolution, as well as your ability to analyze historical events and their significance. 100 0 0 editor 1 15 0 0 Grading Criteria:

  • Clear thesis statement and well-structured argument: 20 points
  • Accurate discussion of pre-revolutionary events and policies: 20 points
  • Insightful analysis of the Declaration of Independence: 15 points
  • Thoughtful examination of key revolutionary figures: 15 points
  • Comprehensive evaluation of the revolution\'s impact: 20 points
  • Consideration of the revolution\'s broader influence: 10 points
  • Use of specific historical examples and proper citations: 10 points
]]>
'; - static const prompt_quizgen_coding_example = - 'Please use this XML sample as a template for your response: Dart List Manipulation: Filtering Even Numbers Write a Dart function called filterEvenNumbers that takes a list of integers as input and returns a new list containing only the even numbers from the input list. Your function should use the following signature:

 List filterEvenNumbers(List numbers)         

Requirements:

  • Use Dart\'s list methods to implement the filtering logic.
  • The original list should not be modified.
  • If the input list is empty, return an empty list.
  • Include comments to explain your code.

Test your function with different input lists to ensure it works correctly.

]]>
100 0 0 editor 1 30 0 0 void main() { List numbers1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; List result1 = filterEvenNumbers(numbers1); print(\'Test 1: \$result1\'); // Expected: [2, 4, 6, 8, 10] List numbers2 = [1, 3, 5, 7, 9]; List result2 = filterEvenNumbers(numbers2); print(\'Test 2: \$result2\'); // Expected: [] List numbers3 = []; List result3 = filterEvenNumbers(numbers3); print(\'Test 3: \$result3\'); // Expected: [] } List filterEvenNumbers(List numbers) { // Your implementation here } ]]> filterEvenNumbers(List numbers) { // Your code here } void main() { // Test your function here } ]]>
'; - // 'Please use this XML sample as a template for your response: Maximum grade goes here00editorfilepicker11501Level 4, the highest criteria score goes here.Level 3 criteria score goes hereLevel 2 criteria score goes hereLevel 1, the lowest criteria score goes hereInput goes hereExpected output goes here '; - // 'Please use this XML sample as a template for your response: Recursive Functions in DartImplement a recursive function in Dart that calculates the nth Fibonacci number. The Fibonacci sequence is defined as follows: the first two numbers are 0 and 1, and each subsequent number is the sum of the two preceding ones. Your function should take an integer n as input and return the nth Fibonacci number. Additionally, explain the time complexity of your recursive solution and suggest how you might optimize it using memoization. Provide your code implementation and explanation below.A well-implemented recursive Fibonacci function should correctly calculate the nth Fibonacci number. The explanation should discuss the exponential time complexity of the naive recursive solution and how memoization can improve it to linear time complexity.1000editor1150'; - - static const prompt_assistant = """ - You are EduLense, a specialized e-learning assistant. You have these possible functions: - 1) getUserCourses() - 2) getCourseParticipants(courseId=?) - 3) getQuizzes(courseID=?, quizTopicId=?) - 4) getQuizGradesForParticipants(courseId=?, quizId=?) - - If you need to call a function to fulfill the user's request, - respond EXACTLY in the format (on a single line): - CALL functionName(arg1=value1, arg2=value2) - - You can make multiple function calls if you need step-by-step data: - - For example, if the user says "What quizzes do I have for my Math course?", - you might first call: - CALL getUserCourses() - to find the course ID for "Math" (like 101). - - Then parse that result. If you see "Math 101 (ID: 101, quizTopicId: 201)", - call: - CALL getQuizzes(courseID=101, quizTopicId=) - - Once you have the quizzes, produce a final text answer (like "You have a midterm quiz..."). - - Avoid calling getUserCourses() repeatedly if you already have the data. - - If you do not need any function call, just provide a direct answer in plain text. - - Example conversation: - User: "Who is in my Math course?" - You might do: - CALL getUserCourses() - (assume the result shows "Math 101" => ID=101) - Then: - CALL getCourseParticipants(courseId=101) - Finally, once you get the participants, answer in plain text. - - Always provide a final text summary once you have enough data from function calls. - Do not keep calling functions indefinitely. - """; - - static String _FormatQuestionNumbers(AssignmentForm form) { - String ret = 'The quiz should have '; - List questionsCount = []; - int count; - if (form.multipleChoiceCount > 0) { - count = form.multipleChoiceCount; - print(count); - if (count == 1) { - questionsCount.add("$count multiple choice question"); - } else { - questionsCount.add("$count multiple choice questions"); - } - } if (form.trueFalseCount > 0) { - count = form.trueFalseCount; - if (count == 1) { - questionsCount.add("$count true or false question"); - } else { - questionsCount.add("$count true or false questions"); - } - } - if (form.shortAnswerCount > 0) { - count = form.shortAnswerCount; - if (count == 1) { - questionsCount.add("$count short answer question"); - } else { - questionsCount.add("$count short answer questions"); - } - } - return "$ret${questionsCount.join(", ")}. "; - } - - static String generatePrompt(AssignmentForm form) { - String prompt = prompt_quizgen_other + _FormatQuestionNumbers(form) + prompt_quizgen_choice_example; - prompt = prompt - .replaceAll('[subject]', form.subject) - .replaceAll('[topic]', form.topic) - .replaceAll('[gradelevel]', form.gradeLevel) - .replaceAll('[maxgrade]', form.maximumGrade.toString()); - - if (form.assignmentCount != null) { - prompt = prompt.replaceAll( - '[numassignments]', form.assignmentCount.toString()); - } - if (form.gradingCriteria != null) { - prompt = prompt.replaceAll('[rubriccriteria]', form.gradingCriteria!); - } - if (form.codingLanguage != null) { - prompt = prompt.replaceAll('[codinglanguage]', form.codingLanguage!); - } - prompt += prompt_quizgen_xmlonly; - return prompt; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/constants/learning_lens.constants.dart b/team_a/teamA/lib/Api/lms/constants/learning_lens.constants.dart deleted file mode 100644 index 82453959..00000000 --- a/team_a/teamA/lib/Api/lms/constants/learning_lens.constants.dart +++ /dev/null @@ -1,4 +0,0 @@ -class LearningLensConstants{ - static const List gradeLevels = ['Kindergarten', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']; - -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/assignee_mode_enum.dart b/team_a/teamA/lib/Api/lms/enum/assignee_mode_enum.dart deleted file mode 100644 index 4cf9e307..00000000 --- a/team_a/teamA/lib/Api/lms/enum/assignee_mode_enum.dart +++ /dev/null @@ -1,6 +0,0 @@ -//Enum for AssigneeMode -enum AssigneeMode { - ASSIGNEE_MODE_UNSPECIFIED, - ALL_STUDENTS, - INDIVIDUAL_STUDENTS -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/course_state_enum.dart b/team_a/teamA/lib/Api/lms/enum/course_state_enum.dart deleted file mode 100644 index d1da73e6..00000000 --- a/team_a/teamA/lib/Api/lms/enum/course_state_enum.dart +++ /dev/null @@ -1,8 +0,0 @@ -//Enum for CourseState -enum CourseState { - COURSE_STATE_UNSPECIFIED, - ACTIVE, - ARCHIVED, - PROVISIONED, - DECLINED -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/course_work_state_enum.dart b/team_a/teamA/lib/Api/lms/enum/course_work_state_enum.dart deleted file mode 100644 index f6413959..00000000 --- a/team_a/teamA/lib/Api/lms/enum/course_work_state_enum.dart +++ /dev/null @@ -1,7 +0,0 @@ -//Enum for CourseWorkState -enum CourseWorkState { - COURSE_WORK_STATE_UNSPECIFIED, - PUBLISHED, - DRAFT, - DELETED -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/course_work_type_enum.dart b/team_a/teamA/lib/Api/lms/enum/course_work_type_enum.dart deleted file mode 100644 index 0e6c8eee..00000000 --- a/team_a/teamA/lib/Api/lms/enum/course_work_type_enum.dart +++ /dev/null @@ -1,7 +0,0 @@ -//Enum for CourseWorkType -enum CourseWorkType { - COURSE_WORK_TYPE_UNSPECIFIED, - ASSIGNMENT, - SHORT_ANSWER_QUESTION, - MULTIPLE_CHOICE_QUESTION -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/lms_enum.dart b/team_a/teamA/lib/Api/lms/enum/lms_enum.dart deleted file mode 100644 index 35de018f..00000000 --- a/team_a/teamA/lib/Api/lms/enum/lms_enum.dart +++ /dev/null @@ -1,4 +0,0 @@ -enum LmsType { - MOODLE, - GOOGLE, -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/enum/preview_version_enum.dart b/team_a/teamA/lib/Api/lms/enum/preview_version_enum.dart deleted file mode 100644 index f09549a1..00000000 --- a/team_a/teamA/lib/Api/lms/enum/preview_version_enum.dart +++ /dev/null @@ -1,5 +0,0 @@ -//Enum for PreviewVersion -enum PreviewVersion { - PREVIEW_VERSION_UNSPECIFIED, - PUBLISHED_VERSION -} diff --git a/team_a/teamA/lib/Api/lms/enum/submission_mod_mode_enum.dart b/team_a/teamA/lib/Api/lms/enum/submission_mod_mode_enum.dart deleted file mode 100644 index aaebce84..00000000 --- a/team_a/teamA/lib/Api/lms/enum/submission_mod_mode_enum.dart +++ /dev/null @@ -1,6 +0,0 @@ -//Enum for SubmissionModificationMode -enum SubmissionModificationMode { - SUBMISSION_MODIFICATION_MODE_UNSPECIFIED, - MODIFIABLE_UNTIL_TURNED_IN, - MODIFIABLE_AFTER_TURNED_IN -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/factory/lms_factory.dart b/team_a/teamA/lib/Api/lms/factory/lms_factory.dart deleted file mode 100644 index 128da031..00000000 --- a/team_a/teamA/lib/Api/lms/factory/lms_factory.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart'; -import 'package:learninglens_app/Api/lms/google_classroom/google_lms_service.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -class LmsFactory { - - static MoodleLmsService _lmsServiceMoodle = MoodleLmsService(); - static GoogleLmsService _lmsServiceGoogle = GoogleLmsService(); - - static LmsInterface getLmsService() { - LmsType lmsType = LocalStorageService.getSelectedClassroom(); - - switch (lmsType) { - // TODO: Do we need this or can we just return Moodle as a default with the default: case? - // case LmsType.MOODLE: - // return getLmsServiceMoodle(); - case LmsType.GOOGLE: - return getLmsServiceGoogle(); - default: - // print('LMS type not found, defaulting to Moodle'); - return getLmsServiceMoodle(); - } - } - - static MoodleLmsService getLmsServiceMoodle() { - return _lmsServiceMoodle; - } - - static GoogleLmsService getLmsServiceGoogle() { - return _lmsServiceGoogle; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/google_classroom/google_classroom_api.dart b/team_a/teamA/lib/Api/lms/google_classroom/google_classroom_api.dart deleted file mode 100644 index a4440515..00000000 --- a/team_a/teamA/lib/Api/lms/google_classroom/google_classroom_api.dart +++ /dev/null @@ -1,747 +0,0 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/beans/lesson_plan.dart'; -import 'package:logging/logging.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -class GoogleClassroomApi { - // final MainController _controller = MainController(); ***** Not used ***** - - Future _getToken() async { - final token = LocalStorageService.getGoogleAccessToken(); - if (token == null) { - print( - 'Error: No valid OAuth token. Ensure the required scopes are enabled. Token null'); - } - return token; - } - - // ----------------------------------------------------------------------- - // Creates a new Google Form - // ----------------------------------------------------------------------- - Future?> createForm(String? teacherFolderId, String title) async { - final token = await _getToken(); - if (token == null) return null; - - final url = Uri.parse('https://forms.googleapis.com/v1/forms'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - final body = jsonEncode({ - 'info': {'title': title, 'documentTitle': title}, - }); - - try { - final response = await http.post(url, headers: headers, body: body); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - print('teacherFolderId: $teacherFolderId'); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - - // Move the folder to where GC expects it to be. - final driveUrl = Uri.https( - 'www.googleapis.com', - '/drive/v3/files/${data['formId']}', - { - 'addParents': teacherFolderId, - 'removeParents': 'root', - }, - ); - final driveHeaders = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - final driveBody = jsonEncode({ - 'addParents': teacherFolderId, // New parent folder - 'removeParents': 'root', - }); - - // Remove from root (optional: fetch current parents if needed) - final driveResponse = await http.patch( - driveUrl, - headers: driveHeaders, - body: driveBody, - ); - print('***********************************************************************************'); - print("Drive Update Status: ${driveResponse.statusCode}"); - print("Drive Update Body: ${driveResponse.body}"); - - - return data; - } else { - print('Form creation failed: ${response.statusCode}'); - return null; - } - } catch (e) { - print('Error creating form: $e'); - return null; - } - } - - // ----------------------------------------------------------------------- - // Batches the update - // ----------------------------------------------------------------------- - Future?> batchUpdateForm( - String formId, List> requests) async { - final token = await _getToken(); - if (token == null) return null; - - final url = - Uri.parse('https://forms.googleapis.com/v1/forms/$formId:batchUpdate'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - final body = jsonEncode({ - 'requests': requests, - }); - - try { - final response = await http.post(url, headers: headers, body: body); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - return data; - } else { - print('Form batch update failed: ${response.statusCode}'); - return null; - } - } catch (e) { - print('Error updating form settings: $e'); - return null; - } - } - - //Future?> createAssignment(String courseid, String sectionid, String assignmentName, String startdate, String enddate, String rubricJson, String description); - // ----------------------------------------------------------------------- -// Creates a Classroom assignment and links the form -// ----------------------------------------------------------------------- - // Future createAssignment(String courseId, String title, - // String description, String responderUri, DateTime dueDate) async { - // //Change the date parameter to DateTime - // // Changed formId to responderUri in the parameters - // final token = await _getToken(); - // if (token == null) return null; - - // final url = Uri.parse( - // 'https://classroom.googleapis.com/v1/courses/$courseId/courseWork'); - // final headers = { - // 'Authorization': 'Bearer $token', - // 'Content-Type': 'application/json', - // }; - // final year = dueDate.year; - // final month = dueDate.month; - // final day = dueDate.day; - // final hours = dueDate.hour; - // final minutes = dueDate.minute; - - // final body = jsonEncode({ - // "title": title, - // "description": description, - // "workType": "ASSIGNMENT", - // "state": "PUBLISHED", - // "dueDate": {"year": year, "month": month, "day": day}, - // "dueTime": {"hours": hours, "minutes": minutes, "seconds": 0}, - // "materials": [ - // { - // "link": {"url": responderUri} - // } // Use the responderUri directly - THIS IS THE FIX! - // ] - // }); - - // try { - // final response = await http.post(url, headers: headers, body: body); - - // print("Response Status: ${response.statusCode}"); - // print("Response Body: ${response.body}"); - - // if (response.statusCode == 200) { - // final data = jsonDecode(response.body); - // final assignmentId = data['id']; - // print('Assignment created successfully with ID: $assignmentId'); - // return assignmentId; - // } else { - // print('Assignment creation failed: ${response.statusCode}'); - // return null; - // } - // } catch (e) { - // print('Error creating assignment: $e'); - // return null; - // } - // } - - Future createAssignment(String courseId, String title, - String description, String responderUri, String dueDate) async { - final log = Logger('GoogleClassroomApi creating Assignments'); - log.info('We are calling createAssignment from Google Classroom.'); - final token = await _getToken(); - if (token == null) return null; - - final url = Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseId/courseWork'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - // Parse the dueDate string to extract year, month, day, hours, and minutes - List dateParts = dueDate.split('-'); - int year = int.parse(dateParts[0]); - int month = int.parse(dateParts[1]); - int day = int.parse(dateParts[2]); - int hours = int.parse(dateParts[3]); - int minutes = int.parse(dateParts[4]); - String? topicId = await getTopicId(courseId, 'Quiz') ?? '755868506953'; - - print('topic id is : $topicId'); - - //String? topicId ='755868506953'; - - - final body = jsonEncode({ - "title": title, - "description": description, - "topicId": topicId, - "workType": "ASSIGNMENT", - "state": "PUBLISHED", - "dueDate": {"year": year, "month": month, "day": day}, - "dueTime": {"hours": hours, "minutes": minutes, "seconds": 0}, - "materials": [ - { - "link": {"url": responderUri} - } // Use the responderUri directly - THIS IS THE FIX! - ] - }); - -print('body for creating assignment is : $body'); - try { - final response = await http.post(url, headers: headers, body: body); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - final assignmentId = data['id']; - print('Assignment created successfully with ID: $assignmentId'); - return assignmentId; - } else { - - print('Assignment creation failed inside createAssignment method : ${response.statusCode}'); - print(response.body); - return null; - } - } catch (e) { - print('Error creating assignment: $e'); - return null; - } - } - - Future getTopicIdByCreating(String courseId, String title) async { - final log = Logger('GoogleClassroomApi creating Topics'); - log.info('Calling createTopic from Google Classroom.'); - - // Obtain the OAuth2 token - final token = await _getToken(); - if (token == null) { - print('Failed to obtain token.'); - return null; - } - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/topics'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - final body = jsonEncode({ - "name": title, - }); - - try { - // Make the POST request to create the topic - final response = await http.post(url, headers: headers, body: body); - - if (response.statusCode == 200) { - // Parse the response and extract the topicId - final data = jsonDecode(response.body); - return data['topicId']; - } else { - print('Failed to create topic. Status code: ${response.statusCode}, Response: ${response.body}'); - } - } catch (e) { - print('Error creating topic: $e'); - } - - return null; -} -Future getTopicId(String courseId, String title) async { - final log = Logger('GoogleClassroomApi getting TopicId'); - log.info('Calling listTopics from Google Classroom.'); - - final token = await _getToken(); - if (token == null) { - print('Failed to obtain token.'); - return null; - } - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/topics'); - final headers = { - 'Authorization': 'Bearer $token', - 'Accept': 'application/json', - }; - - try { - final response = await http.get(url, headers: headers); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - final topics = data['topic'] as List; - - for (var topic in topics) { - if (topic['name'] == title) { - return topic['topicId']; - } - } - - log.warning('Topic with name "$title" not found. So i need to create a new topic'); - return getTopicIdByCreating(courseId, title); - } else { - print('Failed to list topics. Status code: ${response.statusCode}, Response: ${response.body}'); - } - } catch (e) { - print('Error listing topics: $e'); - } - - return null; -} -/* - Future createCourseWorkMaterial(String courseId, String accessToken, String title, ) async { - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials'); - - final headers = { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }; - - final body = jsonEncode({ - "title": "My New Course Material", - "description": "This is a description of the material.", - "materials": [ - { - "link": { - "url": "https://example.com/material" - } - } - ], - "state": "PUBLISHED", - "scheduledTime": "2024-03-15T10:00:00Z", - "topicId": "your_topic_id" - }); - - final response = await http.post(url, headers: headers, body: body); - - if (response.statusCode == 200) { - // Success! The course work material was created. - print('Course work material created successfully!'); - print(response.body); // You might want to parse the response JSON here. - } else { - // Error! Something went wrong. - print('Error creating course work material: ${response.statusCode}'); - print(response.body); - } - } -*/ - // ----------------------------------------------------------------------- - // Course Work Realated Methods - // ----------------------------------------------------------------------- - - - Future createCourseWorkMaterial(String courseId, String title, String description, String materialUrl, - {String? topicId, DateTime? scheduledTime}) async { - print('Creating material: $title'); - - final accessToken = await _getToken(); - if (accessToken == null) return null; - - final googleClassroomApi = GoogleClassroomApi(); - String? topicID = await googleClassroomApi.getTopicId(courseId, "Lesson Plans"); - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials'); - final headers = {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json'}; - final body = jsonEncode({ - "title": title, - "description": description, - "state": "PUBLISHED", - if (scheduledTime != null) "scheduledTime": scheduledTime.toUtc().toIso8601String(), - if (topicID != null) "topicId": topicID, - }); - - try { - final response = await http.post(url, headers: headers, body: body); - if (response.statusCode == 200) { - return jsonDecode(response.body)['id']; - } else { - print('Error creating material: ${response.statusCode}'); - return null; - } - } catch (e) { - print('Error creating material: $e'); - return null; - } - } - -/* -Future updateCourseWorkMaterial(String courseId, String materialId, String? title, String? description, - {String? topicId, DateTime? scheduledTime, String? state}) async { - print('Updating material: $materialId'); - - final accessToken = await _getToken(); - if (accessToken == null) return; - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials/$materialId'); - print('Update URL: $url'); - - final updateMask = _generateUpdateMask(title, description, topicId, scheduledTime, state); - final headers = { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - 'updateMask': updateMask, - }; - print('Update Mask: $updateMask'); - - final Map requestBody = {}; - if (title != null) requestBody["title"] = title; - if (description != null) requestBody["description"] = description; - // if (state != null) requestBody["state"] = state; - // if (scheduledTime != null) requestBody["scheduledTime"] = scheduledTime.toUtc().toIso8601String(); - // if (topicId != null) requestBody["topicId"] = topicId; - - final body = jsonEncode(requestBody); - - print('Request Body:=> $body'); - - try { - print('Inside the try block'); - final response = await http.patch(url, headers: headers, body: body); - print('Response Status Code: ${response.statusCode}'); - print('Response Body: ${response.body}'); - - if (response.statusCode == 200) { - getLessonPlan(courseId); - } else { - print('Error updating material: ${response.statusCode}'); - } - } catch (e) { - print('Error updating material: $e'); - } -} -*/ -Future updateCourseWorkMaterial( - String courseId, - String materialId, - String? title, - String? description, { - String? topicId, - DateTime? scheduledTime, - String? state, - }) async { - print('Updating material: $materialId'); - - final accessToken = await _getToken(); - if (accessToken == null) { - print('No valid access token found.'); - return; - } - - // Generate the updateMask - final updateMask = _generateUpdateMask(title, description, topicId, scheduledTime, state); - final url = Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials/$materialId?updateMask=$updateMask'); - print('Update URL: $url'); - - final headers = { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }; - - final Map requestBody = {}; - if (title != null) requestBody["title"] = title; - if (description != null) requestBody["description"] = description; - // Uncomment and use these if needed - // if (state != null) requestBody["state"] = state; - // if (scheduledTime != null) requestBody["scheduledTime"] = scheduledTime.toUtc().toIso8601String(); - // if (topicId != null) requestBody["topicId"] = topicId; - - final body = jsonEncode(requestBody); - print('Request Body: $body'); - - final client = http.Client(); - try { - final response = await client.patch(url, headers: headers, body: body); - print('Response Status Code: ${response.statusCode}'); - print('Response Body: ${response.body}'); - - if (response.statusCode == 200) { - print('Material updated successfully.'); - // Note: We’ll refresh the UI in the calling code, not here - } else { - print('Error updating material: ${response.statusCode} - ${response.body}'); - } - } catch (e) { - print('Detailed error updating material: $e'); - } finally { - client.close(); - } -} - -// Helper method to generate updateMask (unchanged) -String _generateUpdateMask(String? title, String? description, String? topicId, DateTime? scheduledTime, String? state) { - List fields = []; - if (title != null) fields.add('title'); - if (description != null) fields.add('description'); - if (topicId != null) fields.add('topicId'); - if (scheduledTime != null) fields.add('scheduledTime'); - if (state != null) fields.add('state'); - return fields.join(','); -} - - Future deleteCourseWorkMaterial(String courseId, String materialId) async { - print('Deleting material: $materialId'); - final accessToken = await _getToken(); - if (accessToken == null) return; - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials/$materialId'); - final headers = {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json'}; - - try { - final response = await http.delete(url, headers: headers); - - print(response.statusCode); - print(response.body); - - if (response.statusCode == 200 || response.statusCode == 204) { - getLessonPlan(courseId); - } else { - print('Error deleting material: ${response.statusCode}'); - } - } catch (e) { - print('Error deleting material: $e'); - } - } - - - -Future getLessonPlan(String courseId) async { - LessonPlan lessonPlan = LessonPlan.empty(); - try { - final accessToken = await _getToken(); - if (accessToken == null) return; - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials'); - final headers = {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json'}; - final response = await http.get(url, headers: headers); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - - if (data.containsKey('courseWorkMaterial')) { - List lessonPlans = (data['courseWorkMaterial'] as List) - .map((item) => lessonPlan.fromGoogleJson(item as Map)) - .toList(); - - print('Lesson Plans: $lessonPlans'); - } else { - print('No coursework materials found.'); - } - } else { - print('Error loading coursework materials: ${response.statusCode}'); - } - } catch (e) { - print('Error loading coursework materials: $e'); - } -} - - -// ----------------------------------------------------------------------- -// retrive the quiz questions -// ----------------------------------------------------------------------- - Future?> getQuizQuestions(String courseId, String quizId) async { - final token = await _getToken(); - if (token == null) return null; - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWork/$quizId'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - try { - final response = await http.get(url, headers: headers); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - return data; - } else { - print('Quiz questions retrieval failed: ${response.statusCode}'); - return null; - } - } catch (e) { - print('Error retrieving quiz questions: $e'); - return null; - } - } - - // ----------------------------------------------------------------------- - // Updates the course work - // ----------------------------------------------------------------------- - Future?> updateCourseWork(String courseId, String courseWorkId, String title, String description, - String? dueDate, String? dueTime, String? rubricJson, String? state) async { - final token = await _getToken(); - if (token == null) return null; - - final url = Uri.parse('https://classroom.googleapis.com/v1/courses/$courseId/courseWork/$courseWorkId'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - final body = jsonEncode({ - 'title': title, - 'description': description, - 'dueDate': dueDate, - 'dueTime': dueTime, - 'rubric': rubricJson, - 'state': state, - }); - - try { - final response = await http.put(url, headers: headers, body: body); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - return data; - } else { - print('Course work update failed: ${response.statusCode}'); - return null; - } - } catch (e) { - print('Error updating course work: $e'); - return null; - } - } - - // ----------------------------------------------------------------------- - - // Method to retrieve Google Form questions from an assignment - // ----------------------------------------------------------------------- - - -Future> getAssignmentFormQuestions(String? courseId, String? courseWorkId) async { - // "courseId": "750797786103", - //"id": "757589683856", - try { - // Step 1: Retrieve the stored access token - final token = await _getToken(); - print('Token: $token'); // Debug output - - if (token == null) { - throw Exception('No access token found. Please log in again.'); - } - - // Step 2: Fetch assignment details from Google Classroom API - final courseworkUrl = - 'https://classroom.googleapis.com/v1/courses/$courseId/courseWork/$courseWorkId'; - final courseworkResponse = await http.get( - Uri.parse(courseworkUrl), - headers: { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }, - ); - - print('Coursework URL: $courseworkUrl'); // Debug output - print('Coursework Response: ${courseworkResponse.body}'); // Debug output - - if (courseworkResponse.statusCode != 200) { - throw Exception( - 'Failed to fetch coursework: ${courseworkResponse.statusCode} - ${courseworkResponse.body}'); - } - - final courseworkData = jsonDecode(courseworkResponse.body); - print('Coursework Data: $courseworkData'); // Debug output - - // Step 3: Extract Form URL from materials - String? formUrl; - if (courseworkData['materials'] != null && courseworkData['materials'].isNotEmpty) { - for (var material in courseworkData['materials']) { - if (material['link'] != null && material['link']['url'] != null) { - final url = material['link']['url']; - if (url.contains('docs.google.com/forms')) { - formUrl = url; - break; - } - } - } - } - - if (formUrl == null) { - throw Exception('No Google Form found in assignment materials.'); - } - print('Form URL: $formUrl'); // Debug output - - // Step 4: Extract Form ID from the URL - final formId = formUrl.split('/d/e/')[1].split('/')[0]; - print('Form ID: $formId'); // Debug output - - // Step 5: Fetch form details from Google Forms API - final formsUrl = 'https://forms.googleapis.com/v1/forms/$formId'; - final formsResponse = await http.get( - Uri.parse(formsUrl), - headers: { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }, - ); - - if (formsResponse.statusCode != 200) { - throw Exception( - 'Failed to fetch form: ${formsResponse.statusCode} - ${formsResponse.body}'); - } - - final formData = jsonDecode(formsResponse.body); - print('Form Data: $formData'); // Debug output - - // Step 6: Extract questions from the form - List questions = []; - if (formData['items'] != null) { - for (var item in formData['items']) { - if (item['questionItem'] != null && item['questionItem']['question'] != null) { - questions.add(item['questionItem']['question']['text']); - } - } - } - - return questions; - } catch (e) { - print('Error retrieving form questions: $e'); - return []; - } -} - - - -} diff --git a/team_a/teamA/lib/Api/lms/google_classroom/google_lms_service.dart b/team_a/teamA/lib/Api/lms/google_classroom/google_lms_service.dart deleted file mode 100644 index 2c74b7b1..00000000 --- a/team_a/teamA/lib/Api/lms/google_classroom/google_lms_service.dart +++ /dev/null @@ -1,1098 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/beans/g_question_form_data.dart'; -import 'package:logger/logger.dart'; -import 'package:learninglens_app/beans/quiz_type.dart'; -import 'package:xml/xml.dart' as xml; -import 'package:google_sign_in/google_sign_in.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/submission_status.dart'; -import 'package:learninglens_app/beans/grade.dart'; -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; -import 'package:learninglens_app/beans/moodle_rubric.dart'; -import 'package:learninglens_app/services/api_service.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:learninglens_app/Api/lms/google_classroom/google_classroom_api.dart'; // Import the updated API - -/// A Singleton class for Moodle API access implementing [LmsInterface]. -class GoogleLmsService extends LmsInterface { - // Needed?? - final GoogleClassroomApi _classroomApi = GoogleClassroomApi(); - - // **************************************************************************************** - // Static / Singleton internals - // **************************************************************************************** - - static final GoogleLmsService _instance = GoogleLmsService._internal(); - - /// The singleton accessor. - factory GoogleLmsService() => _instance; - - /// Private named constructor. - GoogleLmsService._internal(); - - // **************************************************************************************** - // Fields implementing LmsInterface - // **************************************************************************************** - - @override - String serverUrl = ''; // The Google REST endpoint - - // The user token is kept private (not in the interface). - String? _userToken; - - @override - String apiURL = - 'https://classroom.googleapis.com/v1'; // Base URL for your Google Classroom - @override - String? userName; - @override - String? firstName; - @override - String? lastName; - @override - String? siteName = 'Google Classroom'; - @override - String? fullName; - @override - String? profileImage; - @override - List? courses; - - late GoogleSignIn _googleSignIn; - - // **************************************************************************************** - // Auth / Login - // **************************************************************************************** - - @override - Future login(String username, String password, String baseURL) { - // TODO: implement google api code - throw UnimplementedError(); - } - - Future loginOath(String clientID) async { - print('Logging in to Google Classroom...'); - - _googleSignIn = GoogleSignIn( - clientId: clientID, - scopes: [ - 'email', - 'profile', - 'https://www.googleapis.com/auth/classroom.courses', - 'https://www.googleapis.com/auth/classroom.topics', - 'https://www.googleapis.com/auth/classroom.rosters', - 'https://www.googleapis.com/auth/classroom.coursework.students', - 'https://www.googleapis.com/auth/classroom.coursework.me', - 'https://www.googleapis.com/auth/classroom.courses.readonly', - 'https://www.googleapis.com/auth/forms.body', - 'https://www.googleapis.com/auth/forms.responses.readonly', - 'https://www.googleapis.com/auth/classroom.courseworkmaterials.readonly', - 'https://www.googleapis.com/auth/classroom.courseworkmaterials', - 'https://www.googleapis.com/auth/forms.body.readonly', - 'https://www.googleapis.com/auth/drive.file', - ], - ); - - try { - final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); - if (googleUser == null) { - throw Exception("Google Sign-In was cancelled by the user."); - } - - // Get the user's name - userName = googleUser.email.split("@").first; - fullName = googleUser.displayName ?? "Unknown User"; - - List nameParts = fullName!.split(" "); - - firstName = nameParts.isNotEmpty ? nameParts.first : ""; - lastName = nameParts.length > 1 ? nameParts.sublist(1).join(" ") : ""; - - print('Welcome, ${firstName ?? 'User'}'); - - final GoogleSignInAuthentication googleAuth = - await googleUser.authentication; - _userToken = googleAuth.accessToken; - - if (_userToken == null) { - throw Exception("Failed to obtain access token."); - } - - LocalStorageService.saveGoogleAccessToken(_userToken!); - } catch (error) { - print("Google Sign-In Error: $error"); - throw Exception("Google Sign-In failed: $error"); - } - - courses = await getUserCourses(); - - // for (Course course in courses!) { - // print('teacherFolderId: ${course.teacherFolderId}'); - // } - } - - @override - bool isLoggedIn() { - return _userToken != null; - } - - String getGoogleAccessToken() { - return _userToken!; - } - - @override - Future isUserTeacher(List moodleCourses) async { - // TODO: implement google api code - throw UnimplementedError(); - } - - @override - void logout() { - print('Logging out of Google...'); - _googleSignIn.signOut(); - resetLMSUserInfo(); - } - - @override - void resetLMSUserInfo() { - // Clear all user-related fields - _userToken = null; - apiURL = ''; - userName = null; - firstName = null; - lastName = null; - siteName = null; - fullName = null; - profileImage = null; - courses = []; - } - - // **************************************************************************************** - // Course-related methods - // **************************************************************************************** - - @override - Future> getCourses() async { - // TODO: implement google api code - // Never called?? - throw UnimplementedError(); - } - - @override - Future> getUserCourses() async { - if (_userToken == null) throw StateError('User not logged in to Google'); - - final response = await ApiService().httpGet( - Uri.parse('https://classroom.googleapis.com/v1/courses'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - // TODO: remove after testing. - // print('Google: ${response.body}'); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final decodedJson = jsonDecode(response.body); - List courses; - - // The response can be either a List or a Map with a 'courses' key - if (decodedJson is List) { - courses = - decodedJson.map((i) => Course.empty().fromGoogleJson(i)).toList(); - } else if (decodedJson is Map) { - final courseList = decodedJson['courses'] as List; - courses = - courseList.map((i) => Course.empty().fromGoogleJson(i)).toList(); - } else { - throw StateError('Unexpected response format from Moodle'); - } - - // Optionally fetch quizzes/essays for each course - for (Course course in courses) { - // set topic ids - final responseTopics = await ApiService().httpGet( - Uri.parse( - 'https://classroom.googleapis.com/v1/courses/${course.id}/topics/'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - var decodedResponseTopics = jsonDecode(responseTopics.body); - - if (decodedResponseTopics.containsKey('topic')) { - List topics = decodedResponseTopics["topic"]; - - // Iterate and capture topicIds - for (var topic in topics) { - if (topic['name'] == 'Quiz') { - course.quizTopicId = int.parse(topic['topicId']); - // print('Id for quiz'); - // print(topic['topicId']); - } else if (topic['name'] == 'Essay') { - course.essayTopicId = int.parse(topic['topicId']); - // print('Id for essay'); - // print(topic['topicId']); - } - } - } - - course.quizzes = await getQuizzes(course.id, topicId: course.quizTopicId); - // print('Quizzes for course ${course.id}: ${course.quizzes}'); - course.essays = await getEssays(course.id, topicId: course.essayTopicId); - // print('Essays for course ${course.id}: ${course.essays}'); - } - - return courses; - } - - @override - Future> getCourseParticipants(String courseId) async { - if (_userToken == null) { - throw StateError('User not logged in to Google Classroom'); - } - - final List participants = []; - - // Fetch students - final studentsResponse = await ApiService().httpGet( - Uri.parse(apiURL + '/courses/$courseId/students'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - if (studentsResponse.statusCode == 200) { - final studentsJson = jsonDecode(studentsResponse.body); - if (studentsJson.containsKey('students')) { - for (var student in studentsJson['students']) { - participants.add(Participant( - id: student['userId'] - .hashCode, // Google Classroom does not provide numeric IDs - fullname: student['profile']['name']['fullName'], - firstname: student['profile']['name']['givenName'], - lastname: student['profile']['name']['familyName'], - roles: ['student'], - )); - } - } - } else { - throw HttpException('Failed to fetch students: ${studentsResponse.body}'); - } - - // Fetch teachers - final teachersResponse = await ApiService().httpGet( - Uri.parse(apiURL + '/courses/$courseId/teachers'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - if (teachersResponse.statusCode == 200) { - final teachersJson = jsonDecode(teachersResponse.body); - if (teachersJson.containsKey('teachers')) { - for (var teacher in teachersJson['teachers']) { - participants.add(Participant( - id: teacher['userId'].hashCode, - fullname: teacher['profile']['name']['fullName'], - firstname: teacher['profile']['name']['givenName'], - lastname: teacher['profile']['name']['familyName'], - roles: ['teacher'], - )); - } - } - } else { - throw HttpException('Failed to fetch teachers: ${teachersResponse.body}'); - } - - return participants; - } - - // **************************************************************************************** - // Quiz methods - // **************************************************************************************** - - @override - Future importQuiz(String courseid, String quizXml) async { - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future> getQuizzes(int? courseID, {int? topicId}) async { - if (_userToken == null) - throw StateError('User not logged in to Google Classroom'); - - final response = await ApiService().httpGet( - Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseID/courseWork'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - // print('quizlist: ${response.body}'); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - // print('Getting quizzes from Google Classroom...'); - // print(response.body); - - final quizzesMap = jsonDecode(response.body) as Map; - final decodedJson = quizzesMap['courseWork'] as List?; - - if (decodedJson == null) { - return []; - } - - List quizList = []; - for (var item in decodedJson) { - // print('Item: $item'); - // If courseID is null, return all quizzes; otherwise filter by course - if (courseID == null || int.parse(item['courseId']) == courseID) { - if (topicId != null && item.containsKey('topicId')) { - if (int.parse(item['topicId']) == topicId) { - quizList.add(Quiz.fromGoogleJson(item)); - } - } - } - } - - // print('I am getting this quiz list: $quizList'); - - return quizList; - } - - @override - Future createQuiz(String courseid, String quizname, String quizintro, - String sectionid, String timeopen, String timeclose) async { - print('Creating quiz in Google Classroom...'); - print('Course ID: $courseid'); - print('Quiz Name: $quizname'); - print('Quiz Intro: $quizintro'); - print('Section ID: $sectionid'); - print('Time Open: $timeopen'); - print('Time Close: $timeclose'); - - try { - // Convert timeopen to ISO 8601 format - String formattedTimeOpen = DateTime.parse(timeopen).toIso8601String(); - - String? assignmentId = await createAssignmentHelper( - courseid, quizname, quizintro, sectionid, formattedTimeOpen); - - if (assignmentId != null) { - return int.parse(assignmentId); - } else { - print('Failed to create quiz'); - return null; - } - } catch (e) { - print('Error creating quiz: $e'); - return null; - } - } - - Future createAssignmentHelper(String courseId, String title, - String description, String responderUri, String dueDate) async { - print('Creating assignment in Google Classroom... Inside helper'); - print('Course ID: $courseId'); - print('Title: $title'); - print('Description: $description'); - print('Responder URI: $responderUri'); - print('Due Date: $dueDate'); - - final token = _userToken; - if (token == null) { - print('User token is null'); - return null; - } - - final url = Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseId/courseWork'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - // Parse the dueDate string - DateTime parsedDate = DateTime.parse(dueDate); - - final body = jsonEncode({ - "title": title, - "description": description, - "workType": "ASSIGNMENT", - "state": "PUBLISHED", - "dueDate": { - "year": parsedDate.year, - "month": parsedDate.month, - "day": parsedDate.day - }, - "dueTime": { - "hours": parsedDate.hour, - "minutes": parsedDate.minute, - "seconds": 0 - }, - "materials": [ - { - "link": {"url": responderUri} - } - ] - }); - - // Print request details - print('Request URL: $url'); - print('Request Headers: $headers'); - print('Request Body: $body'); - - try { - final response = await http.post(url, headers: headers, body: body); - - print("Response Status: ${response.statusCode}"); - print("Response Body: ${response.body}"); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - final assignmentId = data['id']; - print('Assignment created successfully with ID: $assignmentId'); - return assignmentId; - } else { - print('Assignment creation failed: ${response.statusCode}'); - print('Error message: ${response.body}'); - return null; - } - } catch (e) { - print('Error creating assignment: $e'); - return null; - } - } - - @override - Future addRandomQuestions( - String categoryid, String quizid, String numquestions) async { - print('Adding random questions to quiz...'); - print('Category ID: $categoryid'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future importQuizQuestions(String courseid, String quizXml) async { - print('Importing quiz questions...'); - print('Course ID: $courseid'); - print('Quiz XML: $quizXml'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future> getQuestionsFromQuiz(int quizId) async { - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - Future getAssignmentFormQuestions( - String coursedId, String courseWorkId) async { - print( - 'Fetching form questions for course $coursedId, coursework $courseWorkId...'); - try { - final accessToken = await _getToken(); - if (accessToken == null) { - throw Exception('No access token found. Please log in again.'); - } - - final courseworkUrl = - 'https://classroom.googleapis.com/v1/courses/$coursedId/courseWork/$courseWorkId'; - final courseworkResponse = await http.get( - Uri.parse(courseworkUrl), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }, - ); - - if (courseworkResponse.statusCode != 200) { - throw Exception( - 'Failed to fetch coursework: ${courseworkResponse.statusCode} - ${courseworkResponse.body}'); - } - - final courseworkData = jsonDecode(courseworkResponse.body); - print('Coursework data: $courseworkData'); - - String? formUrl; - if (courseworkData['materials'] != null && - courseworkData['materials'].isNotEmpty) { - for (var material in courseworkData['materials']) { - if (material['link'] != null && material['link']['url'] != null) { - final url = material['link']['url']; - if (url.contains('docs.google.com/forms')) { - formUrl = url; - break; - } - } - if (material['form'] != null && material['form']['formUrl'] != null) { - final url = material['form']['formUrl']; - if (url.contains('docs.google.com/forms')) { - formUrl = url; - break; - } - } - } - } - - if (formUrl == null) { - throw Exception('No Google Form found in assignment materials.'); - } - print('Extracted Form URL: $formUrl'); - - // Extract and format dates to YYYY-MM-DD - String? startDate; - if (courseworkData['creationTime'] != null) { - final dateTime = DateTime.parse(courseworkData['creationTime']); - startDate = - '${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')}'; - } - - String? endDate; - if (courseworkData['dueDate'] != null) { - final dueDate = courseworkData['dueDate']; - endDate = - '${dueDate['year']}-${dueDate['month'].toString().padLeft(2, '0')}-${dueDate['day'].toString().padLeft(2, '0')}'; - } - - String? status = courseworkData['state']; - - final formId = await getFormIdFromViewformUrl(formUrl, accessToken); - if (formId == null) { - throw Exception('Failed to retrieve Form ID from viewform URL'); - } - print('Form ID: $formId'); - - final formsUrl = 'https://forms.googleapis.com/v1/forms/$formId'; - final formsResponse = await http.get( - Uri.parse(formsUrl), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }, - ); - - if (formsResponse.statusCode != 200) { - throw Exception( - 'Failed to fetch form: ${formsResponse.statusCode} - ${formsResponse.body}'); - } - - final formData = jsonDecode(formsResponse.body); - print('Form data: $formData'); - - String title = formData['info']?['title'] ?? 'Untitled Form'; - List questions = []; - if (formData['items'] != null) { - for (var item in formData['items']) { - if (item['questionItem'] != null && - item['questionItem']['question'] != null) { - String questionText = item['title'] ?? 'Unnamed Question'; - List options = []; - if (item['questionItem']['question']['choiceQuestion'] != null) { - var choiceQuestion = - item['questionItem']['question']['choiceQuestion']; - if (choiceQuestion['options'] != null) { - for (var option in choiceQuestion['options']) { - options.add(option['value'] ?? 'No Option'); - } - } - } - questions - .add(QuestionData(question: questionText, options: options)); - } - } - } - - return FormData( - title: title, - questions: questions, - startDate: startDate, - endDate: endDate, - formUrl: formUrl, - status: status, - ); - } catch (e) { - print('Error retrieving form questions: $e'); - return FormData(title: 'Error', questions: []); - } - } - - Future getFormIdFromViewformUrl( - String viewformUrl, String accessToken) async { - try { - final publicKey = viewformUrl.split('/d/e/')[1].split('/')[0]; - print('Public key: $publicKey'); - - final driveUrl = 'https://www.googleapis.com/drive/v3/files' - '?q=mimeType="application/vnd.google-apps.form"' - '&fields=files(id,name)' - '&spaces=drive'; - final driveResponse = await http.get( - Uri.parse(driveUrl), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }, - ); - - if (driveResponse.statusCode != 200) { - throw Exception('Failed to fetch Drive files: ${driveResponse.body}'); - } - - final driveData = jsonDecode(driveResponse.body); - print('Drive data: $driveData'); - - for (var file in driveData['files']) { - final fileId = file['id']; - print('Checking file ID: $fileId'); - - final formsUrl = 'https://forms.googleapis.com/v1/forms/$fileId'; - final formResponse = await http.get( - Uri.parse(formsUrl), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json', - }, - ); - - if (formResponse.statusCode == 200) { - final formData = jsonDecode(formResponse.body); - final responderUri = formData['responderUri']; - print('Responder URI for $fileId: $responderUri'); - - if (responderUri != null && responderUri.contains(publicKey)) { - print('Matched form ID: $fileId'); - return fileId; - } - } else { - print('Failed to fetch form $fileId: ${formResponse.statusCode}'); - } - } - - throw Exception( - 'No matching form found in Drive for the provided viewform URL'); - } catch (e) { - print('Error fetching Form ID from Drive: $e'); - return null; - } - } - - Future _getToken() async { - final token = LocalStorageService.getGoogleAccessToken(); - if (token == null) { - print( - 'Error: No valid OAuth token. Ensure the required scopes are enabled. Token null'); - } - return token; - } - - // **************************************************************************************** - // Assignment methods - // **************************************************************************************** - - @override - Future> getEssays(int? courseID, {int? topicId}) async { - if (_userToken == null) - throw StateError('User not logged in to Google Classroom'); - - final response = await ApiService().httpGet( - Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseID/courseWork'), - headers: {'Authorization': 'Bearer $_userToken'}, - ); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final essaysMap = jsonDecode(response.body) as Map; - final decodedJson = essaysMap['courseWork'] as List?; - - if (decodedJson == null) { - return []; - } - - List essayList = []; - for (var item in decodedJson) { - // If courseID is null, return all quizzes; otherwise filter by course - if (courseID == null || int.parse(item['courseId']) == courseID) { - if (topicId != null && item.containsKey('topicId')) { - if (int.parse(item['topicId']) == topicId) { - essayList.add(Assignment.empty().fromGoogleJson(item)); - } - } - } - } - - return essayList; - } - - @override - Future?> createAssignment( - String courseid, - String sectionid, - String assignmentName, - String startdate, - String enddate, - String rubricJson, - String description, - ) async { - print('Creating assignment...'); - print('Course ID: $courseid'); - print('Section ID: $sectionid'); - print('Assignment Name: $assignmentName'); - print('Start Date: $startdate'); - print('End Date: $enddate'); - // TODO: implement google api code - throw UnimplementedError(); - } - - @override - Future getContextId(int assignmentId, String courseId) async { - print('Getting context ID...'); - print('Assignment ID: $assignmentId'); - print('Course ID: $courseId'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - // **************************************************************************************** - // Submissions and grading - // **************************************************************************************** - - @override - Future> getAssignmentSubmissions(int assignmentId) async { - print('Getting assignment submissions...'); - print('Assignment ID: $assignmentId'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future> getSubmissionsWithGrades( - int assignmentId) async { - print('Getting submissions with grades...'); - print('Assignment ID: $assignmentId'); - - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future getSubmissionStatus( - int assignmentId, int userId) async { - print('Getting submission status...'); - print('Assignment ID: $assignmentId'); - print('User ID: $userId'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future> getAssignmentGrades(int assignmentId) async { - print('Getting assignment grades...'); - print('Assignment ID: $assignmentId'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future setRubricGrades( - int assignmentId, int userId, String jsonGrades) async { - print('Setting rubric grades...'); - print('Assignment ID: $assignmentId'); - print('User ID: $userId'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Future> getRubricGrades(int assignmentId, int userid) async { - print('Getting rubric grades...'); - print('Assignment ID: $assignmentId'); - print('User ID: $userid'); - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - @override - Grade? findGradeForUser(List grades, int userId) { - print('Finding grade for user...'); - print('User ID: $userId'); - - // TODO: implement google api code - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - - // **************************************************************************************** - // Rubric retrieval - // **************************************************************************************** - - @override - Future getRubric(String assignmentid) async { - // TODO: implement google api code - print('Getting rubric...'); - print('Assignment ID: $assignmentid'); - throw UnimplementedError( - 'This feature is not supported by Google Classroom. Please contact the developer.'); - } - // **************************************************************************************** - // Quiz creation and assignment with Answer Key - //Short answer question 10 Points - //Multiple choice question 10 Points - //True/False question 5 Points - - // **************************************************************************************** - - Future createAndAssignQuizFromXml( - String courseId, - String quizName, - String quizDescription, - String quizAsXml, - String dueDate, - ) async { - try { - if (quizAsXml.isEmpty) { - print('Error: quizAsXml is empty.'); - return false; - } - - final document = xml.XmlDocument.parse(quizAsXml); - final questions = document.findAllElements('question').toList(); - String? teacherFolderId; - - for (Course course in courses!) { - if (course.id == int.parse(courseId)) { - teacherFolderId = course.teacherFolderId; - } - } - - Map? formResponse = - await _classroomApi.createForm(teacherFolderId, quizName); - if (formResponse == null) { - print('Error: Failed to create Google Form.'); - return false; - } - - final String formId = formResponse['formId']; - final String responderUri = formResponse['responderUri']; - - List> requests = []; - requests.add({ - 'updateSettings': { - 'settings': { - 'emailCollectionType': 'DO_NOT_COLLECT', - 'quizSettings': {'isQuiz': true} - }, - 'updateMask': 'email_collection_type,quiz_settings', - } - }); - - // Parse and add questions with answer keys and points - for (var questionElement in questions) { - String questionType = questionElement.getAttribute('type') ?? 'unknown'; - String questionText = questionElement - .getElement('questiontext') - ?.getElement('text') - ?.text ?? - ''; - - if (questionType == 'category') { - print( - 'Warning: Unsupported question type: $questionType. Skipping question.'); - continue; - } - switch (questionType) { - case 'multichoice': - int points = 10; // Set multichoice to 10 points - List options = []; - List correctAnswerIndices = []; - var answerElements = - questionElement.findAllElements('answer').toList(); - for (int i = 0; i < answerElements.length; i++) { - var answerElement = answerElements[i]; - String optionText = answerElement.getElement('text')?.text ?? ''; - options.add(optionText); - if (answerElement.getAttribute('fraction') == '100') { - correctAnswerIndices.add(i); - } - } - requests.add(_createMultipleChoiceQuestionRequest( - questionText, options, correctAnswerIndices, points)); - break; - case 'truefalse': - int points = 5; // Set truefalse to 5 points - String correctAnswer = questionElement - .findAllElements('answer') - .firstWhere((e) => e.getAttribute('fraction') == '100') - .getElement('text') - ?.text ?? - 'True'; - requests.add(_createTrueFalseQuestionRequest( - questionText, correctAnswer, points)); - break; - case 'shortanswer': - int points = 10; // Set shortanswer to 10 point - String correctAnswer = questionElement - .findAllElements('answer') - .first - .getElement('text') - ?.text ?? - ''; - requests.add(_createShortAnswerQuestionRequest( - questionText, correctAnswer, points)); - break; - default: - print('Warning: Unsupported question type: $questionType'); - } - } - - Map? batchResponse = - await _classroomApi.batchUpdateForm(formId, requests); - if (batchResponse == null) { - print('Error: Failed to update Google Form.'); - return false; - } - - String? assignmentId = await _classroomApi.createAssignment( - courseId, - quizName, - quizDescription, - responderUri, - dueDate, - ); - - if (assignmentId == null) { - print('Error: Failed to create Classroom assignment.'); - return false; - } - - print( - 'Quiz created and assigned successfully! Assignment ID: $assignmentId'); - return true; - } catch (e) { - print('Error during quiz creation and assignment: $e'); - return false; - } - } - - Map _createMultipleChoiceQuestionRequest(String questionText, - List options, List correctAnswerIndices, int points) { - List> choices = []; - for (String option in options) { - choices.add({'value': option}); - } - - return { - 'createItem': { - 'item': { - 'title': questionText, - 'questionItem': { - 'question': { - 'required': true, - 'choiceQuestion': { - 'type': 'RADIO', - 'options': choices, - }, - 'grading': { - 'pointValue': points, - 'correctAnswers': { - 'answers': correctAnswerIndices - .map((index) => {'value': options[index]}) - .toList(), - }, - }, - }, - }, - }, - 'location': {'index': 0}, - }, - }; - } - - Map _createTrueFalseQuestionRequest( - String questionText, String correctAnswer, int points) { - List options = ["True", "False"]; - return { - 'createItem': { - 'item': { - 'title': questionText, - 'questionItem': { - 'question': { - 'required': true, - 'choiceQuestion': { - 'type': 'RADIO', - 'options': [ - {'value': 'True'}, - {'value': 'False'}, - ], - }, - 'grading': { - 'pointValue': points, - 'correctAnswers': { - 'answers': [ - {'value': correctAnswer}, - ], - }, - }, - }, - }, - }, - 'location': {'index': 0}, - }, - }; - } - - Map _createShortAnswerQuestionRequest( - String questionText, String correctAnswer, int points) { - return { - 'createItem': { - 'item': { - 'title': questionText, - 'questionItem': { - 'question': { - 'required': true, - 'textQuestion': {}, - 'grading': { - 'pointValue': points, - 'correctAnswers': { - 'answers': [ - {'value': correctAnswer}, - ], - }, - }, - }, - }, - }, - 'location': {'index': 0}, - }, - }; - } - - @override - Future> getQuizGradesForParticipants( - String courseId, int quizId) { - // TODO: implement getQuizGradesForParticipants - throw UnimplementedError(); - } -} diff --git a/team_a/teamA/lib/Api/lms/lms_interface.dart b/team_a/teamA/lib/Api/lms/lms_interface.dart deleted file mode 100644 index 28a932c6..00000000 --- a/team_a/teamA/lib/Api/lms/lms_interface.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/quiz_type.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/submission_status.dart'; -import 'package:learninglens_app/beans/grade.dart'; -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; -import 'package:learninglens_app/beans/moodle_rubric.dart'; - -// Singleton interface class for API access. -abstract class LmsInterface { - late String serverUrl; - - // User info - late String apiURL; - String? userName; - String? firstName; - String? lastName; - String? siteName; - String? fullName; - String? profileImage; - List? courses; - - // Authentication/Login methods - Future login(String username, String password, String baseURL); - bool isLoggedIn(); - Future isUserTeacher(List moodleCourses); - void logout(); - void resetLMSUserInfo(); - - // Course methods - Future> getCourses(); - Future> getUserCourses(); - Future> getCourseParticipants(String courseId); - - // Quiz methods - Future importQuiz(String courseid, String quizXml); - Future> getQuizzes(int? courseID, {int? topicId}); - Future createQuiz(String courseid, String quizname, String quizintro, - String sectionid, String timeopen, String timeclose); - Future addRandomQuestions( - String categoryid, String quizid, String numquestions); - Future importQuizQuestions(String courseid, String quizXml); - Future> getQuestionsFromQuiz(int quizId); - - // Assignment methods - Future> getEssays(int? courseID, {int? topicId}); - Future?> createAssignment(String courseid, String sectionid, String assignmentName, - String startdate, String enddate, String rubricJson, String description); - Future getContextId(int assignmentId, String courseId); - - // Submission and grading methods - Future> getAssignmentSubmissions(int assignmentId); - Future> getSubmissionsWithGrades(int assignmentId); - Future getSubmissionStatus(int assignmentId, int userId); - Future> getAssignmentGrades(int assignmentId); - Future setRubricGrades(int assignmentId, int userId, String jsonGrades); - Future> getRubricGrades(int assignmentId, int userid); - Grade? findGradeForUser(List grades, int userId); - - // Rubric methods - Future getRubric(String assignmentid); - Future> getQuizGradesForParticipants(String courseId, int quizId); -} diff --git a/team_a/teamA/lib/Api/lms/moodle/classroom_service.dart b/team_a/teamA/lib/Api/lms/moodle/classroom_service.dart deleted file mode 100644 index b9f78bb0..00000000 --- a/team_a/teamA/lib/Api/lms/moodle/classroom_service.dart +++ /dev/null @@ -1 +0,0 @@ -// TODO Implement this library. \ No newline at end of file diff --git a/team_a/teamA/lib/Api/lms/moodle/moodle_lms_service.dart b/team_a/teamA/lib/Api/lms/moodle/moodle_lms_service.dart deleted file mode 100644 index 2f04ecbb..00000000 --- a/team_a/teamA/lib/Api/lms/moodle/moodle_lms_service.dart +++ /dev/null @@ -1,1298 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/lesson_plan.dart'; -import 'package:learninglens_app/beans/question_stat_type.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/override.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/quiz_override'; -import 'package:learninglens_app/beans/quiz_type.dart'; -import 'package:learninglens_app/beans/submission_status.dart'; -import 'package:learninglens_app/beans/grade.dart'; -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; -import 'package:learninglens_app/beans/moodle_rubric.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -/// A Singleton class for Moodle API access implementing [LmsInterface]. -class MoodleLmsService implements LmsInterface { - // **************************************************************************************** - // Static / Singleton internals - // **************************************************************************************** - - static final MoodleLmsService _instance = MoodleLmsService._internal(); - - /// The singleton accessor. - factory MoodleLmsService() => _instance; - - /// Private named constructor. - MoodleLmsService._internal(); - - // **************************************************************************************** - // Fields implementing ApiSingletonInterface - // **************************************************************************************** - - @override - String serverUrl = '/webservice/rest/server.php'; // The Moodle REST endpoint - - // The user token is kept private (not in the interface). - String? _userToken; - - @override - String apiURL = - ''; // Base URL for your Moodle instance, e.g. "https://yourmoodle.com" - @override - String? userName; - @override - String? firstName; - @override - String? lastName; - @override - String? siteName; - @override - String? fullName; - @override - String? profileImage; - @override - List? courses; - - List? overrides; - - // **************************************************************************************** - // Auth / Login - // **************************************************************************************** - - @override - Future login(String username, String password, String baseURL) async { - print('Logging in to Moodle...'); - - // 1) Obtain the token by calling Moodle's login/token.php - final response = await ApiService().httpGet(Uri.parse( - '$baseURL/login/token.php?username=$username&password=$password&service=moodle_mobile_app')); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final data = jsonDecode(response.body) as Map; - if (data.containsKey('error')) { - throw HttpException(data['error']); - } - - // Store token locally - _userToken = data['token']; - apiURL = baseURL; - - // 2) Retrieve user info - final userinforesponse = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': 'core_webservice_get_site_info', - 'moodlewsrestformat': 'json', - }); - - if (userinforesponse.statusCode != 200) { - throw HttpException(userinforesponse.body); - } - - // 3) Parse user info - final userData = jsonDecode(userinforesponse.body) as Map; - userName = userData['username']; - firstName = userData['firstname']; - lastName = userData['lastname']; - siteName = userData['sitename']; - fullName = userData['fullname']; - profileImage = userData['userpictureurl']; - - // 4) Optionally load user courses right away - courses = await getUserCourses(); - overrides = await getAssignmentOverrides(); - } - - @override - bool isLoggedIn() { - return _userToken != null; - } - - @override - Future isUserTeacher(List moodleCourses) async { - // Check each course to see if the user has a teacher role - for (var course in moodleCourses) { - final rolesResponse = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': 'core_enrol_get_enrolled_users', - 'courseid': course.id.toString(), - 'moodlewsrestformat': 'json', - }); - - if (rolesResponse.statusCode != 200) { - throw Exception('Failed to load roles for course ${course.id}'); - } - - // If the user has roleid == 3 or 4, they are teacher-like roles - final users = jsonDecode(rolesResponse.body) as List; - for (var user in users) { - if (user['username'].toString() == userName) { - for (var role in user['roles']) { - if (role['roleid'] == 3 || role['roleid'] == 4) { - return true; - } - } - } - } - } - return false; - } - - @override - void logout() { - print('Logging out of Moodle...'); - resetLMSUserInfo(); - } - - @override - void resetLMSUserInfo() { - // Clear all user-related fields - _userToken = null; - apiURL = ''; - userName = null; - firstName = null; - lastName = null; - siteName = null; - fullName = null; - profileImage = null; - courses = []; - } - - // **************************************************************************************** - // Course-related methods - // **************************************************************************************** - - @override - Future> getCourses() async { - // Returns all courses on the Moodle site (requires admin or special permissions) - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': 'core_course_get_courses', - 'moodlewsrestformat': 'json', - }); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final listData = jsonDecode(response.body) as List; - return listData.map((i) => Course.empty().fromMoodleJson(i)).toList(); - } - - @override - Future> getUserCourses() async { - // Returns courses the user is enrolled in - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': - 'core_course_get_enrolled_courses_by_timeline_classification', - 'classification': 'inprogress', - 'moodlewsrestformat': 'json', - }); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final decodedJson = jsonDecode(response.body); - List userCourses; - - // The response can be either a List or a Map with a 'courses' key - if (decodedJson is List) { - userCourses = - decodedJson.map((i) => Course.empty().fromMoodleJson(i)).toList(); - } else if (decodedJson is Map) { - final courseList = decodedJson['courses'] as List; - userCourses = - courseList.map((i) => Course.empty().fromMoodleJson(i)).toList(); - } else { - throw StateError('Unexpected response format from Moodle'); - } - - // Optionally fetch quizzes/essays for each course - for (Course c in userCourses) { - c.quizzes = await getQuizzes(c.id); - c.essays = await getEssays(c.id); - } - return userCourses; - } - - Future> getAssignmentOverrides() async { - // Returns courses the user is enrolled in - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_get_all_overrides', - 'moodlewsrestformat': 'json', - }); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final decodedJson = jsonDecode(response.body); - List assignmentOverrides; - - if (decodedJson is List) { - assignmentOverrides = - decodedJson.map((i) => Override.empty().fromMoodleJson(i)).toList(); - } else if (decodedJson is Map) { - final courseList = decodedJson['courses'] as List; - assignmentOverrides = - courseList.map((i) => Override.empty().fromMoodleJson(i)).toList(); - } else { - throw StateError('Unexpected response format from Moodle'); - } - - return assignmentOverrides; - } - - @override - Future> getCourseParticipants(String courseId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = - await ApiService().httpPost(Uri.parse(apiURL + serverUrl), body: { - 'wstoken': _userToken, - 'wsfunction': 'core_enrol_get_enrolled_users', - 'courseid': courseId, - 'moodlewsrestformat': 'json', - }); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final decodedJson = jsonDecode(response.body); - List participants = []; - if (decodedJson is List) { - for (var participant in decodedJson) { - if (isStudent(participant)) { - participants.add(Participant.empty().fromMoodleJson(participant)); - } - } - return participants; - // return decodedJson - // .map((i) => Participant.empty().fromMoodleJson(i)) - // .toList(); - } else { - throw StateError('Unexpected response format (expected a List)'); - } - } - - bool isStudent(Map json) { - // Moodle student role id equals 5 - bool isStudent = false; - for (Map role in json['roles']) { - if (role['roleid'] == 5) { - isStudent = true; - } - } - return isStudent; - } - - // **************************************************************************************** - // Quiz methods - // **************************************************************************************** - - @override - Future importQuiz(String courseid, String quizXml) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_quizgen_import_questions', - 'moodlewsrestformat': 'json', - 'courseid': courseid, - 'questionxml': quizXml, - }, - ); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - // Check if Moodle returned an 'error' inside the JSON string - if (response.body.contains('error')) { - throw HttpException(response.body); - } - } - - @override - Future> getQuizzes(int? courseID, {int? topicId}) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'mod_quiz_get_quizzes_by_courses', - 'moodlewsrestformat': 'json', - }, - ); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final quizzesMap = jsonDecode(response.body) as Map; - final decodedJson = quizzesMap['quizzes'] as List?; - - if (decodedJson == null) { - return []; - } - - List quizList = []; - for (var item in decodedJson) { - // If courseID is null, return all quizzes; otherwise filter by course - if (courseID == null || item['course'] == courseID) { - quizList.add(Quiz( - name: item['name'], - coursedId: item['course'], - description: item['intro'], - id: item['id'], - timeOpen: item['timeopen'] = - DateTime.fromMillisecondsSinceEpoch(item['timeopen'] * 1000), - timeClose: item['timeclose'] = - DateTime.fromMillisecondsSinceEpoch(item['timeclose'] * 1000))); - } - } - return quizList; - } - - @override - Future createQuiz(String courseid, String quizname, String quizintro, - String sectionid, String timeopen, String timeclose) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_create_quiz', - 'moodlewsrestformat': 'json', - 'courseid': courseid, - 'name': quizname, - 'intro': quizintro, - 'sectionid': sectionid, - 'timeopen': timeopen, - 'timeclose': timeclose, - }, - ); - - if (response.statusCode != 200) { - print('Failed to create quiz. Status code: ${response.statusCode}.'); - return null; - } - - final responseData = jsonDecode(response.body) as Map; - print('Create Quiz Response: $responseData'); - - return responseData['quizid']; - } catch (e) { - print('Error creating quiz: $e'); - return null; - } - } - - @override - Future addRandomQuestions( - String categoryid, String quizid, String numquestions) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_add_type_randoms_to_quiz', - 'moodlewsrestformat': 'json', - 'categoryid': categoryid, - 'quizid': quizid, - 'numquestions': numquestions, - }, - ); - - if (response.statusCode != 200) { - return 'Request failed with status: ${response.statusCode}.'; - } - - // The response may be a simple boolean string or a JSON object - try { - if (response.body == 'true' || response.body == 'false') { - final boolString = (response.body == 'true').toString(); - print('Boolean Response: $boolString'); - return boolString; - } else { - final responseData = jsonDecode(response.body) as Map; - print('Response: $responseData'); - return responseData['status']; - } - } catch (e) { - print('Error parsing response in addRandomQuestions: $e'); - return e.toString(); - } - } - - @override - Future importQuizQuestions(String courseid, String quizXml) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_import_questions', - 'moodlewsrestformat': 'json', - 'courseid': courseid, - 'questionxml': quizXml, - }, - ); - - if (response.statusCode != 200) { - print('Request failed with status: ${response.statusCode}.'); - return null; - } - - // Some Moodle plugins return extra text before JSON; parse from first '{' - final int indexOfBrace = response.body.indexOf('{'); - if (indexOfBrace == -1) { - print('No JSON object found in response for importQuizQuestions.'); - return null; - } - final jsonPart = response.body.substring(indexOfBrace); - final responseData = jsonDecode(jsonPart) as Map; - print('Import Questions Response: $responseData'); - - return responseData['categoryid'] as int?; - } catch (e) { - print('Error importing quiz questions: $e'); - return null; - } - } - - // **************************************************************************************** - // Assignment methods - // **************************************************************************************** - - @override - Future> getEssays(int? courseID, {int? topicId}) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'mod_assign_get_assignments', - 'moodlewsrestformat': 'json', - }, - ); - - if (response.statusCode != 200) { - throw HttpException(response.body); - } - - final mapJson = jsonDecode(response.body) as Map; - final coursesList = mapJson['courses'] as List?; - - if (coursesList == null) { - return []; - } - - final results = []; - for (var cItem in coursesList) { - // If courseID is null, get for all courses; if not, filter - if (courseID == null || cItem['id'] == courseID) { - final assignmentList = cItem['assignments'] as List; - for (var a in assignmentList) { - results.add(Assignment.empty().fromMoodleJson(a)); - } - } - } - return results; - } - - @override - Future?> createAssignment( - String courseid, - String sectionid, - String assignmentName, - String startdate, - String enddate, - String rubricJson, - String description, - ) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_create_assignment', - 'moodlewsrestformat': 'json', - 'courseid': courseid, - 'sectionid': sectionid, - 'assignmentName': assignmentName, - 'startdate': startdate, - 'enddate': enddate, - 'rubricJson': rubricJson, - 'description': description, - }, - ); - - if (response.statusCode != 200) { - print('Request failed with status: ${response.statusCode}.'); - return null; - } - - final responseData = jsonDecode(response.body) as Map; - print('Create Assignment Response: $responseData'); - - return responseData; - } catch (e) { - print('Error occurred while creating assignment: $e'); - return null; - } - } - - @override - Future getContextId(int assignmentId, String courseId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'core_course_get_contents', - 'moodlewsrestformat': 'json', - 'courseid': courseId, - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to fetch course contents. Status code: ${response.statusCode}'); - return null; - } - - final data = jsonDecode(response.body) as List; - for (var section in data) { - final modules = section['modules'] as List; - for (var module in modules) { - // Look for an assignment module with matching instance - if (module['instance'] == assignmentId && - module['modname'] == 'assign') { - final contextId = module['contextid']; - print('Context ID for assignment $assignmentId is $contextId'); - return contextId as int?; - } - } - } - return null; - } catch (e, st) { - print('Error fetching context ID: $e'); - print('StackTrace: $st'); - return null; - } - } - - // **************************************************************************************** - // Submissions and grading - // **************************************************************************************** - - @override - Future> getAssignmentSubmissions(int assignmentId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'mod_assign_get_submissions', - 'moodlewsrestformat': 'json', - 'assignmentids[0]': assignmentId.toString(), - 'status': 'submitted', - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to load submissions. Status code: ${response.statusCode}'); - return []; - } - - final data = jsonDecode(response.body) as Map; - if (data.containsKey('exception')) { - throw Exception('Moodle API Error: ${data['message']}'); - } - - // Debugging - print('Full Response Data (Submissions): ${jsonEncode(data)}'); - - final assignmentsArr = data['assignments'] as List? ?? []; - final submissionsData = >[]; - - // Extract each "submission" plus the assignmentId - for (var assign in assignmentsArr) { - final subs = assign['submissions'] as List? ?? []; - for (var sub in subs) { - submissionsData.add({ - 'assignmentid': assign['assignmentid'], - 'submission': sub, - }); - } - } - - if (submissionsData.isEmpty) { - print('No submissions found for assignment $assignmentId'); - return []; - } - - return submissionsData - .map((jsonMap) => Submission.empty().fromMoodleJson(jsonMap)) - .toList(); - } catch (e, st) { - print('Error fetching submissions: $e'); - print('StackTrace: $st'); - return []; - } - } - - @override - Future> getSubmissionsWithGrades( - int assignmentId) async { - // Combine submissions with their associated grade - final submissions = await getAssignmentSubmissions(assignmentId); - final grades = await getAssignmentGrades(assignmentId); - - final results = []; - for (final submission in submissions) { - final match = findGradeForUser(grades, submission.userid); - results.add(SubmissionWithGrade(submission: submission, grade: match)); - } - return results; - } - - @override - Future getSubmissionStatus( - int assignmentId, int userId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'mod_assign_get_submission_status', - 'moodlewsrestformat': 'json', - 'assignid': assignmentId.toString(), - 'userid': userId.toString(), - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to load submission status. Status code: ${response.statusCode}'); - return null; - } - - final data = jsonDecode(response.body) as Map; - if (data.containsKey('exception')) { - throw Exception('Moodle API Error: ${data['message']}'); - } - - return SubmissionStatus.empty().fromMoodleJson(data); - } catch (e, st) { - print('Error fetching submission status: $e'); - print('StackTrace: $st'); - return null; - } - } - - @override - Future> getAssignmentGrades(int assignmentId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'mod_assign_get_grades', - 'moodlewsrestformat': 'json', - 'assignmentids[0]': assignmentId.toString(), - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to load assignment grades. Status code: ${response.statusCode}'); - return []; - } - - final data = jsonDecode(response.body) as Map; - if (data.containsKey('exception')) { - throw Exception('Moodle API Error: ${data['message']}'); - } - - print('Grades Response Data: ${jsonEncode(data)}'); - - final grades = []; - final assignmentsList = data['assignments'] as List? ?? []; - for (var assignment in assignmentsList) { - final gList = assignment['grades'] as List? ?? []; - for (var g in gList) { - grades.add(Grade.empty().fromMoodleJson(g)); - } - } - return grades; - } catch (e, st) { - print('Error fetching assignment grades: $e'); - print('StackTrace: $st'); - return []; - } - } - - @override - Future setRubricGrades( - int assignmentId, int userId, String jsonGrades) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_write_rubric_grades', - 'moodlewsrestformat': 'json', - 'assignmentid': assignmentId.toString(), - 'userid': userId.toString(), - 'rubricgrades': jsonGrades, - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to set rubric grades. Status code: ${response.statusCode}'); - return false; - } - return true; - } catch (e, st) { - print('Error setting rubric grades: $e'); - print('StackTrace: $st'); - return false; - } - } - - @override - Future> getRubricGrades(int assignmentId, int userid) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - try { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_get_rubric_grades', - 'moodlewsrestformat': 'json', - 'assignmentid': assignmentId.toString(), - 'userid': userid.toString(), - }, - ); - - if (response.statusCode != 200) { - print('Failed to load rubric grades. Status: ${response.statusCode}'); - return []; - } - - final data = jsonDecode(response.body) as List; - if (data.isEmpty || data.first is! Map) { - return []; - } - print('Rubric Grades Response: ${jsonEncode(data)}'); - return data; - } catch (e, st) { - print('Error fetching rubric grades: $e'); - print('StackTrace: $st'); - return []; - } - } - - @override - Grade? findGradeForUser(List grades, int userId) { - for (final grade in grades) { - if (grade.userid == userId) { - return grade; - } - } - return null; - } - - // **************************************************************************************** - // Rubric retrieval - // **************************************************************************************** - - @override - Future getRubric(String assignmentid) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken, - 'wsfunction': 'local_learninglens_get_rubric', - 'moodlewsrestformat': 'json', - 'assignmentid': assignmentid, - }, - ); - - if (response.statusCode != 200) { - print('Request failed with status: ${response.statusCode}.'); - return null; - } - - final List responseData = jsonDecode(response.body); - if (responseData.isEmpty || responseData.first is! Map) { - return null; - } - - print('Rubric JSON Response: $responseData'); - return MoodleRubric.empty().fromMoodleJson(responseData.first); - } - - // **************************************************************************************** - // TODO: add the method below to the lms_interface. - // **************************************************************************************** - /** - * Fetches all the questions from a quiz. - */ - Future> getQuestionsFromQuiz(int quizId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - final response = await ApiService().httpPost( - url, - body: { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_get_questions_from_quiz', - 'moodlewsrestformat': 'json', - 'quizid': quizId.toString(), - }, - ); - - if (response.statusCode == 200) { - final List jsonList = json.decode(response.body); - - return jsonList - .map((json) => QuestionType.empty().fromMoodleJson(json)) - .toList(); - } else { - throw Exception("Failed to fetch questions: ${response.body}"); - } - } - - Future addQuizOverride({ - required int quizId, - int? userId, - int? groupId, - int? timeOpen, - int? timeClose, - int? timeLimit, - int? attempts, - String? password, - }) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - // Dynamically build request body, removing null values - final Map body = { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_add_quiz_override', - 'moodlewsrestformat': 'json', - 'quizid': quizId.toString(), - }; - - // Add only non-null fields - if (userId != null) body['userid'] = userId.toString(); - if (groupId != null) body['groupid'] = groupId.toString(); - if (timeOpen != null) body['timeopen'] = timeOpen.toString(); - if (timeClose != null) body['timeclose'] = timeClose.toString(); - if (timeLimit != null) body['timelimit'] = timeLimit.toString(); - if (attempts != null) body['attempts'] = attempts.toString(); - if (password != null && password.isNotEmpty) body['password'] = password; - - final response = await ApiService().httpPost(url, body: body); - - final responseData = json.decode(response.body); - - if (response.statusCode == 200 && responseData is Map) { - return QuizOverride.empty().fromMoodleJson(responseData); - } else { - throw Exception("Failed to create quiz override: ${response.body}"); - } - } - - Future addEssayOverride({ - required int assignid, - int? userId, - int? groupId, - int? allowsubmissionsfromdate, - int? dueDate, - int? cutoffDate, - int? timelimit, - int? sortorder, - }) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - // Dynamically build request body, removing null values - final Map body = { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_add_essay_override', - 'moodlewsrestformat': 'json', - 'assignid': assignid.toString(), - }; - - // Add only non-null fields - if (userId != null) body['userid'] = userId.toString(); - if (groupId != null) body['groupid'] = groupId.toString(); - if (allowsubmissionsfromdate != null) - body['allowsubmissionsfromdate'] = allowsubmissionsfromdate.toString(); - if (dueDate != null) body['duedate'] = dueDate.toString(); - if (cutoffDate != null) body['cutoffdate'] = cutoffDate.toString(); - if (timelimit != null) body['timelimit'] = timelimit.toString(); - if (sortorder != null) body['sortorder'] = sortorder.toString(); - - final response = await ApiService().httpPost(url, body: body); - - final responseData = json.decode(response.body); - - if (response.statusCode == 200 && responseData is Map) { - return 'Override: ${responseData['override_id']}'; - } else { - throw Exception("Failed to create quiz override: ${response.body}"); - } - } - -/** - * Fetches all lesson plans associated with a given course ID. - */ - Future> getLessonPlans(int? courseId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - final response = await ApiService().httpPost( - url, - body: { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_get_lesson_plans_by_course', - 'moodlewsrestformat': 'json', - 'courseid': courseId.toString(), - }, - ); - - // print("Lesson Plans Response: ${response.body}"); - - if (response.statusCode == 200) { - final List jsonList = json.decode(response.body); - return jsonList - .map((json) => LessonPlan.empty().fromMoodleJson(json)) - .toList(); - } else { - throw Exception("Failed to fetch lesson plans: ${response.body}"); - } - } - -// Method to create the lesson in Moodle - Future createLesson({ - required int courseId, - required String lessonPlanName, - required String content, - int introformat = 1, - int showdescription = 1, - int available = 0, - int deadline = 0, - int timelimit = 0, - int retake = 1, - int maxAttempts = 3, - int usepassword = 0, - String password = '', - int completion = 1, - }) async { - try { - print("Creating lesson with courseId: $courseId, name: $lessonPlanName"); - - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - "wstoken": _userToken, - "wsfunction": "local_learninglens_create_lesson", - "moodlewsrestformat": "json", - // REQUIRED fields - "courseid": courseId.toString(), - "name": lessonPlanName, - "intro": content, - // OPTIONAL fields - "introformat": introformat.toString(), - "showdescription": showdescription.toString(), - "available": available.toString(), - "deadline": deadline.toString(), - "timelimit": timelimit.toString(), - "retake": retake.toString(), - "maxattempts": maxAttempts.toString(), - "usepassword": usepassword.toString(), - "password": password, - "completion": completion.toString(), - }, - ); - - final jsonResponse = json.decode(response.body) as Map; - print("createLesson Response: $jsonResponse"); - - if (jsonResponse.containsKey("exception")) { - print("Error creating lesson: ${jsonResponse['message']}"); - return false; - } - - print( - "Lesson created successfully! Lesson ID: ${jsonResponse['lessonId']}"); - print("Linked to Course Module ID: ${jsonResponse['courseModuleId']}"); - - return true; - } catch (e) { - print("Error occurred while creating lesson: $e"); - return false; - } - } - - /** - * Deletes a lesson plan from Moodle by its lesson ID. - */ - Future deleteLessonPlan(int lessonId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - final response = await ApiService().httpPost( - url, - body: { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_delete_lesson_plan', - 'moodlewsrestformat': 'json', - 'lessonid': lessonId.toString(), - }, - ); - - print("Delete Lesson Plan Response: ${response.body}"); - - if (response.statusCode == 200) { - final Map jsonResponse = json.decode(response.body); - - if (jsonResponse.containsKey("status") && - jsonResponse["status"] == "success") { - print("Lesson plan deleted successfully."); - return true; - } else { - print("Error deleting lesson plan: ${jsonResponse['message']}"); - return false; - } - } else { - throw Exception("Failed to delete lesson plan: ${response.body}"); - } - } - - /** - * Updates a lesson plan in Moodle by its lesson ID. - */ - Future updateLessonPlan({ - required int lessonId, - String? name, - String? intro, - int? available, - int? deadline, - }) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - final url = Uri.parse('$apiURL$serverUrl'); - - // Construct request body dynamically - final Map body = { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_update_lesson_plan', - 'moodlewsrestformat': 'json', - 'lessonid': lessonId.toString(), - }; - - if (name != null) body['name'] = name; - if (intro != null) body['intro'] = intro; - if (available != null) body['available'] = available.toString(); - if (deadline != null) body['deadline'] = deadline.toString(); - - final response = await ApiService().httpPost(url, body: body); - - print("Update Lesson Plan Response: ${response.body}"); - - if (response.statusCode == 200) { - final Map jsonResponse = json.decode(response.body); - - if (jsonResponse.containsKey("status") && - jsonResponse["status"] == "success") { - print("Lesson plan updated successfully."); - return true; - } else { - print("Error updating lesson plan: ${jsonResponse['message']}"); - return false; - } - } else { - throw Exception("Failed to update lesson plan: ${response.body}"); - } - } - - Future> getQuizGradesForParticipants( - String courseId, int quizId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - // Get all course participants (filtered to only students) - List students = (await getCourseParticipants(courseId)) - .where((participant) => participant.roles.contains('student')) - .toList(); - - for (var student in students) { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken!, - 'wsfunction': 'mod_quiz_get_user_best_grade', - 'moodlewsrestformat': 'json', - 'quizid': quizId.toString(), - 'userid': student.id.toString(), - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to get grade for user ${student.id}. Status: ${response.statusCode}'); - continue; - } - - final jsonResponse = jsonDecode(response.body); - if (jsonResponse is Map && - jsonResponse.containsKey('grade')) { - student.avgGrade = double.tryParse(jsonResponse['grade'].toString()); - } else { - student.avgGrade = null; // No grade found - } - } - return students; - } - - Future> getEssayGradesForParticipants( - String courseId, int assignmentId) async { - if (_userToken == null) throw StateError('User not logged in to Moodle'); - - // Get all course participants (filtered to only students) - List students = (await getCourseParticipants(courseId)) - .where((participant) => participant.roles.contains('student')) - .toList(); - - for (var student in students) { - final response = await ApiService().httpPost( - Uri.parse(apiURL + serverUrl), - body: { - 'wstoken': _userToken!, - 'wsfunction': 'mod_assign_get_grades', - 'moodlewsrestformat': 'json', - 'assignmentids[0]': assignmentId.toString(), - }, - ); - - if (response.statusCode != 200) { - print( - 'Failed to get grade for user ${student.id}. Status: ${response.statusCode}'); - continue; - } - - final jsonResponse = jsonDecode(response.body); - if (jsonResponse is Map && - jsonResponse.containsKey('assignments')) { - final assignments = jsonResponse['assignments'] as List; - for (var assignment in assignments) { - final grades = assignment['grades'] as List; - for (var grade in grades) { - if (grade['userid'] == student.id) { - student.avgGrade = double.tryParse(grade['grade'].toString()); - break; - } - } - } - } else { - student.avgGrade = null; // No grade found - } - } - return students; - } - - - /// Fetches extended question stats (correct/incorrect/partial attempts) - /// from the local_learninglens_get_question_stats_from_quiz service. - Future> getQuestionStatsFromQuiz(int quizId) async { - if (_userToken == null) { - throw StateError('User not logged in to Moodle'); - } - - final url = Uri.parse('$apiURL$serverUrl'); - - final response = await ApiService().httpPost( - url, - body: { - 'wstoken': _userToken!, - 'wsfunction': 'local_learninglens_get_question_stats_from_quiz', - 'moodlewsrestformat': 'json', - 'quizid': quizId.toString(), - }, - ); - - if (response.statusCode != 200) { - throw Exception('Failed to fetch question stats: ${response.body}'); - } - print(quizId); - print(response.body); - final decoded = json.decode(response.body); - if (decoded is! List) { - throw Exception( - 'Expected a list of question stats but got: ${response.body}', - ); - } - - // Convert each item into a QuestionStatsType instance - return decoded.map((item) { - return QuestionStatsType.fromJson(item); - }).toList(); - } -} diff --git a/team_a/teamA/lib/Api/lms/template/api_singleton.dart b/team_a/teamA/lib/Api/lms/template/api_singleton.dart deleted file mode 100644 index 5c60ebd9..00000000 --- a/team_a/teamA/lib/Api/lms/template/api_singleton.dart +++ /dev/null @@ -1,236 +0,0 @@ -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/lesson_plan.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/quiz_type.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/submission_status.dart'; -import 'package:learninglens_app/beans/grade.dart'; -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; -import 'package:learninglens_app/beans/moodle_rubric.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; - - -class ApiSingleton implements LmsInterface { - static final ApiSingleton _instance = ApiSingleton._internal(); - - ApiSingleton._internal(); - - factory ApiSingleton() { - return _instance; - } - - String? _userToken = ''; - - @override - String serverUrl = ''; - - @override - String apiURL = ''; - - @override - String? userName; - - @override - String? firstName; - - @override - String? lastName; - - @override - String? siteName; - - @override - String? fullName; - - @override - String? profileImage; - - @override - List? courses; - - - // Authentication/Login methods - @override - Future login(String username, String password, String baseURL) { - // TODO: implement login - throw UnimplementedError(); - } - - @override - bool isLoggedIn() { - return _userToken != null; - } - - @override - Future isUserTeacher(List moodleCourses) { - // TODO: implement isUserTeacher - throw UnimplementedError(); - } - - @override - void logout() { - print('Logging out of LMS...'); - resetLMSUserInfo(); - } - - @override - void resetLMSUserInfo() { - _userToken = null; - apiURL = ''; - userName = null; - firstName = null; - lastName = null; - siteName = null; - fullName = null; - profileImage = null; - courses = []; - } - - // Course methods - @override - Future> getCourses() { - // TODO: implement getCourses - throw UnimplementedError(); - } - - @override - Future> getUserCourses() { - // TODO: implement getUserCourses - throw UnimplementedError(); - } - - @override - Future> getCourseParticipants(String courseId) { - // TODO: implement getCourseParticipants - throw UnimplementedError(); - } - - - // Quiz methods - @override - Future importQuiz(String courseid, String quizXml) { - // TODO: implement importQuiz - throw UnimplementedError(); - } - - @override - Future> getQuizzes(int? courseID, {int? topicId}) { - // TODO: implement getQuizzes - throw UnimplementedError(); - } - - @override - Future createQuiz(String courseid, String quizname, String quizintro, String sectionid, String timeopen, String timeclose) { - // TODO: implement createQuiz - throw UnimplementedError(); - } - - @override - Future importQuizQuestions(String courseid, String quizXml) { - // TODO: implement importQuizQuestions - throw UnimplementedError(); - } - - @override - Future addRandomQuestions(String categoryid, String quizid, String numquestions) { - // TODO: implement addRandomQuestions - throw UnimplementedError(); - } - - @override - Future> getQuestionsFromQuiz(int quizId) async { - // TODO: implement google api code - throw UnimplementedError(); - } - - - // Assignment methods - @override - Future> getEssays(int? courseID, {int? topicId}) { - // TODO: implement getEssays - throw UnimplementedError(); - } - - @override - Future?> createAssignment(String courseid, String sectionid, String assignmentName, String startdate, String enddate, String rubricJson, String description) { - // TODO: implement createAssignment - throw UnimplementedError(); - } - - @override - Future getContextId(int assignmentId, String courseId) { - // TODO: implement getContextId - throw UnimplementedError(); - } - - // Submission and grading methods - @override - Future> getAssignmentSubmissions(int assignmentId) { - // TODO: implement getAssignmentSubmissions - throw UnimplementedError(); - } - - @override - Future> getSubmissionsWithGrades(int assignmentId) { - // TODO: implement getSubmissionsWithGrades - throw UnimplementedError(); - } - - @override - Future getSubmissionStatus(int assignmentId, int userId) { - // TODO: implement getSubmissionStatus - throw UnimplementedError(); - } - - @override - Future> getAssignmentGrades(int assignmentId) { - // TODO: implement getAssignmentGrades - throw UnimplementedError(); - } - - @override - Future setRubricGrades(int assignmentId, int userId, String jsonGrades) { - // TODO: implement setRubricGrades - throw UnimplementedError(); - } - - @override - Future getRubricGrades(int assignmentId, int userid) { - // TODO: implement getRubricGrades - throw UnimplementedError(); - } - - @override - Grade? findGradeForUser(List grades, int userId) { - // TODO: implement findGradeForUser - throw UnimplementedError(); - } - - // Rubric methods - @override - Future getRubric(String assignmentid) { - // TODO: implement getRubric - throw UnimplementedError(); - } - - //Get Lesson Plan - FuturegetLessonPlan(String courseId){ - //\TODO: implement getLessonPlan - throw UnimplementedError(); - } - - @override - Future> getQuestionsFromQuizGoogle(String courseId, String courseWorkId) async { - // TODO: implement google api code - throw UnimplementedError(); - } - - @override - Future> getQuizGradesForParticipants(String courseId, int quizId) { - // TODO: implement getQuizGradesForParticipants - throw UnimplementedError(); - } - -} \ No newline at end of file diff --git a/team_a/teamA/lib/Controller/assessment_generator.dart b/team_a/teamA/lib/Controller/assessment_generator.dart deleted file mode 100644 index a8a97c46..00000000 --- a/team_a/teamA/lib/Controller/assessment_generator.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:convert'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/services/api_service.dart'; - -class AssessmentGenerator -{ - final String serverUrl; - - AssessmentGenerator({required this.serverUrl}); - - Future generateAssessment(String queryPrompt) async { - final response = await ApiService().httpPost( - Uri.parse('$serverUrl/generateAssessment'), - headers: {'Content-Type': 'application/x-www-form-urlencoded'}, - body: {'QueryPrompt': queryPrompt}, - ); - - if (response.statusCode == 200) { - final responseBody = json.decode(response.body); - final aiResponse = responseBody['assessment']; - return Quiz.fromXmlString(aiResponse); - } else { - throw Exception('Failed to generate assessment'); - } - } -} diff --git a/team_a/teamA/lib/Controller/custom_appbar.dart b/team_a/teamA/lib/Controller/custom_appbar.dart deleted file mode 100644 index b212a208..00000000 --- a/team_a/teamA/lib/Controller/custom_appbar.dart +++ /dev/null @@ -1,195 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/experimental/assistant/textbased_function_caller_view.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Views/dashboard.dart'; -import 'package:learninglens_app/Views/user_settings.dart'; -import 'package:learninglens_app/Views/chat_screen.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -class ClassroomSelection { - static LmsType selectedClassroom = LocalStorageService.getSelectedClassroom() == LmsType.MOODLE - ? LmsType.MOODLE - : LmsType.GOOGLE; -} - -class CustomAppBar extends StatefulWidget implements PreferredSizeWidget { - final String title; - final String userprofileurl; - final VoidCallback? onRefresh; // Optional refresh callback - - CustomAppBar({required this.title, required this.userprofileurl, this.onRefresh}); - - @override - _CustomAppBarState createState() => _CustomAppBarState(); - - @override - Size get preferredSize => Size.fromHeight(kToolbarHeight); -} - -class _CustomAppBarState extends State { - @override - Widget build(BuildContext context) { - return AppBar( - backgroundColor: Theme.of(context).colorScheme.primaryContainer, - title: Text( - widget.title, - textAlign: TextAlign.center, - ), - centerTitle: true, - leadingWidth: 120, - leading: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Flexible( - child: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: isDashboard(context) - ? null - : () { - Navigator.pop(context); - }, - ), - ), - Flexible( - child: IconButton( - icon: Icon(Icons.home), - onPressed: isDashboard(context) - ? null - : () { - navigateToSelectedDashboard(context); - }, - ), - ), - Flexible( - child: IconButton( - icon: Icon(Icons.chat_rounded), - onPressed: () { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => ChatScreen() - ) - ); - }, - ), - ), - ], - ), - actions: [ - - Flexible( - child: IconButton( - icon: Icon(Icons.science), // Science Icon - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => TextBasedFunctionCallerView()), - ); - }, - ), - ), - // Refresh button: Instead of relying on an external callback, - // try to obtain the current route's name and then replace the route, - // effectively refreshing the current view. - IconButton( - icon: Icon(Icons.refresh), - onPressed: () { - final currentRouteName = ModalRoute.of(context)?.settings.name; - if (currentRouteName != null) { - Navigator.pushReplacementNamed(context, currentRouteName); - } else { - // Fallback: if no route name is available, call the provided onRefresh callback if any. - widget.onRefresh?.call(); - } - }, - ), - DropdownButtonHideUnderline( - child: DropdownButton( - value: ClassroomSelection.selectedClassroom, - onChanged: isDashboard(context) - ? (LmsType? newValue) { - if (newValue != null) { - setState(() { - ClassroomSelection.selectedClassroom = newValue; - }); - navigateToSelectedDashboard(context); - } - } - : null, - items: LmsType.values.map>((LmsType value) { - return DropdownMenuItem( - value: value, - child: Text( - value == LmsType.GOOGLE ? 'Google Classroom' : 'Moodle Classroom', - ), - ); - }).toList(), - ), - ), - IconButton( - icon: Icon(Icons.settings), - onPressed: !isDashboard(context) - ? null - : () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => UserSettings()), - ); - }, - ), - Padding( - padding: EdgeInsets.only(right: 10.0), - child: InkWell( - child: Material( - color: Colors.transparent, - child: Container( - width: 50, - height: 50, - decoration: BoxDecoration( - shape: BoxShape.circle, - ), - child: ClipOval( - child: Image.network( - widget.userprofileurl, - height: 50, - width: 50, - fit: BoxFit.cover, - errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) { - // print('Image load error: $error'); - // Just display the account_circle icon be default - return Icon(Icons.account_circle, size: 50); - }, - ), - ), - ), - ), - ), - ), - ], - ); - } - - bool isDashboard(BuildContext context) { - return widget.title == 'Learning Lens'; - } - - void navigateToSelectedDashboard(BuildContext context) { - if (ClassroomSelection.selectedClassroom == LmsType.GOOGLE) { - LocalStorageService.saveSelectedClassroom(LmsType.GOOGLE); - } else { - LocalStorageService.saveSelectedClassroom(LmsType.MOODLE); - } - - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => TeacherDashboard(), - // builder: (context) => ClassroomSelection.selectedClassroom == LmsType.GOOGLE - // // ? GoogleTeacherDashboard() - // ? TeacherDashboard() - // : TeacherDashboard(), - ), - ); - } -} diff --git a/team_a/teamA/lib/Controller/essay_generator.dart b/team_a/teamA/lib/Controller/essay_generator.dart deleted file mode 100644 index 18b5370b..00000000 --- a/team_a/teamA/lib/Controller/essay_generator.dart +++ /dev/null @@ -1,223 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/services.dart'; -import 'package:flutter/material.dart'; -import 'package:learninglens_app/beans/criterion.dart'; - -class Essay -{ - //Holds the assignment prompt - String? prompt; - //Holds the course level information - String? courseLevel; - //Holds the list of crtiera for a given assignment - List criteria; - //Constructor for a standard essay - Essay(this.prompt, this.courseLevel, this.criteria); - //Generates the table data for the rubric based on the criteria for the essay object. Does not create header row. - List> genTableData() - { - List critList = criteria; - List> tableData = []; - for (Criterion c in critList) - { - int iterator = 1; - Map tempMap = {}; - String currName = c.name; - num currWeight = c.points; - Map desc = c.descriptions; - for (MapEntry d in desc.entries) { - if (iterator == 1) { - tempMap[''] = '$currName\n\nPoints: $currWeight'; - iterator++; - } - tempMap[d.key] = d.value; - iterator++; - } - tableData.add(tempMap); - } - return tableData; - } - //Creates the header row for the table data - List genHeaderData() - { - List headerData = criteria[0].descriptions.keys.toList(); - headerData.insert(0, ''); - return headerData; - } -} - - -// Fetch Criteria data from JSON file and add it to the program -Future> fetchJsonCriteria() async -{ - final String jsonString = await rootBundle.loadString('assets/Criteria.json'); - final Map jsonData = json.decode(jsonString); - List critList = jsonData['Criteria']; // Access the 'users' key - return critList.map((critJson) => Criterion.fromJson(critJson)).toList(); -} - -// Take the default descriptions from the JSON and build full list of critieria based on scale -Future> generateCriteria( - int scale, List selectedCriteria) async { - List allCriteria = await fetchJsonCriteria() as List; - List myCriteria = []; - int iterator = 0; - for (Criterion c in allCriteria) { - List newValues = []; - if (selectedCriteria.contains(c.name)) { - myCriteria.add(c); - switch (scale) { - case 3: - for (int i = 0; i <= 2; i++) { - String currScale = c.scale3[i]; - String currDesc = c.defaultDesc; - newValues.add("Student displays $currScale $currDesc"); - } - myCriteria[iterator].addDescriptions(c.scale3, newValues); - myCriteria[iterator].setWeight(3); - iterator++; - case 4: - for (int i = 0; i <= 3; i++) { - String currScale = c.scale4[i]; - String currDesc = c.defaultDesc; - newValues.add("Student displays $currScale $currDesc"); - } - myCriteria[iterator].addDescriptions(c.scale4, newValues); - myCriteria[iterator].setWeight(4); - iterator++; - case 5: - for (int i = 0; i <= 4; i++) { - String currScale = c.scale5[i]; - String currDesc = c.defaultDesc; - newValues.add("Student displays $currScale $currDesc"); - } - myCriteria[iterator].addDescriptions(c.scale5, newValues); - myCriteria[iterator].setWeight(5); - iterator++; - } - } - } - return myCriteria; -} - -//App that constructs the table widget -class TableApp extends StatelessWidget -{ - const TableApp(this.tableData, this.headerData); - final List> tableData; - final List headerData; - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Editable Table', - home: Scaffold( - appBar: AppBar( - title: Text('Rubric'), - ), - body: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: EditableTable(tableData: tableData, headerData: headerData), - ), - ), - ), - ); - } -} - -//Object that creates editable table rows -class EditableTable extends StatefulWidget -{ - final List> tableData; - final List headerData; - EditableTable({required this.tableData, required this.headerData}); - @override - _EditableTableState createState() => _EditableTableState(); -} - -class _EditableTableState extends State -{ - late List> controllers; - @override - void initState() { - super.initState(); - // Create controllers for each cell in the table except the first column - controllers = widget.tableData.map((row) { - return row.map((key, value) { - return MapEntry(key, TextEditingController(text: value)); - }); - }).toList(); - } - @override - Widget build(BuildContext context) { - return Table( - border: TableBorder.all(), - defaultVerticalAlignment: TableCellVerticalAlignment.middle, - children: _buildTableRows(), - ); - } - // Function to build the table rows dynamically - List _buildTableRows() { - List rows = []; - // Add table header row dynamically based on column headers - rows.add( - TableRow( - children: widget.headerData.map((header) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Text(header, - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold)), - ); - }).toList(), - ), - ); - // Add rows dynamically based on data - for (var i = 0; i < widget.tableData.length; i++) { - rows.add( - TableRow( - children: widget.headerData.map((header) { - // If it is the first column, display it as static text - if (header == widget.headerData.first) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Text(widget.tableData[i][header] ?? '', - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - )), - ); - } - // For other columns, make them editable - return Padding( - padding: const EdgeInsets.all(8.0), - child: TextFormField( - controller: controllers[i][header], - onChanged: (value) { - widget.tableData[i][header] = value; // Update the data - }, - decoration: InputDecoration( - border: OutlineInputBorder(), - ), - keyboardType: TextInputType.multiline, - maxLines: null, // This allows the text field to wrap and expand - minLines: 1, // Minimum number of lines the field should show - ), - ); - }).toList(), - ), - ); - } - return rows; - } - @override - void dispose() { - // Dispose of all controllers when the widget is disposed - for (var row in controllers) { - for (var controller in row.values) { - controller.dispose(); - } - } - super.dispose(); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Controller/g_bean.dart b/team_a/teamA/lib/Controller/g_bean.dart deleted file mode 100644 index a83045a3..00000000 --- a/team_a/teamA/lib/Controller/g_bean.dart +++ /dev/null @@ -1,787 +0,0 @@ -class GCourse { - String id; - String fullName; - - GCourse({required this.id, required this.fullName}); - - factory GCourse.fromJson(Map json) { - return GCourse( - id: json['id'] as String, - fullName: json['name'] - as String, // Use 'name' to match the Google Classroom API - ); - } -} - -// beans.dart - -class Course { - String id; - String name; - String? section; - String? descriptionHeading; - String? description; - String? room; - String? ownerId; - String? creationTime; - String? updateTime; - String? enrollmentCode; - String? courseState; // Consider using an enum for CourseState - String? alternateLink; - String? teacherGroupEmail; - String? courseGroupEmail; - DriveFolder? teacherFolder; - List? courseMaterialSets; - bool? guardiansEnabled; - String? calendarId; - GradebookSettings? gradebookSettings; - - Course({ - required this.id, - required this.name, - this.section, - this.descriptionHeading, - this.description, - this.room, - this.ownerId, - this.creationTime, - this.updateTime, - this.enrollmentCode, - this.courseState, - this.alternateLink, - this.teacherGroupEmail, - this.courseGroupEmail, - this.teacherFolder, - this.courseMaterialSets, - this.guardiansEnabled, - this.calendarId, - this.gradebookSettings, - }); - - factory Course.fromJson(Map json) { - return Course( - id: json['id'] as String, - name: json['name'] as String, - section: json['section'] as String?, - descriptionHeading: json['descriptionHeading'] as String?, - description: json['description'] as String?, - room: json['room'] as String?, - ownerId: json['ownerId'] as String?, - creationTime: json['creationTime'] as String?, - updateTime: json['updateTime'] as String?, - enrollmentCode: json['enrollmentCode'] as String?, - courseState: json['courseState'] as String?, // Consider using an enum - alternateLink: json['alternateLink'] as String?, - teacherGroupEmail: json['teacherGroupEmail'] as String?, - courseGroupEmail: json['courseGroupEmail'] as String?, - teacherFolder: json['teacherFolder'] == null - ? null - : DriveFolder.fromJson(json['teacherFolder'] as Map), - courseMaterialSets: (json['courseMaterialSets'] as List?) - ?.map((e) => CourseMaterialSet.fromJson(e as Map)) - .toList(), - guardiansEnabled: json['guardiansEnabled'] as bool?, - calendarId: json['calendarId'] as String?, - gradebookSettings: json['gradebookSettings'] == null - ? null - : GradebookSettings.fromJson( - json['gradebookSettings'] as Map), - ); - } - - Map toJson() { - return { - 'id': id, - 'name': name, - 'section': section, - 'descriptionHeading': descriptionHeading, - 'description': description, - 'room': room, - 'ownerId': ownerId, - 'creationTime': creationTime, - 'updateTime': updateTime, - 'enrollmentCode': enrollmentCode, - 'courseState': courseState, - 'alternateLink': alternateLink, - 'teacherGroupEmail': teacherGroupEmail, - 'courseGroupEmail': courseGroupEmail, - 'teacherFolder': teacherFolder?.toJson(), - 'courseMaterialSets': courseMaterialSets?.map((e) => e.toJson()).toList(), - 'guardiansEnabled': guardiansEnabled, - 'calendarId': calendarId, - 'gradebookSettings': gradebookSettings?.toJson(), - }; - } - - @override - String toString() { - return 'Course{id: $id, name: $name, section: $section}'; - } -} - -class DriveFolder { - String? id; - String? title; - String? alternateLink; - - DriveFolder({this.id, this.title, this.alternateLink}); - - factory DriveFolder.fromJson(Map json) { - return DriveFolder( - id: json['id'] as String?, - title: json['title'] as String?, - alternateLink: json['alternateLink'] as String?, - ); - } - - Map toJson() { - return { - 'id': id, - 'title': title, - 'alternateLink': alternateLink, - }; - } -} - -class CourseMaterialSet { - String? title; - - CourseMaterialSet({this.title}); - - factory CourseMaterialSet.fromJson(Map json) { - return CourseMaterialSet( - title: json['title'] as String?, - ); - } - - Map toJson() { - return { - 'title': title, - }; - } -} - -class GradebookSettings { - // Define properties based on the GradebookSettings object - // Example: - String? categoryId; - - GradebookSettings({this.categoryId}); - - factory GradebookSettings.fromJson(Map json) { - return GradebookSettings( - categoryId: json['categoryId'] as String?, - ); - } - - Map toJson() { - return { - 'categoryId': categoryId, - }; - } -} - -// CourseWork Bean -class CourseWork { - String? courseId; - String? id; - String? title; - String? description; - List? materials; - String? state; // Consider enum for CourseWorkState - String? alternateLink; - String? creationTime; - String? updateTime; - Date? dueDate; - TimeOfDay? dueTime; - String? scheduledTime; - double? maxPoints; - String? workType; // Consider enum for CourseWorkType - bool? associatedWithDeveloper; - String? assigneeMode; // Consider enum for AssigneeMode - IndividualStudentsOptions? individualStudentsOptions; - String? submissionModificationMode; // Consider enum - String? creatorUserId; - String? topicId; - GradeCategory? gradeCategory; - String? gradingPeriodId; - Assignment? assignment; - MultipleChoiceQuestion? multipleChoiceQuestion; - String? previewVersion; - - CourseWork( - {this.courseId, - this.id, - this.title, - this.description, - this.materials, - this.state, - this.alternateLink, - this.creationTime, - this.updateTime, - this.dueDate, - this.dueTime, - this.scheduledTime, - this.maxPoints, - this.workType, - this.associatedWithDeveloper, - this.assigneeMode, - this.individualStudentsOptions, - this.submissionModificationMode, - this.creatorUserId, - this.topicId, - this.gradeCategory, - this.gradingPeriodId, - this.assignment, - this.multipleChoiceQuestion, - this.previewVersion}); - - factory CourseWork.fromJson(Map json) { - return CourseWork( - courseId: json['courseId'] as String?, - id: json['id'] as String?, - title: json['title'] as String?, - description: json['description'] as String?, - materials: (json['materials'] as List?) - ?.map((e) => Material.fromJson(e as Map)) - .toList(), - state: json['state'] as String?, - alternateLink: json['alternateLink'] as String?, - creationTime: json['creationTime'] as String?, - updateTime: json['updateTime'] as String?, - dueDate: json['dueDate'] == null - ? null - : Date.fromJson(json['dueDate'] as Map), - dueTime: json['dueTime'] == null - ? null - : TimeOfDay.fromJson(json['dueTime'] as Map), - scheduledTime: json['scheduledTime'] as String?, - maxPoints: (json['maxPoints'] as num?)?.toDouble(), - workType: json['workType'] as String?, - associatedWithDeveloper: json['associatedWithDeveloper'] as bool?, - assigneeMode: json['assigneeMode'] as String?, - individualStudentsOptions: json['individualStudentsOptions'] == null - ? null - : IndividualStudentsOptions.fromJson( - json['individualStudentsOptions'] as Map), - submissionModificationMode: json['submissionModificationMode'] as String?, - creatorUserId: json['creatorUserId'] as String?, - topicId: json['topicId'] as String?, - gradeCategory: json['gradeCategory'] == null - ? null - : GradeCategory.fromJson( - json['gradeCategory'] as Map), - gradingPeriodId: json['gradingPeriodId'] as String?, - assignment: json['assignment'] == null - ? null - : Assignment.fromJson(json['assignment'] as Map), - multipleChoiceQuestion: json['multipleChoiceQuestion'] == null - ? null - : MultipleChoiceQuestion.fromJson( - json['multipleChoiceQuestion'] as Map), - previewVersion: json['previewVersion'] as String?, - ); - } - Map toJson() { - return { - 'courseId': courseId, - 'id': id, - 'title': title, - 'description': description, - 'materials': materials?.map((e) => e.toJson()).toList(), - 'state': state, - 'alternateLink': alternateLink, - 'creationTime': creationTime, - 'updateTime': updateTime, - 'dueDate': dueDate?.toJson(), - 'dueTime': dueTime?.toJson(), - 'scheduledTime': scheduledTime, - 'maxPoints': maxPoints, - 'workType': workType, - 'associatedWithDeveloper': associatedWithDeveloper, - 'assigneeMode': assigneeMode, - 'individualStudentsOptions': individualStudentsOptions?.toJson(), - 'submissionModificationMode': submissionModificationMode, - 'creatorUserId': creatorUserId, - 'topicId': topicId, - 'gradeCategory': gradeCategory?.toJson(), - 'gradingPeriodId': gradingPeriodId, - 'assignment': assignment?.toJson(), - 'multipleChoiceQuestion': multipleChoiceQuestion?.toJson(), - 'previewVersion': previewVersion, - }; - } - - @override - String toString() { - return 'CourseWork{id: $id, title: $title, description: $description}'; - } -} - -// Material Bean -class Material { - String? title; - String? alternateLink; - - Material({this.title, this.alternateLink}); - - factory Material.fromJson(Map json) { - return Material( - title: json['title'] as String?, - alternateLink: json['alternateLink'] as String?, - ); - } - - Map toJson() { - return { - 'title': title, - 'alternateLink': alternateLink, - }; - } - - @override - String toString() { - return 'Material{title: $title, alternateLink: $alternateLink}'; - } -} - -// Date Bean -class Date { - int? year; - int? month; - int? day; - - Date({this.year, this.month, this.day}); - - factory Date.fromJson(Map json) { - return Date( - year: json['year'] as int?, - month: json['month'] as int?, - day: json['day'] as int?, - ); - } - - Map toJson() { - return { - 'year': year, - 'month': month, - 'day': day, - }; - } - - @override - String toString() { - return 'Date{year: $year, month: $month, day: $day}'; - } -} - -// TimeOfDay Bean -class TimeOfDay { - int? hours; - int? minutes; - int? seconds; - int? nanos; - - TimeOfDay({this.hours, this.minutes, this.seconds, this.nanos}); - - factory TimeOfDay.fromJson(Map json) { - return TimeOfDay( - hours: json['hours'] as int?, - minutes: json['minutes'] as int?, - seconds: json['seconds'] as int?, - nanos: json['nanos'] as int?, - ); - } - - Map toJson() { - return { - 'hours': hours, - 'minutes': minutes, - 'seconds': seconds, - 'nanos': nanos, - }; - } - - @override - String toString() { - return 'TimeOfDay{hours: $hours, minutes: $minutes}'; - } -} - -// IndividualStudentsOptions Bean -class IndividualStudentsOptions { - // Add properties as needed based on the API definition - - IndividualStudentsOptions(); - - factory IndividualStudentsOptions.fromJson(Map json) { - return IndividualStudentsOptions(); - } - - Map toJson() { - return {}; - } -} - -// GradeCategory Bean -class GradeCategory { - String? name; - double? defaultPoints; - - GradeCategory({this.name, this.defaultPoints}); - - factory GradeCategory.fromJson(Map json) { - return GradeCategory( - name: json['name'] as String?, - defaultPoints: (json['defaultPoints'] as num?)?.toDouble(), - ); - } - - Map toJson() { - return { - 'name': name, - 'defaultPoints': defaultPoints, - }; - } - - @override - String toString() { - return 'GradeCategory{name: $name, defaultPoints: $defaultPoints}'; - } -} - -// Assignment Bean -class Assignment { - // Add properties as needed based on the API definition - // Example: - String? instructions; - - Assignment({this.instructions}); - - factory Assignment.fromJson(Map json) { - return Assignment( - instructions: json['instructions'] as String?, - ); - } - - Map toJson() { - return { - 'instructions': instructions, - }; - } -} - -// MultipleChoiceQuestion Bean -class MultipleChoiceQuestion { - // Add properties as needed based on the API definition - List? choices; - - MultipleChoiceQuestion({this.choices}); - - factory MultipleChoiceQuestion.fromJson(Map json) { - return MultipleChoiceQuestion( - choices: - (json['choices'] as List?)?.map((e) => e as String).toList(), - ); - } - - Map toJson() { - return { - 'choices': choices, - }; - } -} - -// UserProfile Bean (Used in Student and Teacher) -class UserProfile { - String? id; - Name? name; - String? emailAddress; - String? photoUrl; - - UserProfile({this.id, this.name, this.emailAddress, this.photoUrl}); - - factory UserProfile.fromJson(Map json) { - return UserProfile( - id: json['id'] as String?, - name: json['name'] == null - ? null - : Name.fromJson(json['name'] as Map), - emailAddress: json['emailAddress'] as String?, - photoUrl: json['photoUrl'] as String?, - ); - } - - Map toJson() { - return { - 'id': id, - 'name': name?.toJson(), - 'emailAddress': emailAddress, - 'photoUrl': photoUrl, - }; - } -} - -// Name Bean (Used within UserProfile) -class Name { - String? familyName; - String? givenName; - String? fullName; - - Name({this.familyName, this.givenName, this.fullName}); - - factory Name.fromJson(Map json) { - return Name( - familyName: json['familyName'] as String?, - givenName: json['givenName'] as String?, - fullName: json['fullName'] as String?, - ); - } - - Map toJson() { - return { - 'familyName': familyName, - 'givenName': givenName, - 'fullName': fullName, - }; - } -} - -// Student Bean -class Student { - String courseId; - String userId; - UserProfile? profile; - DriveFolder? studentWorkFolder; - - Student( - {required this.courseId, - required this.userId, - this.profile, - this.studentWorkFolder}); - - factory Student.fromJson(Map json) { - return Student( - courseId: json['courseId'] as String, - userId: json['userId'] as String, - profile: json['profile'] == null - ? null - : UserProfile.fromJson(json['profile'] as Map), - studentWorkFolder: json['studentWorkFolder'] == null - ? null - : DriveFolder.fromJson( - json['studentWorkFolder'] as Map), - ); - } - - Map toJson() { - return { - 'courseId': courseId, - 'userId': userId, - 'profile': profile?.toJson(), - 'studentWorkFolder': studentWorkFolder?.toJson(), - }; - } -} - -// Teacher Bean -class Teacher { - String courseId; - String userId; - UserProfile? profile; - - Teacher({required this.courseId, required this.userId, this.profile}); - - factory Teacher.fromJson(Map json) { - return Teacher( - courseId: json['courseId'] as String, - userId: json['userId'] as String, - profile: json['profile'] == null - ? null - : UserProfile.fromJson(json['profile'] as Map), - ); - } - - Map toJson() { - return { - 'courseId': courseId, - 'userId': userId, - 'profile': profile?.toJson(), - }; - } -} - -//courses.topics Bean -class Topic { - String courseId; - String topicId; - String name; - String updateTime; - - Topic( - {required this.courseId, - required this.topicId, - required this.name, - required this.updateTime}); - - factory Topic.fromJson(Map json) { - return Topic( - courseId: json['courseId'] as String, - topicId: json['topicId'] as String, - name: json['name'] as String, - updateTime: json['updateTime'] as String, - ); - } - - Map toJson() { - return { - 'courseId': courseId, - 'topicId': topicId, - 'name': name, - 'updateTime': updateTime, - }; - } -} - -//courses.courseWork.rubrics Bean -class Rubric { - String courseId; - String courseWorkId; - String id; - String creationTime; - String updateTime; - List? criteria; - String? sourceSpreadsheetId; //Union field - - Rubric( - {required this.courseId, - required this.courseWorkId, - required this.id, - required this.creationTime, - required this.updateTime, - this.criteria, - this.sourceSpreadsheetId}); - - factory Rubric.fromJson(Map json) { - return Rubric( - courseId: json['courseId'] as String, - courseWorkId: json['courseWorkId'] as String, - id: json['id'] as String, - creationTime: json['creationTime'] as String, - updateTime: json['updateTime'] as String, - criteria: (json['criteria'] as List?) - ?.map((e) => Criterion.fromJson(e as Map)) - .toList(), - sourceSpreadsheetId: json['sourceSpreadsheetId'] as String?, - ); - } - - Map toJson() { - return { - 'courseId': courseId, - 'courseWorkId': courseWorkId, - 'id': id, - 'creationTime': creationTime, - 'updateTime': updateTime, - 'criteria': criteria?.map((e) => e.toJson()).toList(), - 'sourceSpreadsheetId': sourceSpreadsheetId, - }; - } -} - -// Criterion Bean (Used in Rubric) -class Criterion { - String? criterionId; - String? description; - List? levels; - - Criterion({this.criterionId, this.description, this.levels}); - - factory Criterion.fromJson(Map json) { - return Criterion( - criterionId: json['criterionId'] as String?, - description: json['description'] as String?, - levels: (json['levels'] as List?) - ?.map((e) => Level.fromJson(e as Map)) - .toList(), - ); - } - - Map toJson() { - return { - 'criterionId': criterionId, - 'description': description, - 'levels': levels?.map((e) => e.toJson()).toList(), - }; - } -} - -// Level Bean (Used in Criterion) -class Level { - String? levelId; - String? description; - String? title; - double? points; - - Level({this.levelId, this.description, this.title, this.points}); - - factory Level.fromJson(Map json) { - return Level( - levelId: json['levelId'] as String?, - description: json['description'] as String?, - title: json['title'] as String?, - points: (json['points'] as num?)?.toDouble(), - ); - } - - Map toJson() { - return { - 'levelId': levelId, - 'description': description, - 'title': title, - 'points': points, - }; - } -} - -//Enum for CourseState -enum CourseState { - COURSE_STATE_UNSPECIFIED, - ACTIVE, - ARCHIVED, - PROVISIONED, - DECLINED -} - -//Enum for CourseWorkState -enum CourseWorkState { - COURSE_WORK_STATE_UNSPECIFIED, - PUBLISHED, - DRAFT, - DELETED -} - -//Enum for CourseWorkType -enum CourseWorkType { - COURSE_WORK_TYPE_UNSPECIFIED, - ASSIGNMENT, - SHORT_ANSWER_QUESTION, - MULTIPLE_CHOICE_QUESTION -} - -//Enum for AssigneeMode -enum AssigneeMode { - ASSIGNEE_MODE_UNSPECIFIED, - ALL_STUDENTS, - INDIVIDUAL_STUDENTS -} - -//Enum for SubmissionModificationMode -enum SubmissionModificationMode { - SUBMISSION_MODIFICATION_MODE_UNSPECIFIED, - MODIFIABLE_UNTIL_TURNED_IN, - MODIFIABLE_AFTER_TURNED_IN -} - -//Enum for PreviewVersion -enum PreviewVersion { PREVIEW_VERSION_UNSPECIFIED, PUBLISHED_VERSION } diff --git a/team_a/teamA/lib/Controller/html_converter.dart b/team_a/teamA/lib/Controller/html_converter.dart deleted file mode 100644 index 403ee8c2..00000000 --- a/team_a/teamA/lib/Controller/html_converter.dart +++ /dev/null @@ -1,17 +0,0 @@ -class HtmlConverter -{ - - // Convert string by replacing common HTML tags. - static String convert(String htmlString) { - return htmlString.replaceAll('

', '\n') - .replaceAll('

', '\n') - .replaceAll('
  • ', '\n') - .replaceAll('
  • ', '\n') - .replaceAll('
      ', '\n') - .replaceAll('
    ', '\n') - .replaceAll('', '') - .replaceAll('', '') - .replaceAll('', '') - .replaceAll('', ''); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Controller/main_controller.dart b/team_a/teamA/lib/Controller/main_controller.dart deleted file mode 100644 index e53faad7..00000000 --- a/team_a/teamA/lib/Controller/main_controller.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:learninglens_app/beans/course.dart'; - -class MainController { - // Singleton instance - static final MainController _instance = MainController._internal(); - // Singleton accessor - factory MainController() { - return _instance; - } - // Internal constructor - MainController._internal(); - static bool isLoggedIn = false; - // final llm = LlmApi(dotenv.env['PERPLEXITY_API_KEY']!); - final ValueNotifier isUserLoggedInNotifier = ValueNotifier(false); - Course? selectedCourse; - String? username; - - -} diff --git a/team_a/teamA/lib/Controller/xml_converter.dart b/team_a/teamA/lib/Controller/xml_converter.dart deleted file mode 100644 index c2559ff1..00000000 --- a/team_a/teamA/lib/Controller/xml_converter.dart +++ /dev/null @@ -1,141 +0,0 @@ -import 'package:collection/collection.dart'; -import 'html_converter.dart'; -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; -import 'package:learninglens_app/beans/question.dart'; -import 'package:learninglens_app/beans/answer.dart'; - -// Static utility class for Moodle XML related functions. -class XmlConverter { - - static const cdata1 = ''; - - // Convert a populated Quiz object into an XML Document. - // - // To get the XML String, use XmlDocument.toXmlString() - static XmlDocument convertQuizToXml(Quiz quiz, [bool? toMoodle]) { - bool convertForMoodle = toMoodle ?? false; - final builder = XmlBuilder(); - builder.processing('xml', 'version="1.0" encoding="UTF-8"'); - builder.element(XmlConsts.quiz, nest: () { - // build category dummy node - builder.element(XmlConsts.name, nest: quiz.name ?? 'Unnamed Quiz'); - builder.element(XmlConsts.description, nest: quiz.description ?? 'No description'); - builder.element(XmlConsts.question, nest: () { - builder.attribute(XmlConsts.type, 'category'); - builder.element('category', nest: () { - builder.element(XmlConsts.text, nest: '\$course\$/top/LLM-Generated'); - }); - }); - for (Question question in quiz.questionList) { - builder.element(XmlConsts.question, nest: () { - // question type - builder.attribute(XmlConsts.type, question.type); - // question name - builder.element(XmlConsts.name, nest: () { - if (convertForMoodle) { - builder.element(XmlConsts.text, nest: getShortenedDesc(question.questionText)); - } else { - builder.element(XmlConsts.text, nest: question.name); - } - }); - // question text - builder.element(XmlConsts.questiontext, nest: () { - builder.attribute(XmlConsts.format, XmlConsts.html); - builder.element(XmlConsts.text, nest: () { - builder.cdata(question.questionText); - }); - }); - // general feedback - if (question.generalFeedback != null) { - builder.element(XmlConsts.generalfeedback, nest: () { - builder.attribute(XmlConsts.format, XmlConsts.html); - builder.element(XmlConsts.text, nest: () { - builder.cdata(question.generalFeedback!); - }); - }); - } - // default grade - if (question.defaultGrade != null) { - builder.element(XmlConsts.defaultgrade, nest: question.defaultGrade); - } - // response format - if (question.responseFormat != null) { - builder.element(XmlConsts.responseformat, nest: question.responseFormat); - } - // response required - if (question.responseRequired != null) { - builder.element(XmlConsts.responserequired, nest: question.responseRequired); - } - // attachments required - if (question.attachmentsRequired != null) { - builder.element(XmlConsts.attachmentsrequired, nest: question.attachmentsRequired); - } - // response template - if (question.responseTemplate != null) { - builder.element(XmlConsts.responsetemplate, nest: () { - builder.cdata(question.responseTemplate!); - }); - } - // grader info - if (question.graderInfo != null) { - builder.element(XmlConsts.graderinfo, nest: () { - builder.attribute(XmlConsts.format, XmlConsts.html); - builder.element(XmlConsts.text, nest: () { - builder.cdata(question.graderInfo!); - }); - }); - } - // answers - for (Answer answer in question.answerList) { - builder.element(XmlConsts.answer, nest: () { - builder.attribute(XmlConsts.fraction, answer.fraction); - builder.element(XmlConsts.text, nest: answer.answerText); - if (answer.feedbackText != null) { - builder.element(XmlConsts.feedback, nest: () { - builder.element(XmlConsts.text, nest: answer.feedbackText); - }); - } - }); - } - }); - } - builder.element(XmlConsts.promptUsed, nest: quiz.promptUsed); - }); - return builder.buildDocument(); - } - - static String getShortenedDesc(String description) { - int charLimit = 30; - String desc = HtmlConverter.convert(description.trim()); - desc = desc.replaceAll('\n', ''); - if (desc.length <= charLimit) return desc; - desc = desc.substring(0, charLimit); - desc = desc.substring(0, desc.lastIndexOf(' ')); - desc = "$desc..."; - return desc; - } - - // Split a quiz into list of smaller quizzes - static List splitQuiz(Quiz quiz) { - int qperq; - switch (quiz.questionList.first.type) { - case 'essay': - qperq = 1; - break; - case 'multichoice': - case 'truefalse': - case 'shortanswer': - default: - qperq = 4; - } - List> splitQuizzes = quiz.questionList.slices(qperq).toList(); - List quizList = []; - for (List q in splitQuizzes) { - quizList.add(Quiz(questionList: q)); - } - return quizList; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/TestFiles/allThree.xml b/team_a/teamA/lib/TestFiles/allThree.xml deleted file mode 100644 index d311751f..00000000 --- a/team_a/teamA/lib/TestFiles/allThree.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Pythagorean Theorem - - - - - Question 1 - - - The Pythagorean Theorem states that in a right triangle, the square of the length of the hypotenuse is equal to the sum of the squares of the lengths of the other two sides. - - - True - - Correct! This is the definition of the Pythagorean Theorem. - - - - False - - Incorrect. This statement is indeed true. - - - - - - Question 2 - - - In a right triangle, the Pythagorean Theorem can only be applied if the triangle is isosceles. - - - True - - Incorrect. The Pythagorean Theorem applies to all right triangles, not just isosceles ones. - - - - False - - Correct! The theorem applies to any right triangle. - - - - - - Question 3 - - - The lengths of the sides of a right triangle can be represented by the formula a² + b² = c², where c is the hypotenuse. - - - True - - Correct! This is the Pythagorean theorem representation. - - - - False - - Incorrect. This statement accurately describes the theorem. - - - - - - Question 4 - - - The Pythagorean Theorem is applicable only in three-dimensional geometry. - - - True - - Incorrect. The Pythagorean Theorem is specific to two-dimensional right triangles. - - - - False - - Correct! It is applicable only in two dimensions. - - - - - - Question 5 - - - Which of the following is the correct equation according to the Pythagorean Theorem? - - - a² + b² = c² - - Correct! This is the fundamental equation of the Pythagorean Theorem. - - - - a² - b² = c² - - Incorrect. This is not the correct application of the theorem. - - - - c² = a + b - - Incorrect. This does not represent the Pythagorean Theorem. - - - - a + b = c - - Incorrect. This does not describe the relationship between the sides of a right triangle. - - - - - - Question 6 - - - If a right triangle has legs of lengths 3 and 4, what is the length of the hypotenuse? - - - 5 - - Correct! Using the Pythagorean Theorem: 3² + 4² = 9 + 16 = 25, so c = √25 = 5. - - - - 7 - - Incorrect. This does not follow from the theorem. - - - - 6 - - Incorrect. This is not the correct calculation based on the theorem. - - - - 8 - - Incorrect. This does not represent the hypotenuse length. - - - - - - Question 7 - - - What is the Pythagorean Theorem used for in mathematics? - - - To calculate the length of a side in a right triangle - - Correct! The theorem is used to find unknown side lengths in right triangles. - - - - diff --git a/team_a/teamA/lib/TestFiles/multipleChoice.xml b/team_a/teamA/lib/TestFiles/multipleChoice.xml deleted file mode 100644 index 5beff788..00000000 --- a/team_a/teamA/lib/TestFiles/multipleChoice.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - Pythagorean Theorem - - - - Pythagorean Theorem Question 1 - What is the formula for the Pythagorean theorem? - a² + b² = c²Correct! This is the standard formula representing the Pythagorean theorem. - a² - b² = c²Incorrect. This formula is not correct for the Pythagorean theorem. - 2a + b = cIncorrect. This does not represent the Pythagorean theorem. - a + b = cIncorrect. This is not the correct formula for the theorem. - - - - Pythagorean Theorem Question 2 - If one leg of a right triangle is 6 and the other is 8, what is the length of the hypotenuse? - 10Correct! Using the Pythagorean theorem: √(6² + 8²) = √(36 + 64) = √100 = 10. - 12Incorrect. The correct calculation gives a hypotenuse of 10. - 14Incorrect. This does not follow from the Pythagorean theorem. - 8Incorrect. This is one of the leg lengths, not the hypotenuse. - - - - Pythagorean Theorem Question 3 - What type of triangle does the Pythagorean theorem apply to? - Right triangleCorrect! The Pythagorean theorem is specific to right triangles. - Equilateral triangleIncorrect. The theorem does not apply to equilateral triangles. - Isosceles triangleIncorrect. The theorem is not applicable to isosceles triangles unless they are right triangles. - Scalene triangleIncorrect. The theorem is specifically for right triangles. - - - - Pythagorean Theorem Question 4 - If the hypotenuse is 13 and one leg is 5, what is the length of the other leg? - 12Correct! Using the theorem: √(13² - 5²) = √(169 - 25) = √144 = 12. - 10Incorrect. This does not follow the correct calculation. - 8Incorrect. This is not the correct length derived from the theorem. - 6Incorrect. This value does not satisfy the Pythagorean theorem. - - - - Pythagorean Theorem Question 5 - Which of the following is a Pythagorean triple? - 3, 4, 5Correct! 3² + 4² = 5², thus forming a Pythagorean triple. - 5, 12, 13Incorrect. This is also a Pythagorean triple, but not the only one. - 7, 24, 25Incorrect. This is a valid Pythagorean triple as well. - 2, 2, 3Incorrect. This does not form a Pythagorean triple. - - - - Pythagorean Theorem Question 6 - In a right triangle, if the lengths of the legs are equal, what type of triangle is it? - Isosceles right triangleCorrect! An isosceles right triangle has two equal legs and one right angle. - Equilateral triangleIncorrect. An equilateral triangle has all sides equal, not just the legs. - Scalene triangleIncorrect. A scalene triangle has all sides of different lengths. - Obtuse triangleIncorrect. An obtuse triangle has one angle greater than 90 degrees. - - - - Pythagorean Theorem Question 7 - If a triangle has sides of lengths 8, 15, and 17, is it a right triangle? - YesCorrect! 8² + 15² = 17² verifies that it is a right triangle. - NoIncorrect. This combination does form a right triangle. - - - - Pythagorean Theorem Question 8 - What is the relationship of the lengths of the sides in a right triangle? - The square of the hypotenuse is equal to the sum of the squares of the legs.Correct! This defines the Pythagorean theorem. - The sum of all sides is equal to 180 degrees.Incorrect. This refers to the sum of angles in any triangle, not the Pythagorean theorem. - The legs are always equal in length.Incorrect. This is not true for all right triangles. - Each angle must be acute.Incorrect. A right triangle has one right angle. - - - - Pythagorean Theorem Question 9 - Can the Pythagorean theorem be used in three-dimensional geometry? - No, it only applies to two-dimensional triangles.Incorrect. It applies specifically to two-dimensional right triangles. - Yes, but in a modified form.Correct! The theorem can be adapted for three-dimensional cases using the distance formula. - - - - Pythagorean Theorem Question 10 - What do we call a triangle that satisfies the Pythagorean theorem? - Pythagorean triangleCorrect! Triangles that satisfy this relationship are known as Pythagorean triangles. - Right triangleIncorrect. While all Pythagorean triangles are right triangles, not all right triangles are referred to specifically as Pythagorean triangles. - Acute triangleIncorrect. An acute triangle has all angles less than 90 degrees, which does not satisfy the theorem. - Obtuse triangleIncorrect. An obtuse triangle has one angle greater than 90 degrees, which does not satisfy the theorem. - - diff --git a/team_a/teamA/lib/TestFiles/shortAnswer.xml b/team_a/teamA/lib/TestFiles/shortAnswer.xml deleted file mode 100644 index 81adce24..00000000 --- a/team_a/teamA/lib/TestFiles/shortAnswer.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Pythagorean Theorem - - - - Pythagorean Theorem Question 1 - What is the length of the hypotenuse of a right triangle if the lengths of the two legs are 9 and 12? - 15 - √225 - - - - Pythagorean Theorem Question 2 - If the hypotenuse of a right triangle is 10 and one leg is 6, what is the length of the other leg? - 8 - √(10² - 6²) - - - - Pythagorean Theorem Question 3 - Provide an example of a Pythagorean triple. - 3, 4, 5 - 5, 12, 13 - 7, 24, 25 - - diff --git a/team_a/teamA/lib/TestFiles/trueFalse.xml b/team_a/teamA/lib/TestFiles/trueFalse.xml deleted file mode 100644 index dd7fefbb..00000000 --- a/team_a/teamA/lib/TestFiles/trueFalse.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - Pythagorean Theorem - - - - Pythagorean Theorem Question 1 - The Pythagorean theorem states that in a right triangle, the square of the hypotenuse is equal to the sum of the squares of the other two sides. - TrueCorrect! This is the fundamental statement of the Pythagorean theorem. - FalseIncorrect. The Pythagorean theorem indeed states that the square of the hypotenuse is equal to the sum of the squares of the other two sides. - - - - Pythagorean Theorem Question 2 - For a right triangle with legs of lengths 3 and 4, the length of the hypotenuse is 5. - TrueCorrect! Using the Pythagorean theorem: 3² + 4² = 9 + 16 = 25, so the hypotenuse is √25 = 5. - FalseIncorrect. The hypotenuse is indeed 5, as verified by the Pythagorean theorem. - - - - Pythagorean Theorem Question 3 - The Pythagorean theorem can only be used for triangles with one right angle. - TrueCorrect! The Pythagorean theorem applies specifically to right triangles. - FalseIncorrect. The theorem is specifically applicable only to right triangles. - - - - Pythagorean Theorem Question 4 - The formula a² + b² = c² can be rearranged to find any side of a right triangle. - TrueCorrect! You can rearrange the formula to solve for a, b, or c as needed. - FalseIncorrect. The formula can indeed be rearranged to solve for any side of the triangle. - - - - Pythagorean Theorem Question 5 - The lengths of the sides of a right triangle must always be integers. - TrueIncorrect. While there are integer solutions (like 3, 4, 5), sides can also be non-integers. - FalseCorrect! The sides of a right triangle can be any real numbers, not just integers. - - - - Pythagorean Theorem Question 6 - If a triangle has sides of lengths 5, 12, and 13, it is a right triangle. - TrueCorrect! 5² + 12² = 25 + 144 = 169, which is 13², confirming it is a right triangle. - FalseIncorrect. The triangle with these side lengths is indeed a right triangle by the Pythagorean theorem. - - - - Pythagorean Theorem Question 7 - The hypotenuse is always the longest side in a right triangle. - TrueCorrect! By definition, the hypotenuse is the longest side of a right triangle. - FalseIncorrect. The hypotenuse is always the longest side in a right triangle. - - - - Pythagorean Theorem Question 8 - The Pythagorean theorem can be extended to non-right triangles. - TrueIncorrect. The Pythagorean theorem specifically applies to right triangles only. - FalseCorrect! The theorem is not applicable to non-right triangles. - - - - Pythagorean Theorem Question 9 - The Pythagorean theorem can be used to derive the distance formula in coordinate geometry. - TrueCorrect! The distance formula is derived from the Pythagorean theorem in the context of the coordinate plane. - FalseIncorrect. The distance formula is indeed based on the Pythagorean theorem. - - - - Pythagorean Theorem Question 10 - If one leg of a right triangle is 8 and the hypotenuse is 10, the length of the other leg can be found using the Pythagorean theorem. - TrueCorrect! You can find the other leg's length by using the formula: 10² - 8² = c². - FalseIncorrect. The other leg's length can be calculated using the Pythagorean theorem. - - \ No newline at end of file diff --git a/team_a/teamA/lib/Views/about_page.dart b/team_a/teamA/lib/Views/about_page.dart deleted file mode 100644 index c7f9822b..00000000 --- a/team_a/teamA/lib/Views/about_page.dart +++ /dev/null @@ -1,70 +0,0 @@ -import "package:flutter/material.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; - -/// -/// Template for views -/// Need to change the class name to the name based on the view you -/// are creating to include the constructor as well. -/// Need to change the class that extends State as well. Make sure -/// that the createState function returns the same name. -/// -/// The CustomAppBar is already included, but you will need to update -/// the title string. -/// -/// The content for the page begins in the children array. There is -/// a single text box as a place holder. -/// -/// To add your view to the rest of the app, you will have to add it -/// to the dashboard.dart file. On line ~213, there is a List called -/// buttonData. You will need to update the 'onPressed' section with -/// your new template. You can see examples that Derek has already -/// done on other buttons. -/// -class AboutPage extends StatefulWidget{ - AboutPage(); - - @override - State createState(){ - return _TemplateState(); - } -} - -class _TemplateState extends State{ - - @override - Widget build(BuildContext context){ - return Scaffold( - appBar: CustomAppBar( - title: 'About Learning Lens', - onRefresh: () { - // Add refresh logic here - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '' - ), - body: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children:[ - // Add Content here - Padding( - padding: EdgeInsets.all(16.0), // Adjust padding as needed - child: Text( - 'Learning Lens v2.0 by Team EduLense', - style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), - textAlign: TextAlign.left, - ), - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), // Adds left and right padding - child: Text( - 'Learning Lens is an application developed by students at the University of Maryland Global Campus in the SWEN 670 Software Engineering Capstone course. It originated in the Fall 2024 student cohort and has been further developed by the students of Spring 2025. Some features and ideas were also developed from an application developed by a Fall 2024 cohort team named EvaluAI.\n\nLearning Lens is intended to be used by educators who teach students who utilize Learning Management Systems (LMS) like Moodle and Google Classroom. The application allows teachers to automatically generate quizzes, essay assignments, and lesson plans using various Artificial Intelligence platforms. There are also added features for Individual Education Plans and advanced analytics.\n\nSpring 2025 Contributors Under Team Name "EduLense": Nathaniel Boyd, Daniel Diep, Dinesh Ghimire, Andrew Hammes, Dusty McKinnon, Derek Sappington, and Kevin Watts', - style: TextStyle(fontSize: 15), - ), - ), - ] - ) - ) - ); - } -} diff --git a/team_a/teamA/lib/Views/analytics_page.dart b/team_a/teamA/lib/Views/analytics_page.dart deleted file mode 100644 index 94af9bb1..00000000 --- a/team_a/teamA/lib/Views/analytics_page.dart +++ /dev/null @@ -1,1280 +0,0 @@ -import 'dart:io' show File; // For non-web file I/O -import 'package:flutter/foundation.dart' show kIsWeb; -import 'package:flutter/material.dart'; -import 'package:file_picker/file_picker.dart'; // For file saving on non-web platforms -import 'package:learninglens_app/beans/question_stat_type.dart'; -import 'package:learninglens_app/stub/html_stub.dart' - if (dart.library.html) 'dart:html' as html; - -import 'package:pdf/widgets.dart' as pw; // PDF package -import 'package:excel/excel.dart'; // Excel package - -// Import the LMS services using prefixes so that type checks work correctly. -import 'package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart' - as moodle; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; - -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/quiz_type.dart'; - -import 'package:learninglens_app/Views/dashboard.dart'; -import 'package:learninglens_app/Views/user_settings.dart'; - -// Import the APIs for the Learning Lens Model (LLM). -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'dart:convert'; - -/// Enum to represent export formats. -enum ExportFormat { pdf, excel } - -/// AnalyticsPage displays the Analytics Dashboard where teachers can: -/// - View overall analytics data (live data fetched from the LMS) -/// - Generate a detailed report for essay assignments only (quizzes are omitted) -/// - Export the generated report as a valid PDF or Excel file -/// (using proper PDF/Excel libraries) -/// - View tables in fixed-height containers with visible scrollbars. -/// -/// When a student is clicked in the breakdown table, a detail panel appears -/// on the right showing that student's assignment details (non-editable). -/// -/// A simple wrapper to hold either an essay assignment or a quiz. -/// The `type` property distinguishes between the two. -class Assessment { - final dynamic assessment; // Either an Assignment (essay) or a Quiz. - final String type; // "essay" or "quiz" - - Assessment({required this.assessment, required this.type}); - - String get name { - if (type == "essay") { - return (assessment as Assignment).name; - } else { - return (assessment as Quiz).name ?? 'Unknown Quiz'; - } - } - - int get id { - if (type == "essay") { - return (assessment as Assignment).id ?? 0; - } else { - return (assessment as Quiz).id ?? 0; - } - } -} - -class AnalyticsPage extends StatefulWidget { - const AnalyticsPage({Key? key}) : super(key: key); - - @override - _AnalyticsPageState createState() => _AnalyticsPageState(); -} - -class _AnalyticsPageState extends State { - final lmsService = LmsFactory.getLmsService(); - // Live analytics data fetched from the LMS. - Map? analyticsData; - bool isLoading = false; - String errorMsg = ''; - - // Live data for dropdowns. - List _coursesData = []; - List _assessmentsData = []; - List _participantsData = []; - - // Selections from dropdowns. - Course? _selectedCourse; - String? _selectedSubject; - Assessment? _selectedAssessment; - - // Student breakdown report built from live LMS participant data. - List> _studentBreakdown = []; - Map? _selectedStudent; - - // For quiz assessments, question breakdown data. - List _questionBreakdown = []; - - // Scroll controllers for tables. - late ScrollController _verticalStudentController; - late ScrollController _horizontalStudentController; - late ScrollController _verticalQuestionController; - late ScrollController _horizontalQuestionController; - - // AI Analysis data. - List> _aiAnalysisData = []; - bool _isAnalyzingAI = false; - - @override - void initState() { - super.initState(); - _verticalStudentController = ScrollController(); - _horizontalStudentController = ScrollController(); - _verticalQuestionController = ScrollController(); - _horizontalQuestionController = ScrollController(); - _fetchAnalyticsData(); - } - - @override - void dispose() { - _verticalStudentController.dispose(); - _horizontalStudentController.dispose(); - _verticalQuestionController.dispose(); - _horizontalQuestionController.dispose(); - super.dispose(); - } - - // --------------------------------------------------------------------------- - // _fetchAnalyticsData: - // Fetches live data from the LMS (courses, initial quizzes/essays). - // --------------------------------------------------------------------------- - Future _fetchAnalyticsData() async { - setState(() { - isLoading = true; - errorMsg = ''; - }); - try { - _coursesData = await lmsService.getUserCourses(); - int totalCourses = _coursesData.length; - if (_coursesData.isNotEmpty) { - _selectedCourse = _coursesData.first; - _selectedSubject = _selectedCourse!.subject ?? "General"; - // Fetch essays. - List essayList = - await lmsService.getEssays(_selectedCourse!.id); - // Fetch quizzes (if available). - List quizList = []; - try { - quizList = await (lmsService as moodle.MoodleLmsService) - .getQuizzes(_selectedCourse!.id); - } catch (e) { - print("getQuizzes not available or failed: $e"); - } - // Combine them into one list - _assessmentsData = [ - ...essayList.map((a) => Assessment(assessment: a, type: "essay")), - ...quizList.map((q) => Assessment(assessment: q, type: "quiz")) - ]; - if (_assessmentsData.isNotEmpty) { - _selectedAssessment = _assessmentsData.first; - } - } - setState(() { - analyticsData = { - 'source': lmsService is moodle.MoodleLmsService - ? 'Moodle' - : 'Google Classroom', - 'totalCourses': totalCourses, - 'studentPerformance': 'Live Performance Data', - 'iepProgress': 'Live IEP Data', - 'courseEngagement': 'Live Engagement Metrics', - }; - }); - } catch (e) { - setState(() { - errorMsg = 'Failed to load analytics data: $e'; - }); - } finally { - setState(() { - isLoading = false; - }); - } - } - - // --------------------------------------------------------------------------- - // _generateReport: - // Builds the student breakdown for the currently selected assessment only - // (i.e., one quiz or essay). - // --------------------------------------------------------------------------- - Future _generateReport() async { - if (_selectedCourse == null) return; - setState(() { - isLoading = true; - errorMsg = ''; - _studentBreakdown.clear(); - _questionBreakdown.clear(); - _selectedStudent = null; - }); - - try { - if (isQuiz()) { - // Grab participants for this quiz. - int quizId = _selectedAssessment!.assessment.id; - _participantsData = await (lmsService as moodle.MoodleLmsService) - .getQuizGradesForParticipants( - _selectedCourse!.id.toString(), quizId); - // Filter out non-students, if needed. - _participantsData = _participantsData - .where((i) => i.roles.contains('student')) - .toList(); - } else if (isEssay()) { - // Grab participants for this essay. - int assignmentId = _selectedAssessment!.assessment.id; - _participantsData = await (lmsService as moodle.MoodleLmsService) - .getEssayGradesForParticipants( - _selectedCourse!.id.toString(), assignmentId); - } else { - throw Exception("Unsupported Assessment Type"); - } - - // Build the table shown in the "Student Breakdown" section. - getStudentBreakdown(_participantsData); - - // If it's a quiz, also fetch the question breakdown. - await _fetchQuestionBreakdown(); - } catch (e) { - setState(() { - errorMsg = 'Failed to generate report: $e'; - }); - } finally { - setState(() { - isLoading = false; - }); - } - } - - // --------------------------------------------------------------------------- - // getStudentBreakdown: - // Builds `_studentBreakdown` from the given participant list for the currently - // selected assessment only. - // --------------------------------------------------------------------------- - void getStudentBreakdown(List participantsData) { - _studentBreakdown = participantsData.map((participant) { - double? grade = participant.avgGrade; - String displayGrade = (grade != null) ? '${grade.toInt()}%' : '0%'; - return { - 'id': participant.id, - 'studentName': participant.fullname, - 'avgGrade': displayGrade, - 'classRank': 0, - }; - }).toList(); - - // Sort descending by numeric grade. - _studentBreakdown.sort((a, b) { - int aGrade = int.tryParse(a['avgGrade'].replaceAll('%', '')) ?? 0; - int bGrade = int.tryParse(b['avgGrade'].replaceAll('%', '')) ?? 0; - return bGrade.compareTo(aGrade); - }); - - // Assign a 1-based rank. - for (int i = 0; i < _studentBreakdown.length; i++) { - _studentBreakdown[i]['classRank'] = i + 1; - } - } - - // --------------------------------------------------------------------------- - // _saveReport: - // Exports the generated report as PDF or Excel (only for the single selected assessment). - // --------------------------------------------------------------------------- - Future _saveReport() async { - final format = await _chooseExportFormat(); - if (format == null) return; - String extension = (format == ExportFormat.pdf) ? 'pdf' : 'xlsx'; - String defaultName = 'my_report.$extension'; - - if (kIsWeb) { - // Build bytes. - List bytes = (format == ExportFormat.pdf) - ? await _exportReportAsPdf() - : await _exportReportAsExcel(); - final blob = html.Blob([bytes]); - final url = html.Url.createObjectUrlFromBlob(blob); - final anchor = html.AnchorElement(href: url) - ..style.display = 'none' - ..download = defaultName; - html.document.body?.append(anchor); - anchor.click(); - anchor.remove(); - html.Url.revokeObjectUrl(url); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: - Text('Report exported as $extension via browser download.')), - ); - } else { - final savePath = await _pickFileLocation(defaultName); - if (savePath == null) return; - try { - List bytes = (format == ExportFormat.pdf) - ? await _exportReportAsPdf() - : await _exportReportAsExcel(); - final file = File(savePath); - await file.writeAsBytes(bytes); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Report saved as $extension at:\n$savePath')), - ); - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to save report: $e')), - ); - } - } - } - - // --------------------------------------------------------------------------- - // _chooseExportFormat: - // Prompts the user to select whether to export the report as PDF or Excel. - // --------------------------------------------------------------------------- - Future _chooseExportFormat() async { - return showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Select Export Format'), - content: const Text( - 'Would you like to export the report as PDF or Excel?'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context, ExportFormat.pdf), - child: const Text('PDF'), - ), - TextButton( - onPressed: () => Navigator.pop(context, ExportFormat.excel), - child: const Text('Excel'), - ), - TextButton( - onPressed: () => Navigator.pop(context, null), - child: const Text('Cancel'), - ), - ], - ); - }, - ); - } - - // --------------------------------------------------------------------------- - // _exportReportAsPdf: - // Uses the pdf package to generate a PDF document containing the student breakdown - // and, if applicable, the question breakdown. - // --------------------------------------------------------------------------- - Future> _exportReportAsPdf() async { - final pdf = pw.Document(); - pdf.addPage( - pw.MultiPage( - build: (pw.Context context) { - List widgets = []; - - // Dynamic export for student breakdown. - if (_studentBreakdown.isNotEmpty) { - // Dynamically capture all keys as headers. - final studentHeaders = _studentBreakdown.first.keys.toList(); - // Map each student to a list of string values. - final studentData = _studentBreakdown - .map((student) => - student.values.map((value) => value.toString()).toList()) - .toList(); - widgets.add(pw.Header( - level: 0, child: pw.Text("Student Breakdown Report"))); - widgets.add( - pw.Table.fromTextArray( - headers: studentHeaders, - data: studentData, - ), - ); - } - - // Export question breakdown (only for quizzes). - if (isQuiz() && _questionBreakdown.isNotEmpty) { - widgets.add(pw.SizedBox(height: 20)); - widgets - .add(pw.Header(level: 0, child: pw.Text("Question Breakdown"))); - widgets.add( - pw.Table.fromTextArray( - headers: [ - 'Q#', - 'Question Type', - 'Question', - '% Answered Correct', - '# Correct', - '# Incorrect', - '# Total Attempts' - ], - data: _questionBreakdown - .map((q) => [ - q.id.toString(), - q.questionType, - q.questionText, - "${computePercentCorrect(q).toStringAsFixed(2)}%", - q.numCorrect.toString(), - q.numIncorrect.toString(), - q.totalAttempts.toString(), - ]) - .toList(), - ), - ); - } - return widgets; - }, - ), - ); - return pdf.save(); - } - - // --------------------------------------------------------------------------- - // _exportReportAsExcel: - // Uses the excel package to generate an Excel file containing the student breakdown - // and, if applicable, the question breakdown. - // --------------------------------------------------------------------------- - Future> _exportReportAsExcel() async { - var excel = Excel.createExcel(); - - // Dynamic export for student breakdown. - Sheet studentSheet = excel['Student Breakdown']; - if (_studentBreakdown.isNotEmpty) { - // Get headers dynamically from the first map. - var studentHeaders = _studentBreakdown.first.keys.toList(); - studentSheet.appendRow(studentHeaders); - // Append each student row by mapping the values to strings. - for (var student in _studentBreakdown) { - studentSheet.appendRow( - student.values.map((value) => value.toString()).toList()); - } - } - - // Export question breakdown if it's a quiz. - if (isQuiz() && _questionBreakdown.isNotEmpty) { - Sheet questionSheet = excel['Question Breakdown']; - questionSheet.appendRow([ - 'Q#', - 'Question Type', - 'Question', - '% Answered Correct', - '# Correct', - '# Incorrect', - '# Total Attempts' - ]); - for (var q in _questionBreakdown) { - questionSheet.appendRow([ - q.id, - q.questionType, - q.questionText, - "${computePercentCorrect(q).toStringAsFixed(2)}%", - q.numCorrect, - q.numIncorrect, - q.totalAttempts, - ]); - } - } - - return excel.encode()!; - } - - // --------------------------------------------------------------------------- - // _pickFileLocation: - // For non-web platforms, uses FilePicker to let the user choose a save location. - // On web, file saving is handled via an AnchorElement. - // --------------------------------------------------------------------------- - Future _pickFileLocation(String defaultName) async { - if (kIsWeb) return null; - final result = await FilePicker.platform.saveFile( - dialogTitle: 'Save Report', - fileName: defaultName, - ); - return result; - } - - // --------------------------------------------------------------------------- - // Export AI Analysis Functions - // --------------------------------------------------------------------------- - Future _exportAIAnalysis() async { - final format = await _chooseExportFormat(); - if (format == null) return; - String extension = (format == ExportFormat.pdf) ? 'pdf' : 'xlsx'; - String defaultName = 'ai_analysis_report.$extension'; - - if (kIsWeb) { - List bytes = (format == ExportFormat.pdf) - ? await _exportAIAnalysisAsPdf() - : await _exportAIAnalysisAsExcel(); - final blob = html.Blob([bytes]); - final url = html.Url.createObjectUrlFromBlob(blob); - final anchor = html.AnchorElement(href: url) - ..style.display = 'none' - ..download = defaultName; - html.document.body?.append(anchor); - anchor.click(); - anchor.remove(); - html.Url.revokeObjectUrl(url); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'AI Analysis exported as $extension via browser download.')), - ); - } else { - final savePath = await _pickFileLocation(defaultName); - if (savePath == null) return; - try { - List bytes = (format == ExportFormat.pdf) - ? await _exportAIAnalysisAsPdf() - : await _exportAIAnalysisAsExcel(); - final file = File(savePath); - await file.writeAsBytes(bytes); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('AI Analysis saved as $extension at:\n$savePath')), - ); - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to save AI Analysis: $e')), - ); - } - } - } - - Future> _exportAIAnalysisAsPdf() async { - final pdf = pw.Document(); - pdf.addPage( - pw.MultiPage( - build: (pw.Context context) { - if (_aiAnalysisData.isEmpty) { - return [ - pw.Center(child: pw.Text("No AI Analysis Data available.")) - ]; - } - final headers = ['Student', 'Status', 'Comments']; - final data = _aiAnalysisData - .map((row) => [ - row['Student']?.toString() ?? '', - row['Status']?.toString() ?? '', - row['Comments']?.toString() ?? '', - ]) - .toList(); - return [ - pw.Header(level: 0, child: pw.Text("AI Analysis Summary")), - pw.Table.fromTextArray(headers: headers, data: data), - ]; - }, - ), - ); - return pdf.save(); - } - - Future> _exportAIAnalysisAsExcel() async { - var excel = Excel.createExcel(); - Sheet sheet = excel['AI Analysis']; - sheet.appendRow(['Student', 'Status', 'Comments']); - for (var row in _aiAnalysisData) { - sheet.appendRow([ - row['Student']?.toString() ?? '', - row['Status']?.toString() ?? '', - row['Comments']?.toString() ?? '', - ]); - } - return excel.encode()!; - } - - // --------------------------------------------------------------------------- - // _buildReportForm: - // Displays dropdowns for selecting course, subject, and assessment, - // along with Generate and Export buttons. - // --------------------------------------------------------------------------- - Widget _buildReportForm() { - return Container( - width: 100, - padding: const EdgeInsets.all(16), - color: Colors.grey[200], - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Generate New Report', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), - const SizedBox(height: 8), - // Course dropdown. - DropdownButtonFormField( - value: _selectedCourse, - decoration: const InputDecoration(labelText: 'Course'), - items: _coursesData.map((course) { - return DropdownMenuItem( - value: course, - child: Text(course.fullName.isNotEmpty - ? course.fullName - : course.shortName), - ); - }).toList(), - onChanged: (val) async { - setState(() { - _selectedCourse = val; - _selectedSubject = val?.subject ?? "General"; - // Clear dependent tables when course changes. - _studentBreakdown.clear(); - _questionBreakdown.clear(); - _aiAnalysisData.clear(); - _selectedStudent = null; - }); - if (_selectedCourse != null) { - // Fetch essays and quizzes, then combine them. - List essays = - await lmsService.getEssays(_selectedCourse!.id); - List quizzes = []; - try { - quizzes = await (lmsService as dynamic) - .getQuizzes(_selectedCourse!.id); - } catch (e) { - print("getQuizzes not available or failed: $e"); - } - _assessmentsData = [ - ...essays - .map((a) => Assessment(assessment: a, type: "essay")), - ...quizzes.map((q) => Assessment(assessment: q, type: "quiz")) - ]; - if (_assessmentsData.isNotEmpty) { - _selectedAssessment = _assessmentsData.first; - } - setState(() {}); - } - }, - ), - // Subject dropdown. - if (_selectedCourse != null) - DropdownButtonFormField( - value: _selectedSubject, - decoration: const InputDecoration(labelText: 'Subject'), - items: [ - DropdownMenuItem( - value: _selectedSubject, - child: Text(_selectedSubject ?? "General"), - ) - ], - onChanged: (val) { - setState(() { - _selectedSubject = val; - // Optionally clear dependent tables if needed. - _studentBreakdown.clear(); - _questionBreakdown.clear(); - _aiAnalysisData.clear(); - _selectedStudent = null; - }); - }, - ), - // Assessment dropdown. - DropdownButtonFormField( - value: _selectedAssessment, - decoration: const InputDecoration(labelText: 'Assessment'), - items: _assessmentsData.map((assessment) { - return DropdownMenuItem( - value: assessment, - child: Text( - '${assessment.name} (${assessment.type.toUpperCase()})'), - ); - }).toList(), - onChanged: (val) { - setState(() { - _selectedAssessment = val; - // Clear question breakdown, student breakdown and AI analysis when assessment changes. - _questionBreakdown.clear(); - _studentBreakdown.clear(); - _aiAnalysisData.clear(); - _selectedStudent = null; - }); - }, - ), - const SizedBox(height: 12), - Row( - children: [ - ElevatedButton( - onPressed: _generateReport, - child: const Text('Generate'), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: _studentBreakdown.isNotEmpty ? _saveReport : null, - child: const Text('Export'), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: _studentBreakdown.isNotEmpty ? _analyzeReport : null, - child: _isAnalyzingAI - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Text('AI Analyze'), - ), - ], - ), - ], - ), - ); - } - - // --------------------------------------------------------------------------- - // _buildQuestionBreakdown: - // Displays the question breakdown table for quiz assessments. - // This is shown only when a quiz is selected. - // Here, each DataCell wraps its Text widget with an IntrinsicWidth widget - // to ensure that the column width adjusts to the largest text. - // Additionally, the entire table is wrapped in a FittedBox to scale down - // the table if the user has a smaller screen or they change their resolution. - // --------------------------------------------------------------------------- - Widget _buildQuestionBreakdown() { - if (isEssay()) { - return const SizedBox.shrink(); - } - if (_questionBreakdown.isEmpty) { - return const Center(child: Text('No question breakdown available.')); - } - return SizedBox( - height: 200, - child: Scrollbar( - thumbVisibility: true, - controller: _verticalQuestionController, - child: SingleChildScrollView( - controller: _verticalQuestionController, - scrollDirection: Axis.vertical, - child: Scrollbar( - thumbVisibility: true, - controller: _horizontalQuestionController, - notificationPredicate: (notification) => notification.depth == 2, - child: SingleChildScrollView( - controller: _horizontalQuestionController, - scrollDirection: Axis.horizontal, - // This is where the magic happens with the FittedBox and DataTable. - child: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.centerLeft, - child: DataTable( - columnSpacing: 12.0, - columns: const [ - DataColumn(label: Text('#')), - DataColumn(label: Text('Question Type')), - DataColumn(label: Text('Question')), - DataColumn(label: Text('% Answered Correct')), - DataColumn(label: Text('# Correct')), - DataColumn(label: Text('# Incorrect')), - DataColumn(label: Text('# Total Attempts')), - ], - rows: _questionBreakdown.map((q) { - return DataRow( - cells: [ - DataCell(IntrinsicWidth(child: Text(q.id.toString()))), - DataCell(IntrinsicWidth(child: Text(q.questionType))), - DataCell(IntrinsicWidth(child: Text(q.questionText))), - DataCell(IntrinsicWidth( - child: Text( - "${computePercentCorrect(q).toStringAsFixed(2)}%"))), - DataCell(IntrinsicWidth( - child: Text(q.numCorrect.toString()))), - DataCell(IntrinsicWidth( - child: Text(q.numIncorrect.toString()))), - DataCell(IntrinsicWidth( - child: Text(q.totalAttempts.toString()))), - ], - ); - }).toList(), - ), - ), - ), - ), - ), - ), - ); - } - - // --------------------------------------------------------------------------- - // _buildStudentTable: - // Returns ONLY the table of student data. The detail panel is separate. - // --------------------------------------------------------------------------- - Widget _buildStudentTable() { - if (_studentBreakdown.isEmpty && !isLoading) { - return const Center(child: Text('No student breakdown available.')); - } - if (isLoading) { - return const Center(child: CircularProgressIndicator()); - } - return SizedBox( - height: 300, - child: Scrollbar( - thumbVisibility: true, - controller: _verticalStudentController, - child: SingleChildScrollView( - controller: _verticalStudentController, - scrollDirection: Axis.vertical, - child: Scrollbar( - thumbVisibility: true, - controller: _horizontalStudentController, - notificationPredicate: (notification) => notification.depth == 2, - child: SingleChildScrollView( - controller: _horizontalStudentController, - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 12.0, - columns: const [ - DataColumn(label: Text('Student Name')), - DataColumn(label: Text('Average Grade')), - DataColumn(label: Text('Class Rank')), - ], - rows: _studentBreakdown.map((student) { - return DataRow( - cells: [ - DataCell( - InkWell( - onTap: () { - setState(() { - _selectedStudent = student; - }); - }, - child: Text( - student['studentName'].toString(), - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline, - ), - ), - ), - ), - DataCell(Text(student['avgGrade'].toString())), - DataCell(Text(student['classRank'].toString())), - ], - ); - }).toList(), - ), - ), - ), - ), - ), - ); - } - - // --------------------------------------------------------------------------- - // _buildStudentDetail: - // Displays the selected student's detail info in the bottom-right quadrant. - // --------------------------------------------------------------------------- - Widget _buildStudentDetail() { - if (_selectedStudent == null) { - return const Center( - child: Text( - 'Select a student to see detailed grades.', - style: TextStyle(fontStyle: FontStyle.italic), - ), - ); - } - int studentId = _selectedStudent!['id']; - return FutureBuilder>>( - future: _fetchAllAssessmentsForStudent(studentId), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } - if (snapshot.hasError) { - return Center(child: Text('Error loading grades: ${snapshot.error}')); - } - if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Text('No data available for student $studentId.'); - } - List> detailData = snapshot.data!; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Details for ${_selectedStudent!['studentName']}', - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - ...detailData.map((item) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - "${item['Assessment']} (${item['Type']})", - style: const TextStyle(fontSize: 16), - overflow: TextOverflow.ellipsis, - ), - ), - Text( - item['Grade']!, - style: const TextStyle(fontSize: 16), - ), - ], - ), - ); - }).toList(), - ], - ); - }, - ); - } - - // --------------------------------------------------------------------------- - // _fetchAllAssessmentsForStudent: - // Helper function to fetch ALL assessments (quiz or essay) for ONE student. - // --------------------------------------------------------------------------- - Future>> _fetchAllAssessmentsForStudent( - int studentId) async { - if (_selectedCourse == null) return []; - List>> futureList = []; - for (var assessment in _assessmentsData) { - futureList.add(() async { - String gradeStr = "0%"; - if (assessment.type == "quiz") { - final participants = await (lmsService as moodle.MoodleLmsService) - .getQuizGradesForParticipants( - _selectedCourse!.id.toString(), - assessment.id, - ); - final participant = participants.firstWhere( - (p) => p.id == studentId, - orElse: () => Participant.empty(), - ); - if (participant.avgGrade != null) { - gradeStr = "${participant.avgGrade!.toInt()}%"; - } - } else if (assessment.type == "essay") { - final participants = await (lmsService as moodle.MoodleLmsService) - .getEssayGradesForParticipants( - _selectedCourse!.id.toString(), - assessment.id, - ); - final participant = participants.firstWhere( - (p) => p.id == studentId, - orElse: () => Participant.empty(), - ); - if (participant.avgGrade != null) { - gradeStr = "${participant.avgGrade!.toInt()}%"; - } - } - return { - 'Assessment': assessment.name, - 'Type': assessment.type.toUpperCase(), - 'Grade': gradeStr, - }; - }()); - } - return Future.wait(futureList); - } - - // --------------------------------------------------------------------------- - // _fetchQuestionBreakdown: - // If a quiz is selected, fetch its question breakdown. - // --------------------------------------------------------------------------- - Future _fetchQuestionBreakdown() async { - if (isQuiz()) { - try { - int quizId = _selectedAssessment!.assessment.id; - _questionBreakdown = - await (lmsService as dynamic).getQuestionStatsFromQuiz(quizId); - setState(() {}); - } catch (e) { - print("Failed to fetch question breakdown: $e"); - } - } - } - - bool isQuiz() { - return _selectedAssessment != null && _selectedAssessment!.type == "quiz"; - } - - bool isEssay() { - return _selectedAssessment != null && _selectedAssessment!.type == "essay"; - } - - // --------------------------------------------------------------------------- - // _buildMainGrid: - // Creates a 2×2 grid layout: - // Top-left: Report form - // Bottom-left: Student breakdown table - // Top-right: Question breakdown - // Bottom-right: Selected student detail - // --------------------------------------------------------------------------- - Widget _buildMainGrid() { - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Left Column (narrow) - Expanded( - flex: 1, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // Top-left: the report form - _buildReportForm(), - const SizedBox(height: 20), - const Text( - 'Student Breakdown', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 8), - Container( - color: Colors.white, - padding: const EdgeInsets.all(8), - child: _buildStudentTable(), - ), - ], - ), - ), - const SizedBox(width: 16), - // Right Column (wider) - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // Top-right: label + question breakdown - const Text( - 'Question Breakdown', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 8), - Container( - color: Colors.white, - padding: const EdgeInsets.all(8), - child: _buildQuestionBreakdown(), - ), - const SizedBox(height: 20), - // Bottom-right: label + selected student detail - const Text( - 'Student Detail', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 8), - Container( - color: Colors.white, - padding: const EdgeInsets.all(8), - child: _buildStudentDetail(), - ), - ], - ), - ), - ], - ); - } - - // --------------------------------------------------------------------------- - // _buildContent: - // Builds the overall page content including analytics summary and the 2x2 grid. - // --------------------------------------------------------------------------- - Widget _buildContent() { - if (isLoading && analyticsData == null && errorMsg.isEmpty) { - return const Center(child: CircularProgressIndicator()); - } - if (errorMsg.isNotEmpty) { - return Center(child: Text(errorMsg)); - } - if (analyticsData == null) { - return const Center(child: Text('No analytics data available yet.')); - } - return SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 16), - // Analytics summary. - Center( - child: Column( - children: [ - Text('Analytics Source: ${analyticsData!['source']}', - style: const TextStyle(fontSize: 16)), - Text('Total Courses: ${analyticsData!['totalCourses']}', - style: const TextStyle(fontSize: 16)), - Text( - 'Student Performance: ${analyticsData!['studentPerformance']}', - style: const TextStyle(fontSize: 16)), - Text('IEP Progress: ${analyticsData!['iepProgress']}', - style: const TextStyle(fontSize: 16)), - Text('Course Engagement: ${analyticsData!['courseEngagement']}', - style: const TextStyle(fontSize: 16)), - ], - ), - ), - const SizedBox(height: 20), - // 2x2 grid view. - _buildMainGrid(), - // AI Analysis table below the grid with an export button. - if (_aiAnalysisData.isNotEmpty) ...[ - const SizedBox(height: 30), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - 'AI Analysis Summary', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - ElevatedButton( - onPressed: _exportAIAnalysis, - child: const Text('Export AI Analysis'), - ), - ], - ), - const SizedBox(height: 10), - _buildAIAnalysisTable(), - ], - const SizedBox(height: 30), - ], - ), - ); - } - - // --------------------------------------------------------------------------- - // build: - // Sets up the Scaffold using the shared CustomAppBar and the main content. - // --------------------------------------------------------------------------- - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).colorScheme.surface, - appBar: CustomAppBar( - title: 'Analytics Dashboard', - userprofileurl: lmsService.profileImage ?? '', - onRefresh: _fetchAnalyticsData, - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: _buildContent(), - ), - ); - } - - // --------------------------------------------------------------------------- - // build: - // Builds the overall AI analyisis summary below the 2x2 grid. - // --------------------------------------------------------------------------- - Widget _buildAIAnalysisTable() { - if (_aiAnalysisData.isEmpty) return const SizedBox.shrink(); - return DataTable( - columns: const [ - DataColumn(label: Text('Student')), - DataColumn(label: Text('Status')), - DataColumn(label: Text('Comments')), - ], - rows: _aiAnalysisData.map((row) { - return DataRow( - cells: [ - DataCell(Text(row['Student']?.toString() ?? '')), - DataCell(Text(row['Status']?.toString() ?? '')), - DataCell(Text(row['Comments']?.toString() ?? '')), - ], - ); - }).toList(), - ); - } - - /// Computes the percentage a question is answered correctly. - double computePercentCorrect(QuestionStatsType q) { - if (q.totalAttempts == 0) return 0.0; - return ((q.numCorrect + q.numPartial) / q.totalAttempts) * 100; - } - - /// Computes the average grade across the student breakdown. - double getAverageGrade() { - if (_studentBreakdown.isEmpty) return 0.0; - double sum = 0.0; - for (var student in _studentBreakdown) { - String? gradeStr = student['avgGrade']; - if (gradeStr == null || gradeStr.isEmpty) continue; - gradeStr = gradeStr.replaceAll('%', ''); - double? numericGrade = double.tryParse(gradeStr); - sum += numericGrade ?? 0.0; - } - return sum / _studentBreakdown.length; - } - - /// Returns the total number of quizzes submitted for the current quiz. - int getTotalSubmittedQuizzes() { - if (_questionBreakdown.isEmpty) return 0; - double grandTotalAttempts = 0; - int questionCount = _questionBreakdown.length; - for (QuestionStatsType q in _questionBreakdown) { - grandTotalAttempts += (q.numCorrect + q.numIncorrect + q.numPartial); - } - if (questionCount == 0) return 0; - return (grandTotalAttempts / questionCount).round(); - } - - Future _analyzeReport() async { - if (_studentBreakdown.isEmpty) return; - - // Check for available AI credentials - LlmType? selectedLLM; - if (LocalStorageService.userHasLlmKey(LlmType.CHATGPT)) { - selectedLLM = LlmType.CHATGPT; - } else if (LocalStorageService.userHasLlmKey(LlmType.GROK)) { - selectedLLM = LlmType.GROK; - } else if (LocalStorageService.userHasLlmKey(LlmType.PERPLEXITY)) { - selectedLLM = LlmType.PERPLEXITY; - } else { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - "No AI credentials found. Please log in to an AI platform.")), - ); - return; - } - - String courseName = _selectedCourse?.fullName ?? "Unknown Course"; - String assessmentName = _selectedAssessment?.name ?? "Unknown Assessment"; - - // Build a summary string from the student breakdown data. - String studentSummary = _studentBreakdown.map((student) { - return "Name: ${student['studentName']}, Avg Grade: ${student['avgGrade']}, Rank: ${student['classRank']}"; - }).join("\n"); - - String prompt = - "Analyze the following analytics data for course '$courseName' and assignment '$assessmentName'.\n" - "Student Breakdown Data:\n$studentSummary\n" - "Based on this data, provide a thorough analysis indicating which students are excelling, " - "which are struggling, and which may not have completed the assignment. " - "Return your analysis as a JSON array where each element is an object with keys 'Student', 'Status', and 'Comments'."; - - // Select the AI model based on the available credentials. - dynamic aiModel; - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else { - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } - - setState(() { - _isAnalyzingAI = true; - }); - - try { - var result = await aiModel.postToLlm(prompt); - String normalizedResult = result.trim(); - // Remove markdown code block wrappers if present. - if (normalizedResult.startsWith("```json")) { - normalizedResult = normalizedResult.substring(7); - } - if (normalizedResult.endsWith("```")) { - normalizedResult = - normalizedResult.substring(0, normalizedResult.length - 3); - } - normalizedResult = normalizedResult.trim(); - - var jsonData = json.decode(normalizedResult); - if (jsonData is List) { - setState(() { - _aiAnalysisData = List>.from(jsonData); - }); - } else { - setState(() { - _aiAnalysisData = []; - }); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("AI analysis did not return a valid JSON array.")), - ); - } - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Error during AI analysis: $e")), - ); - } finally { - setState(() { - _isAnalyzingAI = false; - }); - } - } -} diff --git a/team_a/teamA/lib/Views/assessments_view.dart b/team_a/teamA/lib/Views/assessments_view.dart deleted file mode 100644 index 208eb094..00000000 --- a/team_a/teamA/lib/Views/assessments_view.dart +++ /dev/null @@ -1,405 +0,0 @@ -import "package:flutter/material.dart"; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import 'package:learninglens_app/Api/lms/google_classroom/google_lms_service.dart'; -import 'package:learninglens_app/beans/g_question_form_data.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/course.dart'; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import "package:learninglens_app/beans/quiz_type.dart"; -import 'package:learninglens_app/content_carousel.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:flutter/services.dart'; -import 'package:url_launcher/url_launcher.dart'; -import "package:learninglens_app/Views/view_quiz.dart"; - -class AssessmentsView extends StatefulWidget { - AssessmentsView({super.key, this.quizID = 0, this.courseID = 0}); - - final int quizID; - final int? courseID; - - @override - _AssessmentsState createState() => _AssessmentsState(); -} - -class _AssessmentsState extends State { - late Future?> quizzes; - Quiz? selectedQuiz; - List> questionsData = []; - Future? _formDataFuture; - GoogleLmsService googleLmsService = GoogleLmsService(); - - @override - void initState() { - super.initState(); - _refreshQuizzes(); - } - - // Check if Moodle is selected - bool isMoodle() { - return LocalStorageService.getSelectedClassroom() == LmsType.MOODLE; - } - - // Method to refresh quizzes - void _refreshQuizzes() { - setState(() { - quizzes = getAllQuizzes(); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Assessments', - onRefresh: _refreshQuizzes, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Column( - children: [ - Row(children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: CreateButton('assessment')) - ]), - Expanded( - child: FutureBuilder?>( - future: quizzes, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error loading quizzes')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No quizzes found')); - } else { - final quizList = snapshot.data!; - - return LayoutBuilder( - builder: (context, constraints) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: ListView.builder( - itemCount: quizList.length, - itemBuilder: (context, index) { - final quiz = quizList[index]; - final activeCourse = - getCourse(quiz.coursedId); - if (quiz.id == widget.quizID) { - selectedQuiz = quiz; - } - - return ListTile( - title: Text( - '${quiz.name} (${activeCourse.shortName}${activeCourse.courseId})'), - subtitle: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - 'Due: ${quiz.timeClose == null ? "No due date set" : Course.dateFormatted(quiz.timeClose!)}'), - ], - ), - tileColor: selectedQuiz == quiz - ? Theme.of(context) - .colorScheme - .primary - .withOpacity(0.1) - : null, - onTap: () { - setState(() { - selectedQuiz = quiz; - if (!isMoodle()) { - _formDataFuture = googleLmsService - .getAssignmentFormQuestions( - quiz.coursedId.toString(), - quiz.id.toString()); - } - }); - }, - ); - }, - ), - ), - ), - Expanded( - flex: 2, - child: selectedQuiz == null - ? Center( - child: - Text('Select a quiz to view details')) - : isMoodle() - ? _buildMoodleContent() - : _buildGoogleContent(), - ), - ], - ); - }, - ); - } - }, - ), - ), - ], - ), - ); - } - - Widget _buildMoodleContent() { - return Expanded( - flex: 2, - child: selectedQuiz == null && widget.quizID == 0 - ? Center(child: Text('Select a quiz to view details')) - : ViewQuiz(quizId: selectedQuiz?.id ?? widget.quizID), - ); - } - - Widget _buildGoogleContent() { - return FutureBuilder( - future: _formDataFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } else if (snapshot.hasData && snapshot.data!.questions.isNotEmpty) { - return DynamicForm(formData: snapshot.data!); - } else { - return Center(child: Text('No questions found in the Google Form.')); - } - }, - ); - } -} - -Future> getAllQuizzes() async { - print("Getting all quizzes"); - List result = []; - for (Course c in LmsFactory.getLmsService().courses ?? []) { - result.addAll(c.quizzes ?? []); - } - return result; -} - -Course getCourse(int? courseID) { - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (c.id == courseID) { - return c; - } - } - throw "No course found."; -} - -class DynamicForm extends StatelessWidget { - final FormData formData; - - const DynamicForm({super.key, required this.formData}); - - String _getQuestionType(List options) { - if (options.isEmpty) { - return 'Short Answer'; - } else if (options.length == 2) { - return 'True/False'; - } else { - return 'Multiple Choice'; - } - } - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child: Center( - child: Padding( - padding: const EdgeInsets.fromLTRB(16.0, 4.0, 16.0, 16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Text( - formData.title, - style: Theme.of(context) - .textTheme - .headlineSmall - ?.copyWith(fontWeight: FontWeight.bold), - ), - ), - Card( - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('Start Date: ', - style: TextStyle(fontWeight: FontWeight.bold)), - Text(formData.startDate ?? 'N/A'), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('End Date: ', - style: TextStyle(fontWeight: FontWeight.bold)), - Text(formData.endDate ?? 'N/A'), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('Form URL: ', - style: TextStyle(fontWeight: FontWeight.bold)), - GestureDetector( - onTap: () async { - if (formData.formUrl != null) { - final Uri url = Uri.parse(formData.formUrl!); - if (await canLaunchUrl(url)) { - await launchUrl(url); - } else { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Cannot launch URL')), - ); - } - } - }, - child: Text( - formData.formUrl ?? 'N/A', - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline, - ), - ), - ), - if (formData.formUrl != null) ...[ - IconButton( - icon: const Icon(Icons.copy), - onPressed: () { - Clipboard.setData( - ClipboardData(text: formData.formUrl!)); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('URL copied to clipboard')), - ); - }, - ), - ], - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('Status: ', - style: TextStyle(fontWeight: FontWeight.bold)), - Text(formData.status ?? 'N/A'), - ], - ), - const SizedBox(height: 16), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 20, - dataRowHeight: 60, - headingRowColor: MaterialStateProperty.all( - Colors.blueAccent.withOpacity(0.1)), - border: TableBorder.all( - color: Colors.grey, - width: 1.0, - ), - columns: const [ - DataColumn( - label: Center( - child: Text('Question No.', - style: - TextStyle(fontWeight: FontWeight.bold)), - ), - ), - DataColumn( - label: Center( - child: Text('Question', - style: - TextStyle(fontWeight: FontWeight.bold)), - ), - ), - DataColumn( - label: Center( - child: Text('Type', - style: - TextStyle(fontWeight: FontWeight.bold)), - ), - ), - DataColumn( - label: Center( - child: Text('Options', - style: - TextStyle(fontWeight: FontWeight.bold)), - ), - ), - ], - rows: formData.questions.asMap().entries.map((entry) { - int index = entry.key + 1; - QuestionData questionData = entry.value; - return DataRow(cells: [ - DataCell(Text('$index')), - DataCell( - SizedBox( - width: 400, - child: Text( - questionData.question, - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 2, - ), - ), - ), - DataCell( - Text( - _getQuestionType(questionData.options), - ), - ), - DataCell( - SizedBox( - width: 300, - child: Text( - questionData.options.isEmpty - ? 'N/A' - : questionData.options.join(', '), - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 2, - ), - ), - ), - ]); - }).toList(), - ), - ), - ], - ), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/chat_screen.dart b/team_a/teamA/lib/Views/chat_screen.dart deleted file mode 100644 index 6b2f63ff..00000000 --- a/team_a/teamA/lib/Views/chat_screen.dart +++ /dev/null @@ -1,248 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:shared_preferences/shared_preferences.dart'; // For saving/loading chat history -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'dart:convert'; // For encoding and decoding chat history - -class ChatScreen extends StatefulWidget { - @override - _ChatScreenState createState() => _ChatScreenState(); -} - -class _ChatScreenState extends State { - final TextEditingController _controller = TextEditingController(); - List> _messages = []; - bool _isLoading = false; - String _role = 'student'; // Role toggle for student/teacher - final ScrollController _scrollController = - ScrollController(); // For scrolling the chat - SharedPreferences? _prefs; // SharedPreferences for saving chat history - LlmType? selectedLLM; - - @override - void initState() { - super.initState(); - _loadChatHistory(); // Load chat history when screen is initialized - selectedLLM = LlmType.CHATGPT; - } - - // Load chat history from SharedPreferences - Future _loadChatHistory() async { - _prefs = await SharedPreferences.getInstance(); - String? savedMessages = _prefs?.getString('chat_history'); - if (savedMessages != null) { - setState(() { - _messages = List>.from(jsonDecode(savedMessages)); - }); - } - } - - // Save chat history to SharedPreferences - Future _saveChatHistory() async { - if (_prefs != null) { - await _prefs?.setString('chat_history', jsonEncode(_messages)); - } - } - - // Function to handle user message sending and API response - Future _sendMessage() async { - final input = _controller.text; - - if (input.isEmpty) { - return; - } - final aiModel; - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else if (selectedLLM == LlmType.PERPLEXITY) { - // aiModel = OpenAiLLM(perplexityApiKey); - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } else { - // default - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } - - // Update UI to show user's message and reset text field - setState(() { - _messages.add({'text': input, 'sender': 'user'}); - _isLoading = true; // Show a loading indicator while waiting for response - }); - - _controller.clear(); // Clear the input field - _scrollToBottom(); // Scroll to the bottom after sending the message - await _saveChatHistory(); // Save chat history - - try { - // Get ChatGPT response - // final chatGPTService = OpenAiLLM(); - final prompt = - _role == 'teacher' ? "You are assisting a teacher. $input" : input; - final response = await aiModel.getChatResponse(prompt); - - setState(() { - _messages.add({'text': response, 'sender': 'bot'}); - _isLoading = false; - }); - - _scrollToBottom(); // Scroll to the bottom after receiving the bot response - await _saveChatHistory(); // Save chat history after bot response - } catch (error) { - setState(() { - _messages.add({ - 'text': 'Error: Could not fetch response. Please try again.', - 'sender': 'bot' - }); - _isLoading = false; - }); - } - } - - // Function to clear chat history - void _clearChat() { - setState(() { - _messages.clear(); - }); - _saveChatHistory(); // Save the empty state to clear saved chat history - } - - // Function to toggle role (student/teacher) - // void _toggleRole() { ***** Not used ***** - // setState(() { - // _role = _role == 'student' ? 'teacher' : 'student'; - // }); - // } - - // Scroll to the bottom of the chat list - void _scrollToBottom() { - _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: Duration(milliseconds: 300), - curve: Curves.easeOut, - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Ask Chatbot!', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - backgroundColor: Theme.of(context).colorScheme.surface, - body: Row( - children: [ - // Main chat content - Expanded( - child: Column( - children: [ - Expanded( - child: ListView.builder( - controller: - _scrollController, // Attach the ScrollController - padding: const EdgeInsets.all(12), - itemCount: _messages.length, - itemBuilder: (context, index) { - final message = _messages[index]; - final isUserMessage = message['sender'] == 'user'; - - return Align( - alignment: isUserMessage - ? Alignment.centerRight - : Alignment.centerLeft, - child: Container( - margin: const EdgeInsets.symmetric(vertical: 6), - padding: const EdgeInsets.all(14), - decoration: BoxDecoration( - color: isUserMessage - ? Colors.deepPurple - : Colors.grey[300], - borderRadius: BorderRadius.circular(16), - ), - child: Text( - message['text'], - style: TextStyle( - color: - isUserMessage ? Colors.white : Colors.black87, - fontSize: 16, - ), - ), - ), - ); - }, - ), - ), - if (_isLoading) - Padding( - padding: const EdgeInsets.all(8.0), - child: CircularProgressIndicator(), // Loading indicator - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Expanded( - child: TextField( - controller: _controller, - decoration: InputDecoration( - hintText: 'Enter your message...', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - filled: true, - fillColor: Colors.white, - contentPadding: EdgeInsets.symmetric( - vertical: 10, horizontal: 16), - ), - onSubmitted: (_) => _sendMessage(), - ), - ), - IconButton( - icon: Icon(Icons.send, color: Colors.purpleAccent), - onPressed: _sendMessage, - ), - IconButton( - icon: Icon(Icons.clear), - onPressed: _clearChat, // Clear chat history - ), - // IconButton( - // icon: Icon(Icons.switch_account), - // onPressed: _toggleRole, // Toggle role between teacher and student - // tooltip: - // 'Switch role to ${_role == 'student' ? 'Teacher' : 'Student'}', - // ), - DropdownButton( - value: selectedLLM, - onChanged: (LlmType? newValue) { - setState(() { - selectedLLM = newValue; - }); - }, - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text(llm.displayName, style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) ? Colors.black87 : Colors.grey, - ), - ), - ); - }).toList() - ), - ], - ), - ), - ], - ), - ), - ], - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/course_content.dart b/team_a/teamA/lib/Views/course_content.dart deleted file mode 100644 index 2aadc20b..00000000 --- a/team_a/teamA/lib/Views/course_content.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/course.dart'; -import '../content_carousel.dart'; - -//What we need: -//Two carousels, one for essays and the other for assessments. -//Additional information and buttons appear when a card is clicked. -//The essay cards have two buttons leading to submissions and assignment editing pages. -//The assessment cards have a button leading to the assessment editing page. -//Two buttons below that lead to the create essay and create assessment pages. - -//Main Page -class ViewCourseContents extends StatefulWidget { - final Course theCourse; - ViewCourseContents(this.theCourse); - - @override - State createState() { - return _CourseState(); - } -} - -class _CourseState extends State { - late final String courseName; - - @override - void initState() { - super.initState(); - courseName = widget.theCourse.fullName; - } - -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(title: 'Course Content', userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, // Keeps everything left-aligned - children: [ - // Background for "Quizzes" - Container( - width: double.infinity, - color: Theme.of(context).colorScheme.secondary, - padding: const EdgeInsets.all(8.0), // Padding inside the container - margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), // Space around the container - child: Text( - "Quizzes", - style: TextStyle( - fontSize: 32, - color: Theme.of(context).colorScheme.onSecondary, // Text color set for contrast - ), - ), - ), - ContentCarousel( - 'assessment', - widget.theCourse.quizzes, - courseId: widget.theCourse.id, - ), - - // Background for "Essays" - Container( - width: double.infinity, - color: Theme.of(context).colorScheme.secondary, - padding: const EdgeInsets.all(8.0), - margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - child: Text( - "Essays", - style: TextStyle( - fontSize: 32, - color: Theme.of(context).colorScheme.onSecondary, - ), - ), - ), - ContentCarousel( - 'essay', - widget.theCourse.essays, - courseId: widget.theCourse.id, - ), - - // Responsive layout for the buttons - LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth < 600) { - // Stack buttons vertically for narrow screens - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - CreateButton('assessment'), - SizedBox(height: 8.0), // Space between buttons - CreateButton('essay'), - ], - ); - } else { - // Show buttons in a row for wide screens - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CreateButton('assessment'), - CreateButton('essay'), - ], - ); - } - }, - ), - ], - ), - ), - ); -} - - -} diff --git a/team_a/teamA/lib/Views/course_list.dart b/team_a/teamA/lib/Views/course_list.dart deleted file mode 100644 index 23572a46..00000000 --- a/team_a/teamA/lib/Views/course_list.dart +++ /dev/null @@ -1,149 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/course.dart'; -import '../content_carousel.dart'; - -class CourseList extends StatefulWidget { - CourseList({super.key}); - - @override - _CourseListState createState() => _CourseListState(); -} - -class _CourseListState extends State { - final LmsInterface api = LmsFactory.getLmsService(); - late Future> courses; - Course? selectedCourse; - - @override - void initState() { - super.initState(); - courses = api.getUserCourses(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Courses', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: FutureBuilder>( - future: courses, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error loading courses')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No courses found')); - } else { - final courseList = snapshot.data!; - - return LayoutBuilder( - builder: (context, constraints) { - return Row( - children: [ - // Left-side course list with border - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: ListView.builder( - itemCount: courseList.length, - itemBuilder: (context, index) { - final course = courseList[index]; - return ListTile( - title: Text(course.fullName), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('${course.shortName}${course.courseId}'), - Text('${Course.dateFormatted(course.startdate)} - ${Course.dateFormatted(course.enddate)}'), - ], - ), - tileColor: selectedCourse == course - ? Theme.of(context).colorScheme.primary.withOpacity(0.1) - : null, - onTap: () { - setState(() { - selectedCourse = course; - }); - }, - ); - }, - ), - ), - ), - - // Right-side course details (essays and quizzes) - Expanded( - flex: 2, - child: selectedCourse == null - ? Center(child: Text('Select a course to view details')) - : Column( - key: ValueKey(selectedCourse!.id), // Force rebuild on course change - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Essays section - Container( - width: double.infinity, - color: Theme.of(context).colorScheme.secondary, - padding: const EdgeInsets.all(8.0), - margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - child: Text( - "Essays", - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSecondary, - ), - ), - ), - Expanded( - child: ContentCarousel( - 'essay', - selectedCourse!.essays, - courseId: selectedCourse!.id, - ), - ), - - // Quizzes section - Container( - width: double.infinity, - color: Theme.of(context).colorScheme.secondary, - padding: const EdgeInsets.all(8.0), - margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - child: Text( - "Quizzes", - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSecondary, - ), - ), - ), - Expanded( - child: ContentCarousel( - 'assessment', - selectedCourse!.quizzes, - courseId: selectedCourse!.id, - ), - ), - ], - ), - ), - ], - ); - }, - ); - } - }, - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/dashboard.dart b/team_a/teamA/lib/Views/dashboard.dart deleted file mode 100644 index d80cc950..00000000 --- a/team_a/teamA/lib/Views/dashboard.dart +++ /dev/null @@ -1,480 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/Views/analytics_page.dart'; -import 'package:learninglens_app/Views/assessments_view.dart'; -import 'package:learninglens_app/Views/course_list.dart'; -import 'package:learninglens_app/Views/essays_view.dart'; -import 'package:learninglens_app/Views/about_page.dart'; -import 'package:learninglens_app/Views/g_lesson_plan.dart'; -import 'package:learninglens_app/Views/iep_page.dart'; -import 'package:learninglens_app/Views/lesson_plans.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -class TeacherDashboard extends StatelessWidget { - const TeacherDashboard({super.key}); - - @override - Widget build(BuildContext context) { - final bool canAccessApp = canUserAccessApp(context); - - return Scaffold( - appBar: CustomAppBar( - title: 'Learning Lens', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - backgroundColor: Theme.of(context).colorScheme.surface, - body: Column( - children: [ - if (!canAccessApp) - Container( - color: Colors.red[700], - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.only(bottom: 10), - child: Row( - children: [ - const Icon(Icons.warning, color: Colors.white), - const SizedBox(width: 10), - Expanded( - child: Text( - "This application requires an LMS to be logged in and an LLM Key to function properly.", - style: const TextStyle(color: Colors.white), - ), - ), - ], - ), - ), - Expanded( - child: LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > 600) { - return _buildDesktopLayout(context, constraints); - } else { - return _buildMobileLayout(context, constraints); - } - }, - ), - ), - Padding( - padding: const EdgeInsets.only(bottom: 20), - child: Center( - child: TextButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => AboutPage()), - ); - }, - child: const Text("About Learning Lens"), - ), - ), - ), - ], - ), - ); - } - - bool canUserAccessApp(BuildContext context) { - bool isLoggedIntoGoogleClassroom = LocalStorageService.isLoggedIntoGoogle() && LocalStorageService.hasLLMKey(); - bool isLoggedIntoMoodle = LocalStorageService.isLoggedIntoMoodle() && LocalStorageService.hasLLMKey(); - return isMoodle() ? isLoggedIntoMoodle : isLoggedIntoGoogleClassroom; - } - - String getClassroom() { - return LocalStorageService.getSelectedClassroom() == LmsType.MOODLE ? 'Moodle' : 'Google'; - } - - bool isMoodle() { - print(LocalStorageService.getSelectedClassroom()); - return LocalStorageService.getSelectedClassroom() == LmsType.MOODLE; - } - - Widget _buildDesktopLayout(BuildContext context, BoxConstraints constraints) { - final double screenWidth = constraints.maxWidth; - - double baseButtonSize = screenWidth * 0.15; - double baseButtonFontSize = screenWidth * 0.015; - double baseDescriptionFontSize = screenWidth * 0.015; - - double middleButtonSize = baseButtonSize * 1.2; - double middleButtonFontSize = baseButtonFontSize * 1.2; - double middleDescriptionFontSize = baseDescriptionFontSize * 1.1; - - baseButtonSize = baseButtonSize.clamp(80.0, 150.0); - baseButtonFontSize = baseButtonFontSize.clamp(12.0, 18.0); - baseDescriptionFontSize = baseDescriptionFontSize.clamp(12.0, 18.0); - - middleButtonSize = middleButtonSize.clamp(96.0, 180.0); - middleButtonFontSize = middleButtonFontSize.clamp(14.0, 20.0); - middleDescriptionFontSize = middleDescriptionFontSize.clamp(13.0, 20.0); - - double titleFontSize = screenWidth * 0.03; - titleFontSize = titleFontSize.clamp(20.0, 32.0); - - return SingleChildScrollView( - child: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'Teacher ${getClassroom()} Dashboard', - style: TextStyle( - fontSize: titleFontSize, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - const SizedBox(height: 12), - Text( - 'Welcome, ${LmsFactory.getLmsService().firstName ?? 'User'}', - style: TextStyle( - fontSize: titleFontSize * 0.7, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - const SizedBox(height: 20), - _buildGridLayout(context, constraints), - ], - ), - ), - ), - ); - } - - Widget _buildMobileLayout(BuildContext context, BoxConstraints constraints) { - final double screenWidth = constraints.maxWidth; - - double baseButtonSize = screenWidth * 0.35; // Reduced from 0.4 - double baseButtonFontSize = screenWidth * 0.04; // Reduced from 0.045 - double baseDescriptionFontSize = screenWidth * 0.035; // Reduced from 0.04 - - double middleButtonSize = baseButtonSize * 1.1; - double middleButtonFontSize = baseButtonFontSize * 1.1; - double middleDescriptionFontSize = baseDescriptionFontSize * 1.05; - - baseButtonSize = baseButtonSize.clamp(70.0, 120.0); // Reduced max size - baseButtonFontSize = baseButtonFontSize.clamp(10.0, 14.0); // Reduced max size - baseDescriptionFontSize = baseDescriptionFontSize.clamp(10.0, 14.0); // Reduced max size - - middleButtonSize = middleButtonSize.clamp(77.0, 132.0); - middleButtonFontSize = middleButtonFontSize.clamp(11.0, 16.0); - middleDescriptionFontSize = middleDescriptionFontSize.clamp(11.0, 15.0); - - double titleFontSize = screenWidth * 0.06; - titleFontSize = titleFontSize.clamp(16.0, 22.0); // Reduced max size - - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(12.0), // Reduced from 16.0 - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 600), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'Teacher Dashboard', - style: TextStyle( - fontSize: titleFontSize, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - const SizedBox(height: 8), // Reduced from 12 - Text( - 'Welcome, ${LmsFactory.getLmsService().firstName ?? 'User'}', - style: TextStyle( - fontSize: titleFontSize * 0.7, - fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - const SizedBox(height: 12), // Reduced from 20 - _buildGridLayout(context, constraints), - ], - ), - ), - ), - ); - } - - Widget _buildGridLayout(BuildContext context, BoxConstraints constraints) { - final double screenWidth = constraints.maxWidth; - - double baseButtonSize = screenWidth * 0.15; - double baseButtonFontSize = screenWidth * 0.015; - double baseDescriptionFontSize = screenWidth * 0.015; - - baseButtonSize = baseButtonSize.clamp(70.0, 130.0); // Reduced max size - baseButtonFontSize = baseButtonFontSize.clamp(10.0, 16.0); // Reduced max size - baseDescriptionFontSize = baseDescriptionFontSize.clamp(10.0, 16.0); // Reduced max size - - bool canAccessApp = canUserAccessApp(context); - bool isMoodleSelected = isMoodle(); - - List> buttonData = [ - { - 'title': 'Courses', - 'description': 'View available courses.', - 'onPressed': !canAccessApp - ? null - : () => Navigator.push( - context, MaterialPageRoute(builder: (context) => CourseList())), - 'color': Colors.blue, - }, - { - 'title': 'Essays', - 'description': 'View or grade essays.', - 'onPressed': !canAccessApp - ? null - : () => Navigator.push( - context, MaterialPageRoute(builder: (context) => EssaysView())), - 'color': Colors.red, - }, - { - 'title': 'IEP', - 'description': 'Manage Individualized Education Plans.', - 'onPressed': !canAccessApp || !isMoodleSelected - ? null - : () => Navigator.push( - context, MaterialPageRoute(builder: (context) => IepPage())), - 'color': !isMoodleSelected ? Colors.grey : Colors.green, - }, - { - 'title': 'Analytics', - 'description': 'View performance analytics.', - 'onPressed': !canAccessApp || !isMoodleSelected - ? null - : () => Navigator.push( - context, MaterialPageRoute(builder: (context) => AnalyticsPage())), - 'color': !isMoodleSelected ? Colors.grey : Colors.cyan, - }, - { - 'title': 'Lesson Plan', - 'description': 'Create and manage lesson plans.', - 'onPressed': !canAccessApp - ? null - : () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => !isMoodleSelected - ? GoogleLessonPlans() - : LessonPlans(), - ), - ), - 'color': Colors.purple, - }, - { - 'title': 'Assessments', - 'description': 'Create or view assessments.', - 'onPressed': !canAccessApp - ? null - : () => Navigator.push( - context, MaterialPageRoute(builder: (context) => AssessmentsView())), - 'color': Colors.orange, - }, - ]; - - return Padding( - padding: const EdgeInsets.all(12.0), // Reduced from 16.0 - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[0]['description'], - buttonData[0]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[0]['onPressed'], - buttonData[0]['color'], - ), - ), - const SizedBox(width: 12), // Reduced from 20 - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[1]['description'], - buttonData[1]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[1]['onPressed'], - buttonData[1]['color'], - ), - ), - ], - ), - const SizedBox(height: 12), // Reduced from 20 - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[2]['description'], - buttonData[2]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[2]['onPressed'], - buttonData[2]['color'], - ), - ), - const SizedBox(width: 12), // Reduced from 20 - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[3]['description'], - buttonData[3]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[3]['onPressed'], - buttonData[3]['color'], - ), - ), - ], - ), - const SizedBox(height: 12), // Reduced from 20 - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[4]['description'], - buttonData[4]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[4]['onPressed'], - buttonData[4]['color'], - ), - ), - const SizedBox(width: 12), // Reduced from 20 - Expanded( - child: _buildResponsiveColumn( - context, - buttonData[5]['description'], - buttonData[5]['title'], - baseDescriptionFontSize, - baseButtonSize, - baseButtonFontSize, - buttonData[5]['onPressed'], - buttonData[5]['color'], - ), - ), - ], - ), - ], - ), - ); - } - - Widget _buildResponsiveColumn( - BuildContext context, - String description, - String title, - double descriptionFontSize, - double buttonSize, - double buttonFontSize, - void Function()? onPressed, - Color buttonColor, - ) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: buttonSize * 1.5, - child: Text( - description, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: descriptionFontSize, - color: Colors.black, - ), - ), - ), - const SizedBox(height: 8), // Reduced from 10 - _buildDashboardButton( - context, - title, - buttonSize, - buttonFontSize, - onPressed, - buttonColor, - ), - ], - ); - } - - Widget _buildDashboardButton( - BuildContext context, - String title, - double size, - double fontSize, - void Function()? onPressed, - Color buttonColor, - ) { - return Container( - height: size, - width: size, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: buttonColor, - boxShadow: [ - BoxShadow( - color: Colors.grey[500]!, - offset: const Offset(4, 4), - blurRadius: 15, - spreadRadius: 1, - ), - ], - ), - child: Container( - margin: EdgeInsets.all(size * 0.1), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.grey[600]!, - offset: const Offset(4, 4), - blurRadius: 10, - spreadRadius: 1, - ), - ], - ), - child: ElevatedButton( - onPressed: onPressed, - style: ElevatedButton.styleFrom( - shape: const CircleBorder(), - backgroundColor: Colors.transparent, - padding: EdgeInsets.all(size * 0.15), - shadowColor: Colors.transparent, - ), - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - title, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/edit_questions.dart b/team_a/teamA/lib/Views/edit_questions.dart deleted file mode 100644 index dd2df280..00000000 --- a/team_a/teamA/lib/Views/edit_questions.dart +++ /dev/null @@ -1,212 +0,0 @@ -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/Views/send_quiz_to_moodle.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/question.dart'; -import 'package:flutter/material.dart'; -import 'quiz_generator.dart'; - -class EditQuestions extends StatefulWidget { - final String questionXML; - - EditQuestions(this.questionXML); - - @override - EditQuestionsState createState() => EditQuestionsState(); -} - -class EditQuestionsState extends State { - late Quiz myQuiz; - // final TextEditingController _textController = TextEditingController(); - var apikey = LocalStorageService.getOpenAIKey(); - // late OpenAiLLM openai; - var aiModel; - bool _isLoading = false; - - String subject = CreateAssessment.descriptionController.text; - String topic = CreateAssessment.topicController.text; - late String promptstart; - - @override - void initState() { - super.initState(); - myQuiz = Quiz.fromXmlString(widget.questionXML); - getAiModel(); - // if (apikey.isNotEmpty) { - // // TODO: Fix only excepts ChatGPT AI. - // openai = OpenAiLLM(apikey); - // } else { - // // Handle the case where the API key is null - // throw Exception('API key is not set in the environment variables'); - // } - myQuiz.name = CreateAssessment.nameController.text; - myQuiz.description = CreateAssessment.descriptionController.text; - - promptstart = - 'Create a question that is compatible with Moodle XML import. ' - 'Be a bit creative in how you design the question and answers, ' - 'making sure it is engaging but still on the subject of $subject and related to $topic. ' - 'Make sure the XML specification is included, and the question is wrapped ' - 'in the quiz XML element required by Moodle. Each answer should have feedback ' - 'that fits the Moodle XML format, and avoid using HTML elements within a CDATA field. ' - 'The quiz should be challenging and thought-provoking, but appropriate for ' - 'high school students who speak English. The Moodle question type should be '; - } - - void getAiModel() { - LlmType selectedLLM = LlmType.values.firstWhere( - (type) => type.displayName == CreateAssessment.llmController.text, - orElse: () => throw Exception('No LlmType found'), - ); - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else if (selectedLLM == LlmType.PERPLEXITY) { - // aiModel = OpenAiLLM(perplexityApiKey); - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } else { - // default - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Edit Questions', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Column( - children: [ - Text( - 'Swipe right to have the AI rebuild the question.', - style: TextStyle(fontSize: 14),), - Text( - 'Swipe left to remove the question', - style: TextStyle(fontSize: 14),), - Expanded( - child: ListView.builder( - itemCount: myQuiz.questionList.length, - itemBuilder: (context, index) { - var question = myQuiz.questionList[index]; - return Dismissible( - key: Key(question.toString()), - background: Stack( - children: [ - Container( - color: Theme.of(context).colorScheme.scrim, - child: Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(left: 16), - child: Icon( - Icons.refresh, - color: Theme.of(context).colorScheme.surface, - ), - ), - ), - ), - if (_isLoading) - Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.surface, - ), - ), // Spinner behind the item - ), - ], - ), - secondaryBackground: Container( - color: Theme.of(context).colorScheme.error, - child: Align( - alignment: Alignment.centerRight, - child: Padding( - padding: const EdgeInsets.only(right: 16), - child: Icon(Icons.delete), - ), - ), - ), - confirmDismiss: (direction) async { - if (direction == DismissDirection.startToEnd) { - setState(() { - _isLoading = true; - }); - var result = await aiModel - // .postToLlm(promptstart + question.toString()); - .postToLlm(promptstart + question.type.toString()); - - setState(() { - _isLoading = false; // Stop showing the spinner - }); - - if (result.isNotEmpty) { - setState(() { - //replace the old question with the new one from the api call - question = Quiz.fromXmlString(result).questionList[0]; - question.setName = 'Question ${index + 1}'; - myQuiz.questionList[index] = question.copyWith( - isFavorite: !question.isFavorite); - }); - } - return false; - } else { - bool delete = true; - final snackbarController = - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Deleted $Question'), - duration: Duration(seconds: 2), - action: SnackBarAction( - label: 'Undo', onPressed: () => delete = false), - ), - ); - await snackbarController.closed; - return delete; - } - }, - onDismissed: (_) { - setState(() { - myQuiz.questionList.removeAt(index); - }); - }, - child: ListTile( - title: Text(question.toString()), - tileColor: (index.isEven) - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.secondaryContainer, - textColor: (index.isEven) - ? Theme.of(context).colorScheme.onSecondary - : Theme.of(context).colorScheme.onSecondaryContainer, - ), - ); - }, - ), - ), - Row( - children: [ - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QuizMoodle(quiz: myQuiz) - ), - ); - }, - child: const Text('Accept questions and Submit'), - ), - - ], - ) - ], - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/essay_edit_page.dart b/team_a/teamA/lib/Views/essay_edit_page.dart deleted file mode 100644 index 5551e5b4..00000000 --- a/team_a/teamA/lib/Views/essay_edit_page.dart +++ /dev/null @@ -1,176 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:editable/editable.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'dart:convert'; - -import 'send_essay_to_moodle.dart'; // Import for JSON encoding - -class EssayEditPage extends StatefulWidget { - final String jsonData; - final String description; - - EssayEditPage(this.jsonData, this.description); - - @override - EssayEditPageState createState() => EssayEditPageState(); // Public State class -} - -class EssayEditPageState extends State { - - - // Convert JSON to rows compatible with Editable - List rows = []; - - // Headers or Columns - List headers = []; - - @override - void initState() { - super.initState(); - - populateHeadersAndRows(); - } - - // Function to dynamically populate headers and rows based on JSON data - void populateHeadersAndRows() { - Map mappedData = jsonDecode(widget.jsonData); - // Step 1: Build headers dynamically based on the number of levels in the first criterion - List levels = List.from(mappedData['criteria']![0]['levels'] as List); -headers = [ - {"title": 'Criteria', 'index': 1, 'key': 'name', 'widthFactor': 0.15}, // 30% width -]; - -for (int i = 0; i < levels.length; i++) { - headers.add({ - "title": '${levels[i]['score']}', - 'index': i + 2, - 'key': 'level_$i', - 'widthFactor': 0.8/levels.length, // 10% width for each level column - }); -} - - // Step 2: Build rows by mapping each criterion and its levels dynamically - rows = (mappedData['criteria'] ?? []).map((criterion) { - Map row = { - "name": criterion['description'], - }; - - for (int i = 0; i < (criterion['levels'] as List).length; i++) { - row['level_$i'] = (criterion['levels'] as List)[i]['definition']; - } - - return row; - }).toList(); - - setState(() {}); // Ensure the UI is updated after populating headers and rows - } - - /// Create a Key for EditableState - final _editableKey = GlobalKey(); - - /// Merge edits into the original jsonData and return updated JSON - String getUpdatedJson() { - List editedRows = _editableKey.currentState!.editedRows; - Map mappedData = jsonDecode(widget.jsonData); - - // Apply the edits to the original jsonData - for (var editedRow in editedRows) { - int rowIndex = editedRow['row']; - var originalCriterion = mappedData['criteria']?[rowIndex]; - - // For each edited level, update the corresponding level in the original data - editedRow.forEach((key, value) { - if (key != 'row' && key.startsWith('level_')) { - int levelIndex = int.parse(key.split('_')[1]); - (originalCriterion as Map)['levels']?[levelIndex]['definition'] = value; - } - }); - } - - // Convert the updated jsonData back to the required format and return it - Map updatedData = { - "criteria": mappedData['criteria'] - }; - return jsonEncode(updatedData); // Return the JSON as a string - } - -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(title: 'Edit Essay Rubric', userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: LayoutBuilder( - builder: (context, constraints) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, // Align content to the top-left - children: [ - SizedBox(height: 24.0), - - // Expanded is used for the Editable, wrapped with SingleChildScrollView for horizontal scrolling - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Allow horizontal scrolling for the Editable - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: 600, // Ensure the table never shrinks below 600px - maxWidth: constraints.maxWidth > 600 ? constraints.maxWidth : 600, - ), - child: Editable( - key: _editableKey, - tdEditableMaxLines: 100, - trHeight: 100, - columns: headers, - rows: rows, - showCreateButton: false, - tdStyle: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary, - ), - showSaveIcon: false, - onRowSaved: (value) { - print('rowsaved $value'); - }, - borderColor: Theme.of(context).colorScheme.primaryContainer, - onSubmitted: (value) { - print('onsubmitted: $value'); // You can grab this data to store anywhere - }, - ), - ), - ), - ), - - SizedBox(height: 20), // Add some spacing between the Editable and the button - - // Row for the Button outside the scrollable area - Row( - mainAxisAlignment: MainAxisAlignment.center, // Center the button horizontally - children: [ - ElevatedButton( - child: const Text('Send to Moodle'), - onPressed: () { - String updatedJson = getUpdatedJson(); - // Navigate to the Essay Assignment Settings page with the updated JSON - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => - EssayAssignmentSettings(updatedJson, widget.description))); - print(updatedJson); // You can now see the updated JSON in the console - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Data sent to Moodle'))); - }, - ), - ], - ), - SizedBox(height: 20), // Optional additional spacing - ], - ); - }, - ), - ); -} - - - - - -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/essay_generation.dart b/team_a/teamA/lib/Views/essay_generation.dart deleted file mode 100644 index 5391c39a..00000000 --- a/team_a/teamA/lib/Views/essay_generation.dart +++ /dev/null @@ -1,604 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/constants/learning_lens.constants.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/Views/essay_edit_page.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'dart:convert'; -import '../Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; - - -// Required Components: -// 2 Dropdowns: 1 for the Grade Level and 1 for the Point Scale -// 3 Text Boxes: Standard/Objective, Assignment Description, Additional Customization for Rubric (Optional) -// Audio icon for each textbox for readback? -// Paper clip for each textbox for attachments? -// 2 Buttons: 1 Generate Essay Button, 1 Send to Moodle Button -// 1 Frame to show the rubric that was generated? - -class EssayGeneration extends StatefulWidget { - const EssayGeneration({super.key, required this.title}); - final String title; - - @override - State createState() => _EssayGenerationState(); -} - -class _EssayGenerationState extends State -{ - //Holds values for user input fields - int _selectedPointScale = 3; // Default value - String _selectedGradeLevel = LearningLensConstants.gradeLevels.last; // Default value for GradeLevelDropdown - bool _isLoading = false; - // String? selectedLLM = 'Perplexity'; // default - LlmType? selectedLLM; - - // llm options - final List llmOptions = ['ChatGPT', 'CLAUDE', 'Perplexity']; - - // Variables to store the text inputs - final TextEditingController _standardObjectiveController = - TextEditingController(); - final TextEditingController _assignmentDescriptionController = - TextEditingController(); - final TextEditingController _additionalCustomizationController = - TextEditingController(); - - dynamic globalRubric; - dynamic rubricasjson; - - // api keys - // final perplexityApiKey = LocalStorageService.getPerplexityKey(); - // final openApiKey = LocalStorageService.getOpenAIKey(); - // final claudeApiKey = LocalStorageService.getClaudeKey(); - - // event handlers - void _handlePointScaleChanged(int? newValue) { - setState(() { - if (newValue != null) { - _selectedPointScale = newValue; - } - }); - } - - // Function to store the selected grade level value - void _handleGradeLevelChanged(String? newValue) { - setState(() { - if (newValue != null) { - _selectedGradeLevel = newValue; - } - }); - } - - // Handle LLM Selection - void _handleLLMChanged(LlmType? newValue) { - setState(() { - if (newValue != null) { - selectedLLM = newValue; - } - }); - } - - // Get api key for selected LLM - String getApiKey() { - switch (selectedLLM) { - case LlmType.CHATGPT: - return LocalStorageService.getOpenAIKey(); - case LlmType.GROK: - return LocalStorageService.getGrokKey(); - case LlmType.PERPLEXITY: - return LocalStorageService.getPerplexityKey(); - default: - return LocalStorageService.getOpenAIKey(); - } - } - - Future pingApi(String inputs) async { - try { - setState(() { - _isLoading = true; // Set loading state to true - }); - - String apiKey = - getApiKey(); // Get the correct API key based on the selected LLM - if (apiKey.isEmpty) { - throw Exception("API key is missing"); - } - - // Dynamically instantiate the appropriate LLM class based on the selectedLLM - dynamic llmInstance; - if (selectedLLM == LlmType.CHATGPT) { - llmInstance = OpenAiLLM(getApiKey()); - } else if (selectedLLM == LlmType.GROK) { - llmInstance = GrokLLM(getApiKey()); - } else if (selectedLLM == LlmType.PERPLEXITY) { - llmInstance = PerplexityLLM(getApiKey()); // Perplexity API class - } else { - throw Exception('Invalid LLM selected.'); - } - - String queryPrompt = ''' - I am building a program that creates rubrics when provided with assignment information. I will provide you with the following information about the assignment that needs a rubric: - Difficulty level, point scale, assignment objective, assignment description. You may also receive additional customization rules. - Using this information, you will reply with a rubric that includes 3-5 criteria. Your reply must only contain the JSON information, and begin with a {. - Remove any ``` from your output. - - You must reply with a representation of the rubric in JSON format that exactly matches this format: - { - "criteria": [ - { - "description": #CriteriaName, - "levels": [ - { "definition": #CriteriaDef, "score": #ScoreValue }, - ] - } - ] - } - #CriteriaName must be replaced with the name of the criteria. - #CriteriaDef must be replaced with a detailed description of what meeting that criteria would look like for each scale value. - #ScoreValue must be replaced with a number representing the score. The score for the lowest scale value will be 0, and the scores will increase by 1 for each scale. - You should create as many "levels" objects as there are point scale values. - Make sure the JSON exactly matches the format above, or you will receive an error. - Do not include any additional information in your response. - Here is the assignment information: - $inputs - '''; - globalRubric = await llmInstance.postToLlm(queryPrompt); - globalRubric = globalRubric.replaceAll('```', '').trim(); - return jsonDecode(globalRubric); - } catch (e) { - print("Error in API request: $e"); - return null; - } finally { - setState(() { - _isLoading = false; // Reset loading state to false - }); - } - } - - String getSelectedResponses() { - return ''' - Selected Grade Level: $_selectedGradeLevel - Selected Point Scale: $_selectedPointScale - Standard / Objective: ${_standardObjectiveController.text} - Assignment Description: ${_assignmentDescriptionController.text} - Additional Customization: ${_additionalCustomizationController.text} - '''; - } - - @override - void dispose() { - // Dispose the controllers when the widget is removed from the widget tree - _standardObjectiveController.dispose(); - _assignmentDescriptionController.dispose(); - _additionalCustomizationController.dispose(); - super.dispose(); - } - _EssayGenerationState(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(title: 'Create Essay Rubric', userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - // Using Row to split screen into two sections - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Left Column - Expanded( - flex: - 2, // This controls the space for the left side, bigger ratio - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text("Rubric Generator", - style: TextStyle(fontSize: 24)), - const SizedBox(height: 16), - - // Grade Level Dropdown - GradeLevelDropdown( - selectedGradeLevel: _selectedGradeLevel, - onChanged: _handleGradeLevelChanged, - ), - - const SizedBox(height: 16), - - // Point Scale Dropdown - PointScaleDropdown( - selectedPointScale: _selectedPointScale, - onChanged: _handlePointScaleChanged, - ), - - const SizedBox(height: 16), - - // LLM Selection Dropdown - DropdownButton( - value: selectedLLM, - onChanged: _handleLLMChanged, - // items: ['Perplexity', 'OpenAI', 'Claude'] - // .map>((String value) { - // return DropdownMenuItem( - // value: value, - // child: Text(value), - // ); - // }).toList(), - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text(llm.displayName, style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) ? Colors.black87 : Colors.grey, - ), - ), - ); - }).toList() - ), - - const SizedBox(height: 16), - - // Standard/objective - TextBox( - label: "Standard / Objective", - // icon: Icons.mic, - // secondaryIcon: Icons.attachment, - initialValue: '', - onChanged: (newValue) { - _standardObjectiveController.text = newValue!; - }, - maxLines: 2, - ), - const SizedBox(height: 16), - - // Assignment description - TextBox( - label: "Assignment Description", - // icon: Icons.mic, - // secondaryIcon: Icons.attachment, - initialValue: '', - onChanged: (newValue) { - _assignmentDescriptionController.text = newValue!; - }, - maxLines: 2, - ), - const SizedBox(height: 16), - - // Additional customization - TextBox( - label: "Additional Customization for Rubric (Optional)", - // icon: Icons.mic, - // secondaryIcon: Icons.attachment, - initialValue: '', - onChanged: (newValue) { - _additionalCustomizationController.text = newValue!; - }, - maxLines: 2, - ), - - const SizedBox(height: 16), - - // Generate Button - Button( - 'essay', - onPressed: () { - final result = getSelectedResponses(); - - pingApi(result).then((dynamic results) { - setState(() { - rubricasjson = globalRubric; - globalRubric = results; // Store the rubric - }); - }); - }, - ), - ], - ), - ), - - const SizedBox(width: 32), // Adds space between the two columns - - // Right Side - Expanded( - flex: 3, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - height: 600, - color: Colors.grey[200], - child: - _isLoading // Make the container dependent on the isLoading var - ? Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircularProgressIndicator(), // Loading spinner - SizedBox(height: 16), - Text( - "Generating Rubric...", // Display this text when we start loading - style: TextStyle( - fontSize: 18, color: Colors.black54), - ), - ], - ), - ) - : globalRubric != null && - globalRubric['criteria'] != null - ? SingleChildScrollView( - child: Table( - border: TableBorder - .all(), // Adds border to the table cells - columnWidths: const { - 0: FlexColumnWidth( - 1), // Description column - // Dynamically add scores per column - }, - children: [ - TableRow( - children: [ - Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - 'Criteria', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16), - ), - ), - - // Dynamically create score level headers - for (var level in globalRubric[ - 'criteria'][0][ - 'levels']) // Assuming all criteria have the same number of levels - Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - '${level['score']}', - style: TextStyle( - fontWeight: - FontWeight.bold, - fontSize: 16), - textAlign: TextAlign.center, - ), - ), - ], - ), - - // Create rows - for (var criteria - in globalRubric['criteria']) ...[ - TableRow( - children: [ - Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - criteria['description'], - style: TextStyle( - fontWeight: - FontWeight.bold), - ), - ), - - // Add score levels for each column - for (var level - in criteria['levels']) - Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - '${level['definition']}', - textAlign: TextAlign.center, - ), - ), - ], - ), - ], - ], - ), - ) - : Center( - child: Text( - "No Rubric Data Available", - style: TextStyle( - fontSize: 18, color: Colors.black54), - ), - ), - ), - const SizedBox(height: 16), - // Send to Moodle Button - Button( - "assessment", - onPressed: rubricasjson != null - ? () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - EssayEditPage(rubricasjson, _assignmentDescriptionController.text), - ), - ); - } - : null, // Disable button when rubricasjson is null - ), - ], - ), - ), - ], - ), - ), - ); - } -} - -// Create Class for Buttons -class Button extends StatelessWidget { - // Fields in this widget subclass are marked final - final String type; - final String text; - final String filters = ""; - final VoidCallback? onPressed; - Button._(this.type, this.text, {this.onPressed}); - - factory Button(String type, {VoidCallback? onPressed}) { - if (type == "assessment") { - return Button._( - type, - "Continue (Edit Rubric)", - onPressed: onPressed, - ); - } else if (type == "essay") { - return Button._( - type, - "Generate Rubric", - onPressed: onPressed, - ); - } else { - return Button._(type, ""); - } - } - @override - Widget build(BuildContext context) { - return OutlinedButton( - onPressed: onPressed, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [Icon(Icons.create), Text(text)], - )); - } -} - -class TextBox extends StatefulWidget { - // Create stateful widget to maintain persistence in textboxes from events - final String label; - // final IconData icon; - // final IconData secondaryIcon; - final String initialValue; - final ValueChanged onChanged; - final int maxLines; - - const TextBox({ - super.key, - required this.label, - // required this.icon, - // required this.secondaryIcon, - required this.initialValue, - required this.onChanged, - this.maxLines = 1, - }); - - @override - TextBoxState createState() => TextBoxState(); -} - -class TextBoxState extends State { - // State within - late TextEditingController _controller; - - @override - void initState() { - super.initState(); - // Initialize controller with initial value - _controller = TextEditingController(text: widget.initialValue); - // Listen for changes - _controller.addListener(() { - widget.onChanged(_controller.text); // Call the passed onChanged function - }); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return TextField( - controller: _controller, // Use the controller initialized in initState - maxLines: widget.maxLines, - decoration: InputDecoration( - labelText: widget.label, - // prefixIcon: Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Icon(widget.icon), - // SizedBox(height: 4), - // Icon(widget.secondaryIcon), - // ], - // ), - ), - ); - } -} - -class PointScaleDropdown extends StatelessWidget { - final int selectedPointScale; - // We need to store the value of the int the user inputs - final ValueChanged onChanged; - - const PointScaleDropdown({ - Key? key, - required this.selectedPointScale, - required this.onChanged, - }) : super(key: key); - - void _handleValueChanged(int? newValue) { - // Additional Logic - onChanged(newValue); // Call the passed onChanged function - } - - @override - Widget build(BuildContext context) { - return DropdownButtonFormField( - decoration: const InputDecoration(labelText: "Point Scale"), - value: selectedPointScale, - items: [1, 2, 3, 4, 5].map((int value) { - return DropdownMenuItem( - value: value, - child: Text(value.toString()), - ); - }).toList(), - onChanged: _handleValueChanged, - ); - } -} - -class GradeLevelDropdown extends StatelessWidget { - final String selectedGradeLevel; - // We need to store the value of the string the user inputs - final ValueChanged onChanged; - - const GradeLevelDropdown({ - Key? key, - required this.selectedGradeLevel, - required this.onChanged, - }) : super(key: key); - - void _handleTextChanged(String? newValue) { - // Additional Logic - onChanged(newValue); // Call the passed onChanged function - } - - @override - Widget build(BuildContext context) { - return DropdownButtonFormField( - decoration: const InputDecoration(labelText: "Grade Level"), - value: selectedGradeLevel.isNotEmpty ? selectedGradeLevel : null, - items: LearningLensConstants.gradeLevels - .map((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - onChanged: _handleTextChanged, - ); - } -} diff --git a/team_a/teamA/lib/Views/essays_view.dart b/team_a/teamA/lib/Views/essays_view.dart deleted file mode 100644 index 21f477d6..00000000 --- a/team_a/teamA/lib/Views/essays_view.dart +++ /dev/null @@ -1,333 +0,0 @@ -import "package:flutter/material.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Views/view_submissions.dart"; -import "package:learninglens_app/beans/assignment.dart"; -import "package:learninglens_app/beans/participant.dart"; -import "package:learninglens_app/beans/course.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import "package:learninglens_app/beans/submission_with_grade.dart"; -import "package:learninglens_app/content_carousel.dart"; - -// The Page -class EssaysView extends StatefulWidget { - EssaysView({super.key, this.essayID = 0, this.courseID = 0}); - final int essayID; - final int? courseID; - - @override - _EssaysState createState() => _EssaysState(); -} - -class _EssaysState extends State { - late Future> essays; - Assignment? selectedEssay; - late Future> futureSubmissionsWithGrades; - late Future> futureParticipants; - String? submissionError; // To store error message for submissions - String? participantError; // To store error message for participants - - @override - void initState() { - super.initState(); - essays = getAllEssays(widget.courseID); - // Initialize with placeholder futures to avoid null errors - futureSubmissionsWithGrades = Future.value([]); - futureParticipants = Future.value([]); - } - - // Helper method to fetch submissions with error handling - Future> fetchSubmissionsWithGrades( - int essayId) async { - try { - return await LmsFactory.getLmsService().getSubmissionsWithGrades(essayId); - } on UnimplementedError catch (e) { - setState(() { - submissionError = - "Submissions/Grading feature is currently not available for Google Classroom. Please reach out to the developer for more information."; - }); - return []; // Return empty list to avoid breaking the FutureBuilder - } catch (e) { - setState(() { - submissionError = "Error fetching submissions: $e"; - }); - return []; - } - } - - // Helper method to fetch participants with error handling - Future> fetchCourseParticipants(String courseId) async { - try { - return await LmsFactory.getLmsService().getCourseParticipants(courseId); - } on UnimplementedError catch (e) { - setState(() { - participantError = "Participants feature is not yet implemented."; - }); - return []; // Return empty list to avoid breaking the FutureBuilder - } catch (e) { - setState(() { - participantError = "Error fetching participants: $e"; - }); - return []; - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Essays', - onRefresh: () { - setState(() { - essays = getAllEssays(widget.courseID); - }); - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Column( - children: [ - Row(children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: CreateButton('essay')) - ]), - Expanded( - child: FutureBuilder>( - future: essays, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error loading essays')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No essays found')); - } else { - final essayList = snapshot.data!; - - return LayoutBuilder( - builder: (context, constraints) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: ListView.builder( - itemCount: essayList.length, - itemBuilder: (context, index) { - final essay = essayList[index]; - final activeCourse = - getCourse(essay.courseId); - if (essay.id == widget.essayID) { - selectedEssay = essay; - } - return ListTile( - title: Text( - '${essay.name} (${activeCourse.shortName}${activeCourse.courseId})'), - subtitle: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - 'Due: ${essay.dueDate == null ? "No due date set" : Course.dateFormatted(essay.dueDate!)}'), - ], - ), - tileColor: selectedEssay == essay - ? Theme.of(context) - .colorScheme - .primary - .withOpacity(0.1) - : null, - onTap: () { - setState(() { - selectedEssay = essay; - submissionError = null; // Reset error - participantError = null; // Reset error - futureSubmissionsWithGrades = - fetchSubmissionsWithGrades( - essay.id!); - futureParticipants = - fetchCourseParticipants( - essay.courseId.toString()); - }); - }, - ); - }, - ), - ), - ), - Expanded( - flex: 2, - child: selectedEssay == null && widget.essayID == 0 - ? Center( - child: - Text('Select an essay to view details')) - : Column( - children: [ - Container( - decoration: BoxDecoration( - border: - Border.all(color: Colors.grey), - borderRadius: - BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: - const EdgeInsets.all( - 8.0), - child: Text('Essay Prompt', - style: TextStyle( - fontSize: 20))), - Text(selectedEssay - ?.description ?? - getEssay(widget.essayID, - widget.courseID) - ?.description ?? - "No description is available."), - ], - ), - ), - ), - ), - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - border: - Border.all(color: Colors.grey), - borderRadius: - BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - 'Student Submissions', - style: TextStyle( - fontSize: 20)), - ), - Expanded( - child: submissionError != null - ? Center( - child: Column( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons - .construction, // Under development icon - size: 48.0, - color: Colors - .orange, - ), - SizedBox( - height: 16.0), - Text( - submissionError!, - textAlign: - TextAlign - .center, - style: - TextStyle( - fontSize: - 16.0, - color: Colors - .grey[ - 700], - ), - ), - ], - ), - ) - : SubmissionList( - key: ValueKey( - selectedEssay - ?.id ?? - widget - .essayID), - assignmentId: - selectedEssay - ?.id ?? - widget - .essayID, - courseId: selectedEssay - ?.courseId - .toString() ?? - widget.courseID - .toString(), - ), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ], - ); - }, - ); - } - }, - ), - ), - ], - ), - ); - } -} - -// Helper function that pulls the quizzes from all the user's courses -Future> getAllEssays(int? courseID) async { - List result = []; - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (courseID == 0 || courseID == null || c.id == courseID) { - result.addAll(c.essays ?? []); - } - } - return result; -} - -Assignment? getEssay(int? essayID, int? courseID) { - Assignment? result; - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (courseID == 0 || courseID == null || c.id == courseID) { - for (Assignment a in c.essays ?? []) { - if (a.id == essayID) { - result = a; - } - } - } - } - return result; -} - -// Helper function that gets the course number for the quiz -Course getCourse(int? courseID) { - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (c.id == courseID) { - return c; - } - } - throw "No course found."; -} diff --git a/team_a/teamA/lib/Views/g_assignment_create.dart b/team_a/teamA/lib/Views/g_assignment_create.dart deleted file mode 100644 index 19d9a414..00000000 --- a/team_a/teamA/lib/Views/g_assignment_create.dart +++ /dev/null @@ -1,298 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/google_classroom/google_classroom_api.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/Controller/main_controller.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; -import 'package:intl/intl.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -class CreateAssignmentPage extends StatefulWidget { - GoogleClassroomApi _googleClassroomApi = GoogleClassroomApi(); - - @override - _CreateAssignmentPageState createState() => _CreateAssignmentPageState(); -} - -class _CreateAssignmentPageState extends State { - final _formKey = GlobalKey(); - String? _selectedCourseId; - int? _points; - DateTime? _dueDate; - TimeOfDay? _dueTime; - final String _topic = 'Essay'; // Made static with fixed value - String? _title; - String? _instructions; - List _courses = []; - bool _isLoading = false; - bool _isSubmitting = false; - final MainController _controller = MainController(); - - @override - void initState() { - super.initState(); - _fetchCourses(); - } - - Future _getToken() async { - final token = LocalStorageService.getGoogleAccessToken(); - if (token == null) { - print('Error: No valid OAuth token. Ensure the required scopes are enabled.'); - } - return token; - } - - Future _fetchCourses() async { - setState(() => _isLoading = true); - final token = await _getToken(); - if (token == null) return; - - final response = await http.get( - Uri.parse('https://classroom.googleapis.com/v1/courses'), - headers: {'Authorization': 'Bearer $token'}, - ); - if (response.statusCode == 200) { - setState(() => _courses = jsonDecode(response.body)['courses'] ?? []); - } else { - print('Courses fetch error: ${response.statusCode}'); - } - setState(() => _isLoading = false); - } - - Future _selectDueDate(BuildContext context) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime(2101), - ); - if (picked != null) { - setState(() { - _dueDate = picked; - }); - } - } - - Future _selectDueTime(BuildContext context) async { - final TimeOfDay? picked = await showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ); - if (picked != null) { - setState(() { - _dueTime = picked; - }); - } - } - - Future _createAssignment() async { - if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); - - if ((_dueDate != null && _dueTime == null) || - (_dueDate == null && _dueTime != null)) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Please select both due date and time.'), - backgroundColor: Colors.red, - ), - ); - return; - } - - setState(() => _isSubmitting = true); - - final token = await _getToken(); - if (token == null) { - setState(() => _isSubmitting = false); - return; - } - - final url = Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$_selectedCourseId/courseWork'); - final headers = { - 'Authorization': 'Bearer $token', - 'Content-Type': 'application/json', - }; - - Map requestBody = { - 'title': _title, - 'description': _instructions, - 'state': 'PUBLISHED', - 'workType': 'ASSIGNMENT', - 'maxPoints': _points, - }; - - if (_dueDate != null && _dueTime != null) { - requestBody['dueDate'] = { - 'year': _dueDate!.year, - 'month': _dueDate!.month, - 'day': _dueDate!.day, - }; - requestBody['dueTime'] = { - 'hours': _dueTime!.hour, - 'minutes': _dueTime!.minute, - 'seconds': 0, - }; - } - - String? topicIdNew = await widget._googleClassroomApi.getTopicId(_selectedCourseId!, _topic); - if (topicIdNew != null) { - requestBody['topicId'] = topicIdNew; - } - - final body = jsonEncode(requestBody); - - try { - final response = await http.post(url, headers: headers, body: body); - - if (response.statusCode == 200) { - print('Assignment created successfully!'); - Navigator.pop(context); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Error creating assignment: ${response.statusCode}'), - backgroundColor: Colors.red, - ), - ); - } - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Network error: ${e.toString()}'), - backgroundColor: Colors.red, - ), - ); - } finally { - setState(() => _isSubmitting = false); - } - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Create Assignment', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: _isLoading - ? Center(child: CircularProgressIndicator()) - : SingleChildScrollView( - padding: const EdgeInsets.all(16.0), - child: Card( - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - DropdownButtonFormField( - decoration: InputDecoration( - labelText: 'Course', - border: OutlineInputBorder(), - ), - value: _selectedCourseId, - items: _courses.map((course) { - return DropdownMenuItem( - value: course['id'], - child: Text(course['name'] ?? 'Unnamed Course'), - ); - }).toList(), - onChanged: (value) { - setState(() => _selectedCourseId = value); - }, - validator: (value) => - value == null ? 'Please select a course' : null, - onSaved: (value) => _selectedCourseId = value, - ), - SizedBox(height: 16), - TextFormField( - decoration: InputDecoration( - labelText: 'Title', - border: OutlineInputBorder(), - ), - validator: (value) => - value!.isEmpty ? 'Please enter a title' : null, - onSaved: (value) => _title = value, - ), - SizedBox(height: 16), - TextFormField( - decoration: InputDecoration( - labelText: 'Instructions', - border: OutlineInputBorder(), - ), - maxLines: 3, - onSaved: (value) => _instructions = value, - ), - SizedBox(height: 16), - TextFormField( - decoration: InputDecoration( - labelText: 'Points', - border: OutlineInputBorder(), - ), - keyboardType: TextInputType.number, - validator: (value) { - if (value!.isEmpty) return 'Please enter points'; - if (int.tryParse(value) == null) - return 'Please enter a valid number'; - return null; - }, - onSaved: (value) => _points = int.parse(value!), - ), - SizedBox(height: 16), - ListTile( - title: Text(_dueDate == null - ? 'Select Due Date' - : 'Due Date: ${DateFormat('yyyy-MM-dd').format(_dueDate!)}'), - trailing: Icon(Icons.calendar_today), - onTap: () => _selectDueDate(context), - ), - ListTile( - title: Text(_dueTime == null - ? 'Select Due Time' - : 'Due Time: ${_dueTime!.format(context)}'), - trailing: Icon(Icons.access_time), - onTap: () => _selectDueTime(context), - ), - SizedBox(height: 16), - Text( - 'Assessment Type: $_topic', - style: TextStyle( - fontSize: 16, - color: Colors.grey[600], - ), - ), - SizedBox(height: 24), - ElevatedButton( - onPressed: _isSubmitting ? null : _createAssignment, - style: ElevatedButton.styleFrom( - minimumSize: Size(double.infinity, 50), - ), - child: _isSubmitting - ? SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 2, - ), - ) - : Text('Create Assignment'), - ), - ], - ), - ), - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/g_lesson_plan.dart b/team_a/teamA/lib/Views/g_lesson_plan.dart deleted file mode 100644 index 1c96a21a..00000000 --- a/team_a/teamA/lib/Views/g_lesson_plan.dart +++ /dev/null @@ -1,725 +0,0 @@ -// This file contains the code for the Google Lesson Plans page. -// This page allows users to create, edit, and delete lesson plans for Google Classroom courses. -// Users can select a course, grade level, and enter lesson plan details manually or generate them with AI. -import "dart:convert"; -import "package:flutter/material.dart"; -import "package:http/http.dart" as http; -import "package:learninglens_app/Api/llm/llm_api_modules_base.dart"; -import "package:learninglens_app/Api/lms/constants/learning_lens.constants.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Api/lms/google_classroom/google_classroom_api.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import "package:learninglens_app/beans/course.dart"; -import "package:learninglens_app/services/local_storage_service.dart"; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:logging/logging.dart'; - -class GoogleLessonPlans extends StatefulWidget { - @override - State createState() => _LessonPlanState(); -} - -class _LessonPlanState extends State { - List? courses = []; - String? selectedCourse; - List courseworkMaterials = []; - dynamic selectedMaterial; - bool isEditing = false; - bool useAiGeneration = false; - String? selectedLLM; - String? selectedGradeLevel; - - // Loading flags - bool isLoadingCourses = false; - bool isLoadingLessonPlans = false; // New loading flag for lesson plans - bool isGeneratingAI = false; - bool isSaving = false; - bool isDeleting = false; - bool isUpdating = false; - - // API key availability flags - bool hasOpenAIKey = false; - bool hasGrokKey = false; - bool hasPerplexityKey = false; - - final TextEditingController lessonPlanNameController = - TextEditingController(); - final TextEditingController manualEntryController = TextEditingController(); - final TextEditingController aiPromptDetailsController = - TextEditingController(); - final log = Logger('GoogleLessonPlans'); - final GoogleClassroomApi googleClassroomApi = GoogleClassroomApi(); - - @override - void dispose() { - lessonPlanNameController.dispose(); - manualEntryController.dispose(); - aiPromptDetailsController.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - _loadCourses(); - _checkApiKeys(); - } - - Future _checkApiKeys() async { - setState(() { - String openAIKey = LocalStorageService.getOpenAIKey() ?? ''; - String grokKey = LocalStorageService.getGrokKey() ?? ''; - String perplexityKey = LocalStorageService.getPerplexityKey() ?? ''; - - hasOpenAIKey = openAIKey.isNotEmpty; - hasGrokKey = grokKey.isNotEmpty; - hasPerplexityKey = perplexityKey.isNotEmpty; - // print('OpenAI key: $hasOpenAIKey'); - // hasGrokKey = LocalStorageService.getGrokKey() as bool; - // print('Grok key: $hasGrokKey'); - // hasPerplexityKey = LocalStorageService.getPerplexityKey() as bool; - // print('Perplexity key: $hasPerplexityKey'); - }); - } - - Future _getToken() async { - final token = LocalStorageService.getGoogleAccessToken(); - if (token == null) { - log.severe('Error: No valid OAuth token.'); - } - return token; - } - - Future _loadCourses() async { - setState(() { - isLoadingCourses = true; - }); - try { - List fetchedCourses = - await LmsFactory.getLmsService().getUserCourses(); - setState(() { - courses = fetchedCourses; - selectedCourse = null; - }); - } catch (e) { - log.severe('Failed to load courses: $e'); - } finally { - setState(() { - isLoadingCourses = false; - }); - } - } - - Future _loadLessonPlan(String courseId) async { - setState(() { - isLoadingLessonPlans = true; // Start loading indicator - }); - try { - final accessToken = await _getToken(); - if (accessToken == null) return; - - final url = Uri.parse( - 'https://classroom.googleapis.com/v1/courses/$courseId/courseWorkMaterials'); - final headers = { - 'Authorization': 'Bearer $accessToken', - 'Content-Type': 'application/json' - }; - final response = await http.get(url, headers: headers); - - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - setState(() { - courseworkMaterials = data['courseWorkMaterial'] ?? []; - selectedMaterial = null; - isEditing = false; - }); - } else { - print('Error loading coursework materials: ${response.statusCode}'); - setState(() { - courseworkMaterials = []; - }); - } - } catch (e) { - print('Error loading coursework materials: $e'); - setState(() { - courseworkMaterials = []; - }); - } finally { - setState(() { - isLoadingLessonPlans = false; // Stop loading indicator - }); - } - } - - Future generateLessonPlanWithAI() async { - setState(() { - isGeneratingAI = true; - }); - - final openApiKey = LocalStorageService.getOpenAIKey(); - final grokApiKey = LocalStorageService.getGrokKey(); - final perplexityApiKey = LocalStorageService.getPerplexityKey(); - - try { - late final LLM aiModel; - switch (selectedLLM) { - case 'ChatGPT': - aiModel = OpenAiLLM(openApiKey); - break; - case 'Grok': - aiModel = GrokLLM(grokApiKey); - break; - case 'Perplexity': - aiModel = PerplexityLLM(perplexityApiKey); - break; - default: - throw Exception('Unsupported AI model: $selectedLLM'); - } - - String prompt = - "Create a concise, all-text lesson plan for ${lessonPlanNameController.text} for grade ${selectedGradeLevel == 'K' ? 'Kindergarten' : selectedGradeLevel} covering ${manualEntryController.text}. ${aiPromptDetailsController.text}. Write it as student-facing content for studying, essays, and quizzes. Use plain text, no Markdown, in 500 words."; - - var result = await aiModel.generate(prompt); - setState(() { - manualEntryController.text = result; - }); - } catch (e) { - log.severe("Error generating lesson plan: $e"); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to generate lesson plan: $e')), - ); - } finally { - setState(() { - isGeneratingAI = false; - }); - } - } - - void _showLessonPlanDialog(dynamic lessonPlan) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(lessonPlan['title'] ?? 'Untitled'), - content: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width * 0.4, - child: Text(lessonPlan['description'] ?? '', - textAlign: TextAlign.left), - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text("Close"), - ), - ], - ); - }, - ); - } - - void _clearFormFields() { - lessonPlanNameController.clear(); - manualEntryController.clear(); - aiPromptDetailsController.clear(); - setState(() { - selectedGradeLevel = null; - useAiGeneration = false; - selectedLLM = null; - isEditing = false; - selectedMaterial = null; - }); - } - - bool _canSubmit() { - return selectedCourse != null && - selectedGradeLevel != null && - lessonPlanNameController.text.isNotEmpty && - manualEntryController.text.isNotEmpty; - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Lesson Plans', - onRefresh: _loadCourses, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: isLoadingCourses - ? Center(child: CircularProgressIndicator()) - : SingleChildScrollView( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Padding( - padding: EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Add New Lesson Plan', - style: TextStyle( - fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 20), - DropdownButtonFormField( - value: selectedCourse, - items: [ - DropdownMenuItem( - value: null, - child: Text('Select Course'), - ), - ...(courses - ?.map>((course) { - return DropdownMenuItem( - value: course.id.toString(), - child: Text(course.fullName), - ); - }).toList() ?? - []) - ], - onChanged: (value) async { - setState(() { - selectedCourse = value; - }); - if (value != null) { - await _loadLessonPlan(value); - } - }, - decoration: InputDecoration( - labelText: 'Course', - border: OutlineInputBorder()), - ), - SizedBox(height: 20), - DropdownButtonFormField( - value: selectedGradeLevel, - items: LearningLensConstants.gradeLevels - .map>((grade) { - return DropdownMenuItem( - value: grade, child: Text(grade)); - }).toList(), - onChanged: (value) { - setState(() { - selectedGradeLevel = value; - }); - }, - decoration: InputDecoration( - labelText: 'Grade Level', - border: OutlineInputBorder(), - errorText: selectedGradeLevel == null && isSaving - ? 'Grade Level is required' - : null, - ), - validator: (value) => - value == null ? 'Required' : null, - ), - SizedBox(height: 20), - TextField( - controller: lessonPlanNameController, - decoration: InputDecoration( - labelText: 'Lesson Plan Name', - border: OutlineInputBorder(), - errorText: - lessonPlanNameController.text.isEmpty && - (isSaving || isGeneratingAI) - ? 'Lesson Plan Name is required' - : null, - ), - onChanged: (value) => setState(() {}), - ), - SizedBox(height: 20), - CheckboxListTile( - title: Text("Generate Lesson Plan with AI"), - value: useAiGeneration, - onChanged: (bool? value) { - setState(() { - useAiGeneration = value!; - if (!useAiGeneration) { - selectedLLM = null; - manualEntryController.clear(); - aiPromptDetailsController.clear(); - } - }); - }, - ), - if (useAiGeneration) - Column( - children: [ - IgnorePointer( - ignoring: !(hasOpenAIKey || - hasGrokKey || - hasPerplexityKey), - child: DropdownButtonFormField( - value: selectedLLM, - decoration: InputDecoration( - labelText: "Select AI Model", - border: OutlineInputBorder(), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: (hasOpenAIKey || - hasGrokKey || - hasPerplexityKey) - ? Colors.grey - : Colors.grey.withOpacity(0.3), - ), - ), - ), - onChanged: (String? newValue) { - if (newValue != null) { - setState(() => selectedLLM = newValue); - } - }, - items: [ - DropdownMenuItem( - value: 'ChatGPT', - enabled: hasOpenAIKey, - child: Text( - 'ChatGPT${!hasOpenAIKey ? " (API Key Required)" : ""}', - style: TextStyle( - color: hasOpenAIKey - ? null - : Colors.grey, - ), - ), - ), - DropdownMenuItem( - value: 'Grok', - enabled: hasGrokKey, - child: Text( - 'Grok${!hasGrokKey ? " (API Key Required)" : ""}', - style: TextStyle( - color: - hasGrokKey ? null : Colors.grey, - ), - ), - ), - DropdownMenuItem( - value: 'Perplexity', - enabled: hasPerplexityKey, - child: Text( - 'Perplexity${!hasPerplexityKey ? " (API Key Required)" : ""}', - style: TextStyle( - color: hasPerplexityKey - ? null - : Colors.grey, - ), - ), - ), - ], - ), - ), - if (!hasOpenAIKey && - !hasGrokKey && - !hasPerplexityKey) - Padding( - padding: EdgeInsets.only(top: 8.0), - child: Text( - 'Please add an API key in settings to use AI generation', - style: TextStyle( - color: Colors.red, fontSize: 12), - ), - ), - SizedBox(height: 20), - TextField( - controller: aiPromptDetailsController, - maxLines: 3, - decoration: InputDecoration( - labelText: - 'Additional Details for AI Prompt', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 20), - ElevatedButton( - onPressed: selectedLLM != null && - (selectedLLM == 'ChatGPT' && - hasOpenAIKey || - selectedLLM == 'Grok' && - hasGrokKey || - selectedLLM == 'Perplexity' && - hasPerplexityKey) && - selectedGradeLevel != null && - lessonPlanNameController - .text.isNotEmpty - ? () async { - await generateLessonPlanWithAI(); - } - : null, - child: isGeneratingAI - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2), - ) - : Text('Generate Lesson Plan'), - ), - ], - ), - SizedBox(height: 20), - TextField( - controller: manualEntryController, - maxLines: 8, - decoration: InputDecoration( - labelText: 'Enter/Edit Lesson Plan', - border: OutlineInputBorder(), - errorText: - manualEntryController.text.isEmpty && isSaving - ? 'Lesson Plan details are required' - : null, - ), - onChanged: (value) => setState(() {}), - ), - SizedBox(height: 20), - ElevatedButton( - onPressed: _canSubmit() - ? () async { - setState(() { - isSaving = true; - }); - String? materialId = - await googleClassroomApi - .createCourseWorkMaterial( - selectedCourse!, - lessonPlanNameController.text, - manualEntryController.text, - "https://example.com", - ); - if (materialId != null) { - await _loadLessonPlan(selectedCourse!); - _clearFormFields(); - } - setState(() { - isSaving = false; - }); - } - : null, - child: isSaving - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2), - ) - : Text('Submit'), - ), - ], - ), - ), - ), - Expanded( - flex: 3, - child: Padding( - padding: EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Existing Lesson Plans', - style: TextStyle( - fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 20), - isLoadingLessonPlans - ? Center(child: CircularProgressIndicator()) - : Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0)), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 20, - columns: [ - DataColumn( - label: SizedBox( - width: 150, - child: Text('Name', - style: TextStyle( - fontWeight: - FontWeight.bold)))), - DataColumn( - label: SizedBox( - width: 300, - child: Text('Lesson Plan', - style: TextStyle( - fontWeight: - FontWeight.bold)))), - DataColumn( - label: Text('Select', - style: TextStyle( - fontWeight: - FontWeight.bold))), - DataColumn( - label: Text('View', - style: TextStyle( - fontWeight: - FontWeight.bold))), - ], - rows: courseworkMaterials.map((material) { - bool isSelected = - selectedMaterial == material; - return DataRow( - cells: [ - DataCell( - ConstrainedBox( - constraints: BoxConstraints( - maxWidth: 150), - child: Text( - material['title'] ?? - 'Untitled', - overflow: - TextOverflow.ellipsis), - ), - ), - DataCell( - ConstrainedBox( - constraints: BoxConstraints( - maxWidth: 300), - child: SingleChildScrollView( - scrollDirection: - Axis.vertical, - child: Text( - material['description'] ?? - '', - maxLines: 3, - overflow: TextOverflow - .ellipsis), - ), - ), - ), - DataCell(Checkbox( - value: isSelected, - onChanged: (bool? selected) { - setState(() { - selectedMaterial = selected! - ? material - : null; - if (selectedMaterial != - null) { - lessonPlanNameController - .text = - selectedMaterial[ - 'title'] ?? - ''; - manualEntryController.text = - selectedMaterial[ - 'description'] ?? - ''; - isEditing = false; - } else { - _clearFormFields(); - } - }); - }, - )), - DataCell(ElevatedButton( - onPressed: () => - _showLessonPlanDialog( - material), - child: Text("View"), - )), - ], - ); - }).toList(), - ), - ), - ), - SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton( - onPressed: selectedMaterial != null - ? () async { - setState(() { - isDeleting = true; - }); - await googleClassroomApi - .deleteCourseWorkMaterial( - selectedCourse!, - selectedMaterial['id']); - await _loadLessonPlan(selectedCourse!); - _clearFormFields(); - setState(() { - isDeleting = false; - }); - } - : null, - child: isDeleting - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2), - ) - : Text('Delete Selected'), - ), - ElevatedButton( - onPressed: selectedMaterial != null - ? () => setState(() { - isEditing = true; - lessonPlanNameController.text = - selectedMaterial['title'] ?? ''; - manualEntryController.text = - selectedMaterial['description'] ?? - ''; - }) - : null, - child: Text('Edit Selected'), - ), - ElevatedButton( - onPressed: isEditing && selectedMaterial != null - ? () async { - setState(() { - isUpdating = true; - }); - try { - await googleClassroomApi - .updateCourseWorkMaterial( - selectedCourse!, - selectedMaterial['id'], - lessonPlanNameController.text, - manualEntryController.text, - ); - await _loadLessonPlan( - selectedCourse!); - _clearFormFields(); - } catch (e) { - print('Error during update: $e'); - ScaffoldMessenger.of(context) - .showSnackBar( - SnackBar( - content: Text( - 'Failed to update lesson plan: $e')), - ); - } finally { - setState(() { - isUpdating = false; - }); - } - } - : null, - child: isUpdating - ? SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2), - ) - : Text('Save Update'), - ), - ], - ), - ], - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/g_quiz_question_page.dart b/team_a/teamA/lib/Views/g_quiz_question_page.dart deleted file mode 100644 index 7e8f7af9..00000000 --- a/team_a/teamA/lib/Views/g_quiz_question_page.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/google_classroom/google_lms_service.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/g_question_form_data.dart'; -import 'dart:convert'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:url_launcher/url_launcher.dart'; -import 'package:flutter/services.dart'; // Added for clipboard functionality - -// Dynamic form widget with table inside a card -class DynamicForm extends StatelessWidget { - final FormData formData; - - const DynamicForm({super.key, required this.formData}); - - // Determine question type based on options - String _getQuestionType(List options) { - if (options.isEmpty) { - return 'Short Answer'; - } else if (options.length == 2) { - return 'True/False'; - } else { - return 'Multiple Choice'; - } - } - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - // Title - Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: Text( - formData.title, - style: Theme.of(context) - .textTheme - .headlineSmall - ?.copyWith(fontWeight: FontWeight.bold), - ), - ), - // Card containing assignment details and table - Card( - elevation: 4, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.0), - ), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - // Assignment Details - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Start Date: ', - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text(formData.startDate ?? 'N/A'), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'End Date: ', - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text(formData.endDate ?? 'N/A'), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Form URL: ', - style: TextStyle(fontWeight: FontWeight.bold), - ), - GestureDetector( - onTap: () async { - if (formData.formUrl != null) { - final Uri url = Uri.parse(formData.formUrl!); - if (await canLaunchUrl(url)) { - await launchUrl(url); - } else { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Cannot launch URL')), - ); - } - } - }, - child: Text( - formData.formUrl ?? 'N/A', - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline, - ), - ), - ), - if (formData.formUrl != null) ...[ - IconButton( - icon: const Icon(Icons.copy), - onPressed: () { - Clipboard.setData( - ClipboardData(text: formData.formUrl!)); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('URL copied to clipboard')), - ); - }, - ), - ], - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Status: ', - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text(formData.status ?? 'N/A'), - ], - ), - const SizedBox(height: 16), - // Table - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 20, - dataRowHeight: 60, - headingRowColor: MaterialStateProperty.all( - Colors.blueAccent.withOpacity(0.1)), - border: TableBorder.all( - color: Colors.grey, - width: 1.0, - ), - columns: const [ - DataColumn( - label: Center( - child: Text( - 'Question No.', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - DataColumn( - label: Center( - child: Text( - 'Question', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - DataColumn( - label: Center( - child: Text( - 'Type', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - DataColumn( - label: Center( - child: Text( - 'Options', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - ], - rows: formData.questions.asMap().entries.map((entry) { - int index = entry.key + 1; - QuestionData questionData = entry.value; - return DataRow(cells: [ - DataCell(Text('$index')), - DataCell( - SizedBox( - width: 400, - child: Text( - questionData.question, - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 2, - ), - ), - ), - DataCell( - Text( - _getQuestionType(questionData.options), - ), - ), - DataCell( - SizedBox( - width: 300, - child: Text( - questionData.options.isEmpty - ? 'N/A' - : questionData.options.join(', '), - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 2, - ), - ), - ), - ]); - }).toList(), - ), - ), - ], - ), - ), - ), - ], - ), - ), - ), - ); - } -} - -// Updated QuizQuestionPage -class QuizQuestionPage extends StatefulWidget { - final String coursedId; - final String assessmentId; - - const QuizQuestionPage( - {super.key, required this.coursedId, required this.assessmentId}); - - @override - State createState() => _QuizQuestionPageState(); -} - -class _QuizQuestionPageState extends State { - late Future _formDataFuture; - - @override - void initState() { - super.initState(); - print( - 'Course ID from QuizQuestion Page: ${widget.coursedId}, Assessment ID from QuizQuestion Page: ${widget.assessmentId}'); - GoogleLmsService googleLmsService = GoogleLmsService(); - _formDataFuture = googleLmsService.getAssignmentFormQuestions( - widget.coursedId, widget.assessmentId); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Quiz Questions Here ....', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: FutureBuilder( - future: _formDataFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.error_outline, color: Colors.red, size: 60), - const SizedBox(height: 16), - Text( - 'Error: ${snapshot.error.toString()}', - style: const TextStyle(fontSize: 18, color: Colors.red), - textAlign: TextAlign.center, - ), - ], - ), - ); - } else if (snapshot.hasData && snapshot.data!.questions.isNotEmpty) { - return DynamicForm(formData: snapshot.data!); - } else { - return const Center( - child: Text( - 'No questions found in the Google Form.', - style: TextStyle(fontSize: 18, color: Colors.grey), - ), - ); - } - }, - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/iep_page.dart b/team_a/teamA/lib/Views/iep_page.dart deleted file mode 100644 index 9c5b182d..00000000 --- a/team_a/teamA/lib/Views/iep_page.dart +++ /dev/null @@ -1,681 +0,0 @@ -import "package:flutter/material.dart"; -import 'package:intl/intl.dart'; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/quiz_override'; -import 'package:learninglens_app/beans/override.dart'; - -class IepPage extends StatefulWidget { - IepPage(); - - @override - State createState() { - return _IepPageState(); - } -} - -class _IepPageState extends State { - TextEditingController _dateController = TextEditingController(); - TextEditingController _cutoffDateController = TextEditingController(); - bool? isChecked1 = false; - bool? isChecked2 = false; - String? selectedCourse; - String? selectedAssignment; - String? selectedEssay; - int? essayId; - int? quizId; - int? userId; - int? newEndTime; - String selectedDate = 'Select a Date'; - Future>? participants; - Future>? essay; - Future>? quiz; - List type = ['Quiz', 'Essay']; - double? epochTime; - double? epochTime2; - List attempts = ['Unlimited', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; - int? selectedAttempt; - - void _selectDate(BuildContext context) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (picked != null && picked != DateTime.now()) { - setState(() { - _dateController.text = "${picked.toLocal()}".split(' ')[0]; - epochTime = picked.millisecondsSinceEpoch / 1000.round(); - }); - } - } - - void _selectCutOffDate(BuildContext context) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2000), - lastDate: DateTime(2100), - ); - if (picked != null && picked != DateTime.now()) { - setState(() { - _cutoffDateController.text = "${picked.toLocal()}".split(' ')[0]; - epochTime2 = picked.millisecondsSinceEpoch / 1000.round(); - }); - } - } - - // void _getAssignmentOverride() async { ***** Not used ***** - // await MoodleLmsService().getAssignmentOverrides(); - // } - - // Function to show details in a dialog - void _showDetailsDialog(BuildContext context, Override override) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text("Details"), - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Student Name: ${override.fullname}"), - Text("Course Name: ${override.courseName}"), - Text("Assignment: ${override.type}: ${override.assignmentName}"), - Text("Extended Due Date: ${formatDate(override.endTime?.toString())}"), - Text("Cut Off Date: ${formatDate(override.cutoffTime?.toString())}"), - Text("Attempts: ${override.attempts?.toString() ?? 'N/A'}"), - ], - ), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text("Close"), - ), - ], - ); - }, - ); - } - - @override - Widget build(BuildContext context) { - final screenWidth = MediaQuery.of(context).size.width; - - return Scaffold( - appBar: CustomAppBar( - title: 'Individual Education Plans', - onRefresh: () { - // _loadCourses(); - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: SingleChildScrollView( - child: LayoutBuilder( - builder: (context, constraints) { - return Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Individual Education Plan Page', - style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), - ), - Text( - 'Enroll Student in New IEP', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - DropdownMenu( - label: Text('Course'), - // helperText: 'Course', - hintText: 'Select Course', - width: 350, - dropdownMenuEntries: (getAllCourses() ?? []).map((Course course) { - return DropdownMenuEntry( - value: course.id.toString(), - label: course.fullName, - ); - }).toList(), - onSelected: (String? selectedValue) { - setState(() { - selectedCourse = selectedValue; - }); - participants = handleSelection(selectedValue); - if (selectedValue != null) { - essay = handleEssaySelection(int.parse(selectedValue)); - } else { - print('Selected Value is Null'); - } - if (selectedValue != null) { - quiz = handleQuizSelection(int.parse(selectedValue)); - } else { - print('Selected Value is Null'); - } - }, - ), - SizedBox(height: 10), - Visibility( - visible: selectedCourse != null, - child: FutureBuilder>( - future: participants, - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return CircularProgressIndicator(); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - List> dropdownEntries = snapshot.data!.map((Participant participant) { - return DropdownMenuEntry( - value: participant.id.toString(), - label: participant.fullname, - ); - }).toList(); - return DropdownMenu( - label: Text('Participants'), - // helperText: 'Participants', - hintText: 'Select Participants', - width: 350, - dropdownMenuEntries: dropdownEntries, - onSelected: (String? selectedParticipant) { - setState(() { - if (selectedParticipant != null) { - userId = int.parse(selectedParticipant); - } else { - print('No Participants were selected'); - } - }); - }, - ); - } else { - return DropdownMenu( - label: Text('Participants'), - hintText: 'Select A Course To View Participants', - // helperText: 'Participants', - width: 350, - dropdownMenuEntries: [], - ); - } - }, - ), - ), - SizedBox(height: 10), - Visibility( - visible: userId != null, - child: DropdownMenu( - width: 350, - label: Text('Assignment'), - // helperText: 'Assignment', - hintText: 'Select Quiz or Essay', - dropdownMenuEntries: type.map>((String value) { - return DropdownMenuEntry( - value: value, - label: value, - ); - }).toList(), - onSelected: (String? selectedValue) { - setState(() { - selectedAssignment = selectedValue; - essayId = null; - quizId = null; - _dateController.clear(); - _cutoffDateController.clear(); - epochTime = null; - epochTime2 = null; - }); - if (selectedAssignment == 'Essay') { - if (selectedCourse != null) { - handleEssaySelection(int.parse(selectedCourse!)); - } else { - print('Selected Course Is Null'); - } - } - }, - ), - ), - SizedBox(height: 10), - Visibility( - visible: selectedAssignment == 'Essay', - child: FutureBuilder>( - future: essay, - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return CircularProgressIndicator(); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - List> dropdownEntries = snapshot.data!.map((Assignment assignment) { - return DropdownMenuEntry( - value: assignment.id.toString(), - label: assignment.name, - ); - }).toList(); - return DropdownMenu( - label: Text('Essays'), - // helperText: 'Essays', - hintText: 'Select Essay', - width: 350, - dropdownMenuEntries: dropdownEntries, - onSelected: (String? selectedEssayId) { - setState(() { - if (selectedEssayId != null) { - essayId = int.parse(selectedEssayId); - } else { - print('Essay ID was Null'); - } - }); - }, - ); - } else { - return DropdownMenu( - hintText: 'Select A Course To View Essays', - label: Text('Essays'), - // helperText: 'Essays', - width: 350, - dropdownMenuEntries: [], - ); - } - }, - ), - ), - SizedBox(height: 10), - Visibility( - visible: selectedAssignment == 'Quiz', - child: FutureBuilder>( - future: quiz, - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return CircularProgressIndicator(); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - List> dropdownEntries = snapshot.data!.map((Quiz quiz) { - return DropdownMenuEntry( - value: quiz.id.toString(), - label: quiz.name!, - ); - }).toList(); - return DropdownMenu( - label: Text('Quiz'), - // helperText: 'Quiz', - hintText: 'Select Quiz', - width: 350, - dropdownMenuEntries: dropdownEntries, - onSelected: (String? selectedQuizId) { - setState(() { - if (selectedQuizId != null) { - quizId = int.parse(selectedQuizId); - } else { - print('Quiz Id is null'); - } - }); - }, - ); - } else { - return DropdownMenu( - hintText: 'Select A Course To View Quizzes', - label: Text('Quizzes'), - // helperText: 'Quizzes', - width: 350, - dropdownMenuEntries: [], - ); - } - }, - ), - ), - SizedBox(height: 10), - Visibility( - visible: quizId != null, - child: DropdownMenu( - width: 350, - label: Text('Attempts'), - // helperText: 'Attempts', - hintText: 'Select Number of Attempts', - dropdownMenuEntries: attempts.map>((String attempts) { - return DropdownMenuEntry( - value: attempts, - label: attempts, - ); - }).toList(), - onSelected: (String? selectedValue) { - setState(() { - if (selectedValue == 'Unlimited') { - selectedAttempt = 0; - } else { - selectedAttempt = int.parse(selectedValue!); - } - }); - }, - ), - ), - SizedBox(height: 10), - Visibility( - visible: selectedAttempt != null && selectedAssignment == 'Quiz', - child: Row( - children: [ - Container( - width: 250, - margin: EdgeInsets.only(right: 20), - padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.black), - ), - child: Text( - _dateController.text, - style: TextStyle(fontSize: 20), - ), - ), - GestureDetector( - onTap: () => _selectDate(context), // Correct usage of named parameter `onTap` - child: Container( - padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10), - decoration: BoxDecoration( - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - 'Select Date', - ), - ), - ), - ], - ), - ), - // SizedBox(height: 10), - Visibility( - visible: essayId != null && selectedAssignment == 'Essay', - child: Column( - children: [ - Row( - children: [ - Container( - width: 250, - margin: EdgeInsets.only(right: 20), - padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.black), - ), - child: Text( - _dateController.text, - style: TextStyle(fontSize: 20), - ), - ), - GestureDetector( - onTap: () => _selectDate(context), // Correct usage of named parameter `onTap` - child: Container( - padding: EdgeInsets.symmetric(vertical: 15, horizontal: 18), - decoration: BoxDecoration( - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - 'Select Due Date', - ), - ), - ), - ], - ), - SizedBox(height: 20), - Row( - children: [ - Container( - width: 250, - margin: EdgeInsets.only(right: 20), - padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.black), - ), - child: Text( - _cutoffDateController.text, - style: TextStyle(fontSize: 20), - ), - ), - GestureDetector( - onTap: () => _selectCutOffDate(context), // Correct usage of named parameter `onTap` - child: Container( - padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10), - decoration: BoxDecoration( - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - 'Select Cutoff Date', - ), - ), - ), - ], - ), - SizedBox(height: 10), - Text( - 'Cutoff Date: Last day it can be submitted late', - style: TextStyle(fontSize: 14, color: Colors.grey), - ), - ], - ), - ), - SizedBox(height: 10), - Visibility( - visible: epochTime != null, - child: Container( - padding: EdgeInsets.only(top: 50, left: 160), - child: ElevatedButton( - onPressed: () { - if (selectedAssignment == 'Quiz') { - quizOver(epochTime, quizId, userId, selectedAttempt); - Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => IepPage())); - } else if (selectedAssignment == 'Essay') { - essayOver(epochTime, essayId, userId, epochTime2); - Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => IepPage())); - } - }, - child: Text('Submit'), - ), - ), - ), - ], - ), - Expanded( - child: Column( - children: [ - Text( - 'Existing IEPs', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - Container( - margin: EdgeInsets.only(left: 10), - width: constraints.maxWidth * 0.7, - height: 830, - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(0.0), - ), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: screenWidth < 1024 - ? _buildSimplifiedTable(context) - : _buildFullTable(context), - ), - ), - ), - ], - ), - ), - ], - ); - }, - ), - ), - ); - } - - // Build the simplified table for smaller screens - DataTable _buildSimplifiedTable(BuildContext context) { - return DataTable( - headingRowColor: MaterialStateProperty.all(const Color.fromARGB(255, 77, 195, 89)), - columns: [ - DataColumn(label: Text('Student Name', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Course Name', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Actions', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - ], - rows: (getOverrides() ?? []).asMap().map((index, override) { - return MapEntry(index, DataRow( - cells: [ - DataCell(Text(override.fullname)), - DataCell(Text(override.courseName)), - DataCell( - ElevatedButton( - onPressed: () => _showDetailsDialog(context, override), - child: Text("View"), - ), - ), - ], - )); - }).values.toList(), - ); - } - - // Build the full table for larger screens - DataTable _buildFullTable(BuildContext context) { - return DataTable( - headingRowColor: MaterialStateProperty.all(const Color.fromARGB(255, 77, 195, 89)), - columns: [ - DataColumn(label: Text('Student Name', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Course Name', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Assignment', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Due Dates', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - DataColumn(label: Text('Attempts', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))), - ], - rows: (getOverrides() ?? []).asMap().map((index, override) { - return MapEntry(index, buildDataRow(override, index)); - }).values.toList(), - ); - } -} - -List? getAllCourses() { - List? result; - result = MoodleLmsService().courses; - return result; -} - -Future>? getAllParticipants(String courseID) async { - List? participants; - participants = await MoodleLmsService().getCourseParticipants(courseID); - return participants; -} - -Future> handleSelection(String? courseID) async { - if (courseID != null) { - List? participants = await getAllParticipants(courseID); - if (participants == null) { - return []; - } else { - return participants; - } - } else { - print('Course ID was Null.'); - return []; - } -} - -Future> handleEssaySelection(int? courseID) async { - if (courseID != null) { - List? essays = await MoodleLmsService().getEssays(courseID); - if (essays.isNotEmpty) { - return essays; - } else { - return []; - } - } else { - return []; - } -} - -Future> handleQuizSelection(int? courseID) async { - if (courseID != null) { - List? quizzes = await MoodleLmsService().getQuizzes(courseID); - if (quizzes.isNotEmpty) { - return quizzes; - } else { - return []; - } - } else { - return []; - } -} - -void quizOver(epochTime, quizId, userId, attempts) async { - QuizOverride override = await MoodleLmsService().addQuizOverride(quizId: quizId, userId: userId, timeClose: epochTime, attempts: attempts); - print('Override: $override'); -} - -void essayOver(epochTime, essayId, userId, epochTime2) async { - String essayOverride = await MoodleLmsService().addEssayOverride(assignid: essayId, userId: userId, dueDate: epochTime, cutoffDate: epochTime2); - print('Override: $essayOverride'); -} - -List? getOverrides() { - List? overrides; - overrides = MoodleLmsService().overrides; - return overrides; -} - -String formatDate(String? dateString) { - if (dateString == null) { - return 'N/A'; - } - DateFormat dateFormat = DateFormat('MMM d yyyy hh:mm a'); - return dateFormat.format(DateTime.parse(dateString)); -} - -DataRow buildDataRow(Override override, int index) { - return DataRow( - color: MaterialStateProperty.resolveWith((states) { - return index % 2 == 0 ? Colors.grey[400]! : Colors.white; - }), - cells: [ - DataCell(Text(override.fullname)), - DataCell(Text(override.courseName)), - DataCell( - Text( - "${override.type}: ${override.assignmentName}", - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - DataCell( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Extended: ${formatDate(override.endTime?.toString())}", - style: TextStyle(fontSize: 14), - ), - SizedBox(height: 4), - Text( - "Cut off: ${formatDate(override.cutoffTime?.toString())}", - style: TextStyle(fontSize: 14), - ), - ], - ), - ), - DataCell(Text(override.attempts?.toString() ?? 'N/A')), - ], - ); -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/lesson.dart b/team_a/teamA/lib/Views/lesson.dart deleted file mode 100644 index 93fb562a..00000000 --- a/team_a/teamA/lib/Views/lesson.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'dart:convert'; - -class Lesson { - final int courseId; - final String lessonPlanName; - final String? content; // Content is now explicitly the lesson description - - Lesson( - {required this.lessonPlanName, required this.courseId, this.content}); - - /// Convert lesson plan to JSON for storage or API submission - Map toJson() { - return { - 'lessonPlanName': lessonPlanName, - 'courseId': courseId, - 'content': content, // Pass content as lesson description - }; - } - - /// Save lesson plan locally using SharedPreferences - Future saveLessonLocally() async { - final prefs = await SharedPreferences.getInstance(); - final List savedPlans = prefs.getStringList('lessonPlans') ?? []; - savedPlans.add(jsonEncode(this.toJson())); - await prefs.setStringList('lessonPlans', savedPlans); - } - - /// Load lesson plans from SharedPreferences - static Future> loadLessonPlans() async { - final prefs = await SharedPreferences.getInstance(); - final List savedPlans = prefs.getStringList('lessonPlans') ?? []; - - return savedPlans.map((plan) { - final Map planJson = jsonDecode(plan); - return Lesson( - lessonPlanName: planJson['lessonPlanName'], - courseId: planJson['courseId'], - content: planJson['content'], - ); - }).toList(); - } - - /// Submit lesson plan and automatically create a Moodle lesson - Future submitLesson() async { - final lessonPlanJson = this.toJson(); - print("Submitting lesson plan with data: $lessonPlanJson"); - var courseId = lessonPlanJson['courseId']; - var lessonPlanName = lessonPlanJson['lessonPlanName']; - var content = lessonPlanJson['content']; - return await MoodleLmsService().createLesson( - courseId: courseId, // Pass courseId as a string - lessonPlanName: lessonPlanName, - content: content ?? "No description provided", - ); - } -} diff --git a/team_a/teamA/lib/Views/lesson_plans.dart b/team_a/teamA/lib/Views/lesson_plans.dart deleted file mode 100644 index 9b827732..00000000 --- a/team_a/teamA/lib/Views/lesson_plans.dart +++ /dev/null @@ -1,914 +0,0 @@ -import "package:flutter/material.dart"; -import "package:learninglens_app/Api/lms/constants/learning_lens.constants.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import "package:learninglens_app/Views/lesson.dart"; -import "package:learninglens_app/beans/course.dart"; -import "package:learninglens_app/beans/lesson_plan.dart"; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'dart:convert'; - -// Define a constant for grade levels - -class LessonPlans extends StatefulWidget { - @override - State createState() => _LessonPlanState(); -} - -class _LessonPlanState extends State { - List? courses = []; - String? selectedCourse; - List lessonPlans = []; - LessonPlan? selectedLessonPlan; - bool isEditing = false; - bool useAiGeneration = false; - LlmType? selectedLLM; - bool isSubmitDisabled = false; - String? selectedGradeLevel; - bool isSubmitting = false; - - //final ScrollController _scrollController = ScrollController(); - List _scrollControllers = []; - - final TextEditingController lessonPlanNameController = TextEditingController(); - final TextEditingController manualEntryController = TextEditingController(); - final TextEditingController additionalPromptController = TextEditingController(); // New controller - bool showAiPromptSection = false; // New state variable to control visibility - bool isGeneratingLesson = false; // New state variable for loading state - - @override - void dispose() { - lessonPlanNameController.dispose(); - manualEntryController.dispose(); - additionalPromptController.dispose(); - for (var controller in _scrollControllers) { - controller.dispose(); - } - super.dispose(); - } - - @override - void initState() { - super.initState(); - _loadCourses(); // Load courses when the widget initializes - } - - Future _loadCourses() async { - try { - var userCourses = await LmsFactory.getLmsService().courses; - setState(() { - courses = userCourses; // Update the state with fetched courses - }); - } catch (e) { - print("Error loading courses: $e"); - } - } - - void _fetchLessonPlans(int courseId) async { - List plans = await MoodleLmsService().getLessonPlans(courseId); - setState(() { - lessonPlans = plans; - _scrollControllers = List.generate( - lessonPlans.length, - (index) => ScrollController(), - growable: true, - ); - }); - } - - String normalizeText(String text) { - return text - .replaceAll('’', "'") // Replace garbled curly apostrophe with a plain apostrophe - .replaceAll('’', "'") // Replace Unicode curly apostrophe with a plain apostrophe - .replaceAll('“', '"') // Replace Unicode left double quotation mark - .replaceAll('”', '"') // Replace Unicode right double quotation mark - .replaceAll('‘', "'") // Replace Unicode left single quotation mark - .replaceAll('’', "'"); // Replace Unicode right single quotation mark -} - - Future generateLessonPlanWithAI() async { - try { - final aiModel; - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else { - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } - - String prompt = """Generate an all text (no diagrams) lesson of less than 500 words for ${lessonPlanNameController.text} for grade $selectedGradeLevel covering key topics like ${manualEntryController.text}. ${additionalPromptController.text}. This lesson is WHAT THE STUDENT WILL SEE! This lesson will be viewed by students and students will use it to study from (which will help them write essays and take quizzes). IMPORTANT: Do not use any Markdown syntax (e.g., #, *, **, etc.). Use plain text only."""; - var result = await aiModel.postToLlm(prompt); - - String normalizedText = utf8.decode(result.codeUnits); - - setState(() { - manualEntryController.text = normalizeText(normalizedText); // Update the manual entry textbox with the AI response - }); - } catch (e) { - print("Error generating lesson plan: $e"); - setState(() { - isGeneratingLesson = false; // Ensure loading spinner is hidden on error - }); - } -} - - String _convertTextToHtml(String text) { - return "

    ${text.replaceAll('\n\n', '

    ').replaceAll('\n', '
    ')}

    "; - } - - String _stripHtmlTags(String htmlText) { - return htmlText - .replaceAll(RegExp(r']*>'), '\n\n') - .replaceAll(RegExp(r'

    '), '') - .replaceAll(RegExp(r''), '\n') - .replaceAll(RegExp(r'<[^>]*>'), '') - .trim(); - } - - void _showLessonPlanDialog(LessonPlan plan) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text(plan.name), - content: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width * 0.4, - child: Text(_stripHtmlTags(plan.intro), textAlign: TextAlign.left), - ), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text("Close"), - ), - ], - ); - }, - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Lesson Plans', - onRefresh: _loadCourses, // Refresh courses when the app bar is refreshed - userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: SingleChildScrollView( - child: LayoutBuilder( - builder: (context, constraints) { - bool isNarrowScreen = constraints.maxWidth <= 805; // Breakpoint for narrow screens - bool isMediumScreen = constraints.maxWidth > 805 && constraints.maxWidth <= 1170; // Breakpoint for medium screens - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Add New Lesson Plan Section - if (!isNarrowScreen) - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Add New Lesson Plan', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 10), - DropdownButtonFormField( - value: selectedCourse, - items: courses?.map>((course) { - return DropdownMenuItem( - value: course.id.toString(), - child: Text(course.fullName), - ); - }).toList() ?? [], - onChanged: (value) { - setState(() { - selectedCourse = value; - _fetchLessonPlans(int.parse(value!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - additionalPromptController.clear(); - selectedLLM = null; - isEditing = false; - isSubmitDisabled = false; - useAiGeneration = false; - showAiPromptSection = false; - selectedGradeLevel = null; - }); - }, - decoration: InputDecoration( - labelText: 'Course', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - TextField( - controller: lessonPlanNameController, - decoration: InputDecoration( - labelText: 'Lesson Plan Name', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - DropdownButtonFormField( - decoration: const InputDecoration( - labelText: 'Select Grade Level', - border: OutlineInputBorder(), - ), - value: selectedGradeLevel, - items: LearningLensConstants.gradeLevels.map((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - onChanged: (String? newValue) { - setState(() { - selectedGradeLevel = newValue; - }); - }, - ), - SizedBox(height: 20), - - // AI and Manual Generation Options - // Inside the build method, where the AI generation options are defined - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CheckboxListTile( - title: Text("Generate Lesson Plan with AI"), - value: useAiGeneration, - onChanged: (bool? value) { - setState(() { - useAiGeneration = value!; - showAiPromptSection = useAiGeneration; // Show/hide the new section - if (!useAiGeneration) { - selectedLLM = null; // Reset dropdown when unchecked - } - }); - }, - ), - - if (useAiGeneration) - DropdownButtonFormField( - value: selectedLLM, - decoration: const InputDecoration(labelText: "Select AI Model"), - onChanged: (LlmType? newValue) { - setState(() { - selectedLLM = newValue; - }); - }, - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text(llm.displayName, style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) ? Colors.black87 : Colors.grey, - )), - ); - }).toList(), - disabledHint: Text("Enable AI to select a model"), - ), - - // New UI elements for additional AI prompt - if (showAiPromptSection) - Column( - children: [ - SizedBox(height: 20), - TextField( - controller: additionalPromptController, - maxLines: 4, // Half the height of the manual entry textbox - decoration: InputDecoration( - labelText: "Enter any additional prompts for the AI model to customize your lesson", - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - ElevatedButton( - onPressed: isGeneratingLesson || selectedLLM == null - ? null - : () async { - setState(() { - isGeneratingLesson = true; // Show loading spinner - }); - - await generateLessonPlanWithAI(); // Call the AI generation logic - - setState(() { - isGeneratingLesson = false; // Hide loading spinner - }); - }, - child: isGeneratingLesson - ? SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ) - : Text("Generate Lesson Plan"), - ), - ], - ), - ], - ), - SizedBox(height: 20), - - // Textbox for Lesson Plan Content - TextField( - controller: manualEntryController, - maxLines: 8, - decoration: InputDecoration( - labelText: useAiGeneration - ? "Edit the AI-generated lesson plan" - : "Enter Lesson Plan Manually", - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 20), - - // Submit Button - ElevatedButton( - onPressed: isSubmitDisabled || isSubmitting - ? null - : () async { - setState(() { - isSubmitting = true; - }); - - if (selectedCourse != null) { - Lesson newLp = Lesson( - lessonPlanName: lessonPlanNameController.text, - courseId: int.parse(selectedCourse!), - content: _convertTextToHtml(manualEntryController.text), - ); - bool success = await newLp.submitLesson(); - print(success ? 'Lesson plan sent successfully' : 'Lesson plan send failed'); - _fetchLessonPlans(int.parse(selectedCourse!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - additionalPromptController.clear(); - selectedLLM = null; - useAiGeneration = false; - - } - - setState(() { - isSubmitting = false; - }); - }, - child: isSubmitting - ? SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ) - : Text('Submit'), - ), - ], - ), - ), - SizedBox(width: 20), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Existing Lesson Plans', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 10), - Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 10, - columns: [ - DataColumn( - label: SizedBox( - width: 100, - child: Text('Name', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ), - if (!isMediumScreen) // Hide Lesson Plan column for medium screens - DataColumn( - label: SizedBox( - width: 200, - child: Text('Lesson Plan', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ), - DataColumn( - label: Text('Select', style: TextStyle(fontWeight: FontWeight.bold)), - ), - DataColumn( - label: Text('View', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ], - rows: lessonPlans.asMap().entries.map((entry) { - int index = entry.key; - LessonPlan plan = entry.value; - bool isSelected = selectedLessonPlan == plan; - return DataRow( - cells: [ - DataCell( - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 150), - child: Text( - plan.name, - overflow: TextOverflow.ellipsis, - ), - ), - ), - if (!isMediumScreen) // Hide Lesson Plan column for medium screens - DataCell( - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 250), - child: Container( - height: 60, // Fixed height to maintain row size - child: Scrollbar( - controller: _scrollControllers[index], // Add a ScrollController - child: SingleChildScrollView( - controller: _scrollControllers[index], // Add a ScrollController - scrollDirection: Axis.vertical, - child: Text( - _stripHtmlTags(plan.intro), - ), - ), - ), - ), - ), - ), - DataCell( - Checkbox( - value: isSelected, - onChanged: (bool? selected) { - setState(() { - selectedLessonPlan = selected! ? plan : null; - }); - }, - ), - ), - DataCell( - ElevatedButton( - onPressed: () { - _showLessonPlanDialog(plan); - }, - child: Text("View"), - ), - ), - ], - ); - }).toList(), - ), - ), - ), - SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton( - onPressed: selectedLessonPlan != null && !isEditing - ? () async { - await MoodleLmsService().deleteLessonPlan(selectedLessonPlan!.id); - _fetchLessonPlans(int.parse(selectedCourse!)); - setState(() { - selectedLessonPlan = null; - }); - } - : null, - child: Text('Delete Selected'), - ), - ElevatedButton( - onPressed: selectedLessonPlan != null && !isEditing - ? () { - setState(() { - isEditing = true; - lessonPlanNameController.text = selectedLessonPlan!.name; - manualEntryController.text = _stripHtmlTags(selectedLessonPlan!.intro); - isSubmitDisabled = true; - }); - } - : null, - child: Text('Edit Selected'), - ), - ElevatedButton( - onPressed: isEditing - ? () async { - String manualEntryToHtml = _convertTextToHtml(manualEntryController.text); - await MoodleLmsService().updateLessonPlan( - lessonId: selectedLessonPlan!.id, - name: lessonPlanNameController.text, - intro: manualEntryToHtml, - available: 1672531200, //dummy value - deadline: 1675132800, //dummy value - ); - _fetchLessonPlans(int.parse(selectedCourse!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - additionalPromptController.clear(); - selectedLLM = null; - useAiGeneration = false; - - setState(() { - selectedLessonPlan = null; - isEditing = false; - isSubmitDisabled = false; - }); - } - : null, - child: Text('Save Edits'), - ), - ], - ), - ], - ), - ), - ], - ), - - // For Narrow Screens (805px or less) - if (isNarrowScreen) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Add New Lesson Plan', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 10), - DropdownButtonFormField( - value: selectedCourse, - items: courses?.map>((course) { - return DropdownMenuItem( - value: course.id.toString(), - child: Text(course.fullName), - ); - }).toList() ?? [], - onChanged: (value) { - setState(() { - selectedCourse = value; - _fetchLessonPlans(int.parse(value!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - additionalPromptController.clear(); - additionalPromptController.clear(); - selectedLLM = null; - isEditing = false; - isSubmitDisabled = false; - useAiGeneration = false; - showAiPromptSection = false; - selectedGradeLevel = null; - }); - }, - decoration: InputDecoration( - labelText: 'Course', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - TextField( - controller: lessonPlanNameController, - decoration: InputDecoration( - labelText: 'Lesson Plan Name', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - DropdownButtonFormField( - decoration: const InputDecoration( - labelText: 'Select Grade Level', - border: OutlineInputBorder(), - ), - value: selectedGradeLevel, - items: LearningLensConstants.gradeLevels.map((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - onChanged: (String? newValue) { - setState(() { - selectedGradeLevel = newValue; - }); - }, - ), - SizedBox(height: 20), - - // AI and Manual Generation Options - // Inside the build method, where the AI generation options are defined - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CheckboxListTile( - title: Text("Generate Lesson Plan with AI"), - value: useAiGeneration, - onChanged: (bool? value) { - setState(() { - useAiGeneration = value!; - showAiPromptSection = useAiGeneration; // Show/hide the new section - if (!useAiGeneration) { - selectedLLM = null; // Reset dropdown when unchecked - } - }); - }, - ), - - if (useAiGeneration) - DropdownButtonFormField( - value: selectedLLM, - decoration: const InputDecoration(labelText: "Select AI Model"), - onChanged: (LlmType? newValue) { - setState(() { - selectedLLM = newValue; - }); - }, - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text(llm.displayName, style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) ? Colors.black87 : Colors.grey, - )), - ); - }).toList(), - disabledHint: Text("Enable AI to select a model"), - ), - - // New UI elements for additional AI prompt - if (showAiPromptSection) - Column( - children: [ - SizedBox(height: 20), - TextField( - controller: additionalPromptController, - maxLines: 4, // Half the height of the manual entry textbox - decoration: InputDecoration( - labelText: "Enter any additional prompts for the AI model to customize your lesson", - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 10), - ElevatedButton( - onPressed: isGeneratingLesson || selectedLLM == null - ? null - : () async { - setState(() { - isGeneratingLesson = true; // Show loading spinner - }); - - await generateLessonPlanWithAI(); // Call the AI generation logic - - setState(() { - isGeneratingLesson = false; // Hide loading spinner - }); - }, - child: isGeneratingLesson - ? SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ) - : Text("Generate Lesson Plan"), - ), - ], - ), - ], - ), - SizedBox(height: 20), - - // Textbox for Lesson Plan Content - TextField( - controller: manualEntryController, - maxLines: 8, - decoration: InputDecoration( - labelText: useAiGeneration - ? "Edit the AI-generated lesson plan" - : "Enter the Lesson Plan Manually", - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 20), - - // Submit Button - ElevatedButton( - onPressed: isSubmitDisabled || isSubmitting - ? null - : () async { - setState(() { - isSubmitting = true; - }); - - if (selectedCourse != null) { - Lesson newLp = Lesson( - lessonPlanName: lessonPlanNameController.text, - courseId: int.parse(selectedCourse!), - content: _convertTextToHtml(manualEntryController.text), - ); - bool success = await newLp.submitLesson(); - print(success ? 'Lesson plan sent successfully' : 'Lesson plan send failed'); - _fetchLessonPlans(int.parse(selectedCourse!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - lessonPlanNameController.clear(); - manualEntryController.clear(); - additionalPromptController.clear(); - selectedLLM = null; - isEditing = false; - isSubmitDisabled = false; - useAiGeneration = false; - showAiPromptSection = false; - selectedGradeLevel = null; - } - - setState(() { - isSubmitting = false; - }); - }, - child: isSubmitting - ? SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ) - : Text('Submit'), - ), - SizedBox(height: 20), - - // Existing Lesson Plans Section for Narrow Screens - Text('Existing Lesson Plans', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - SizedBox(height: 10), - Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: DataTable( - columnSpacing: 10, - columns: [ - DataColumn( - label: SizedBox( - width: 100, - child: Text('Name', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ), - if (!isMediumScreen) // Hide Lesson Plan column for medium screens - DataColumn( - label: SizedBox( - width: 200, - child: Text('Lesson Plan', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ), - DataColumn( - label: Text('Select', style: TextStyle(fontWeight: FontWeight.bold)), - ), - DataColumn( - label: Text('View', style: TextStyle(fontWeight: FontWeight.bold)), - ), - ], - rows: lessonPlans.asMap().entries.map((entry) { - int index = entry.key; - LessonPlan plan = entry.value; - bool isSelected = selectedLessonPlan == plan; - return DataRow( - cells: [ - DataCell( - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 150), - child: Text( - plan.name, - overflow: TextOverflow.ellipsis, - ), - ), - ), - if (!isMediumScreen) // Hide Lesson Plan column for medium screens - DataCell( - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 250), - child: Container( - height: 60, // Fixed height to maintain row size - child: Scrollbar( - controller: _scrollControllers[index], // Add a ScrollController - child: SingleChildScrollView( - controller: _scrollControllers[index], // Add a ScrollController - scrollDirection: Axis.vertical, - child: Text( - _stripHtmlTags(plan.intro), - ), - ), - ), - ), - ), - ), - DataCell( - Checkbox( - value: isSelected, - onChanged: (bool? selected) { - setState(() { - selectedLessonPlan = selected! ? plan : null; - }); - }, - ), - ), - DataCell( - ElevatedButton( - onPressed: () { - _showLessonPlanDialog(plan); - }, - child: Text("View"), - ), - ), - ], - ); - }).toList(), - ), - ), - ), - SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton( - onPressed: selectedLessonPlan != null && !isEditing - ? () async { - await MoodleLmsService().deleteLessonPlan(selectedLessonPlan!.id); - _fetchLessonPlans(int.parse(selectedCourse!)); - setState(() { - selectedLessonPlan = null; - }); - } - : null, - child: Text('Delete Selected'), - ), - ElevatedButton( - onPressed: selectedLessonPlan != null && !isEditing - ? () { - setState(() { - isEditing = true; - lessonPlanNameController.text = selectedLessonPlan!.name; - manualEntryController.text = _stripHtmlTags(selectedLessonPlan!.intro); - isSubmitDisabled = true; - }); - } - : null, - child: Text('Edit Selected'), - ), - ElevatedButton( - onPressed: isEditing - ? () async { - String manualEntryToHtml = _convertTextToHtml(manualEntryController.text); - await MoodleLmsService().updateLessonPlan( - lessonId: selectedLessonPlan!.id, - name: lessonPlanNameController.text, - intro: manualEntryToHtml, - available: 1672531200, //dummy value - deadline: 1675132800, //dummy value - ); - _fetchLessonPlans(int.parse(selectedCourse!)); - lessonPlanNameController.clear(); - manualEntryController.clear(); - - setState(() { - selectedLessonPlan = null; - isEditing = false; - isSubmitDisabled = false; - }); - } - : null, - child: Text('Save Edits'), - ), - ], - ), - ], - ), - ], - ); - }, - ), - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/m_assessment_view.dart b/team_a/teamA/lib/Views/m_assessment_view.dart deleted file mode 100644 index a7000ef8..00000000 --- a/team_a/teamA/lib/Views/m_assessment_view.dart +++ /dev/null @@ -1,158 +0,0 @@ -import "package:flutter/material.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Views/view_quiz.dart"; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/course.dart'; -import "package:learninglens_app/Controller/custom_appbar.dart"; -import "package:learninglens_app/content_carousel.dart"; - -//The Page -class MAssessmentsView extends StatefulWidget { - MAssessmentsView({super.key, this.quizID = 0, this.courseID = 0}); - - final int quizID; - final int? courseID; - - @override - _AssessmentsState createState() => _AssessmentsState(); -} - -class _AssessmentsState extends State { - late Future?> quizzes; - Quiz? selectedQuiz; - - List> questionsData = []; - - @override - void initState() { - super.initState(); - quizzes = getAllQuizzes(widget.courseID); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Assessments', - onRefresh: () { - setState(() { - quizzes = getAllQuizzes(widget.courseID); - }); - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Column( - children: [ - Row(children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: CreateButton('assessment')) - ]), - Expanded( - child: FutureBuilder?>( - future: quizzes, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error loading quizzes')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No quizzes found')); - } else { - final quizList = snapshot.data!; - - return LayoutBuilder( - builder: (context, constraints) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - // Left-side course list with border - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: ListView.builder( - itemCount: quizList.length, - itemBuilder: (context, index) { - final quiz = quizList[index]; - final activeCourse = - getCourse(quiz.coursedId); - if (quiz.id == widget.quizID) { - selectedQuiz = quiz; - } - - return ListTile( - title: Text( - '${quiz.name} (${activeCourse.shortName}${activeCourse.courseId})'), - subtitle: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - 'Due: ${quiz.timeClose == null ? "No due date set" : Course.dateFormatted(quiz.timeClose!)}'), - ], - ), - tileColor: selectedQuiz == quiz - ? Theme.of(context) - .colorScheme - .primary - .withOpacity(0.1) - : null, - onTap: () { - setState(() { - selectedQuiz = quiz; - }); - }, - ); - }, - ), - ), - ), - - // Right-side course details (quiz questions) - Expanded( - flex: 2, - child: selectedQuiz == null && widget.quizID == 0 - ? Center( - child: - Text('Select a quiz to view details')) - : ViewQuiz(quizId: selectedQuiz?.id ?? widget.quizID), - ), - ], - ); - }, - ); - } - }, - ), - ), - ], - ), - ); - } -} - -//Helper function that pulls the quizzes from all the user's courses -Future> getAllQuizzes(int? courseID) async { - List result = []; - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (courseID == 0 || courseID == null || c.id == courseID) { - result.addAll(c.quizzes ?? []); - } - } - return result; -} - -//Helper function that gets the course number for the quiz -Course getCourse(int? courseID) { - for (Course c in LmsFactory.getLmsService().courses ?? []) { - if (c.id == courseID) { - return c; - } - } - throw "No course found."; -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/quiz_generator.dart b/team_a/teamA/lib/Views/quiz_generator.dart deleted file mode 100644 index 6dbd2b58..00000000 --- a/team_a/teamA/lib/Views/quiz_generator.dart +++ /dev/null @@ -1,397 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:learninglens_app/Api/llm/prompt_engine.dart'; -import 'package:learninglens_app/Api/llm/perplexity_api.dart'; -import 'package:learninglens_app/Api/lms/constants/learning_lens.constants.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/beans/assignment_form.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'edit_questions.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; - -class CreateAssessment extends StatefulWidget { - static TextEditingController nameController = TextEditingController(); - static TextEditingController descriptionController = TextEditingController(); - static TextEditingController subjectController = TextEditingController(); - static TextEditingController multipleChoiceController = - TextEditingController(); - static TextEditingController trueFalseController = TextEditingController(); - static TextEditingController shortAnswerController = TextEditingController(); - static TextEditingController topicController = TextEditingController(); - static TextEditingController llmController = TextEditingController(); - - CreateAssessment(); - - @override - State createState() { - return _AssessmentState(); - } -} - -class _AssessmentState extends State { - double paddingHeight = 16.0, paddingWidth = 32; - bool isAdvancedModeOnGetFromGlobalVarsLater = false; - final _formKey = GlobalKey(); - String? selectedSubject, selectedGradeLevel; - LlmType? selectedLLM; - List _subjects = [ - 'Math', - 'Science', - 'Language Arts', - 'Social Studies', - 'Health', - 'Art', - 'Music' - ]; - bool _isLoading = false; - - _AssessmentState(); - - void generateQuiz(Map fields) { - if (_formKey.currentState!.validate()) { - // Parse question counts, defaulting to 0 if empty - int multipleChoiceCount = - int.tryParse(fields['multipleChoice']!.text) ?? 0; - int trueFalseCount = int.tryParse(fields['trueFalse']!.text) ?? 0; - int shortAnswerCount = int.tryParse(fields['shortAns']!.text) ?? 0; - - // Check if at least one type of question is greater than 1 - if (multipleChoiceCount <= 0 && - trueFalseCount <= 0 && - shortAnswerCount <= 0) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Please ensure at least one type of question has a count greater than 0.'), - ), - ); - return; - } - - AssignmentForm af = AssignmentForm( - subject: selectedSubject != null - ? selectedSubject.toString() - : fields['subject']!.text, - topic: fields['description']!.text, - gradeLevel: selectedGradeLevel.toString(), - title: fields['name']!.text, - trueFalseCount: trueFalseCount, - shortAnswerCount: shortAnswerCount, - multipleChoiceCount: multipleChoiceCount, - maximumGrade: 100, - ); - generateQuestions(af); - } - } - - Future generateQuestions(AssignmentForm af) async { - try { - setState(() { - _isLoading = true; - }); - final aiModel; - if (selectedLLM == LlmType.CHATGPT) { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } else if (selectedLLM == LlmType.GROK) { - aiModel = GrokLLM(LocalStorageService.getGrokKey()); - } else if (selectedLLM == LlmType.PERPLEXITY) { - aiModel = PerplexityLLM(LocalStorageService.getPerplexityKey()); - } else { - aiModel = OpenAiLLM(LocalStorageService.getOpenAIKey()); - } - var result = await aiModel.postToLlm(PromptEngine.generatePrompt(af)); - if (result.isNotEmpty) { - setState(() { - _isLoading = false; - }); - Navigator.push(context, - MaterialPageRoute(builder: (context) => EditQuestions(result))); - } - } catch (e) { - print("Failure sending request to LLM: $e"); - setState(() { - _isLoading = false; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Create Assessment', - onRefresh: () { - // _loadCourses(); - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ), - body: Form( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - child: _isLoading - ? Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CircularProgressIndicator(), - SizedBox(height: paddingHeight), - Text( - 'Generating Quiz Questions...', - style: TextStyle( - fontSize: 18, color: Colors.black54), - ) - ], - ), - ) - : SingleChildScrollView( - child: Table( - columnWidths: const {0: FlexColumnWidth(2)}, - children: [ - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - TextEntry._('Assessment Name', true, - CreateAssessment.nameController) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - TextEntry._( - 'Description', - false, - CreateAssessment.descriptionController, - isTextArea: true, - ) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - isAdvancedModeOnGetFromGlobalVarsLater - ? TextEntry._('Question Subject', true, - CreateAssessment.subjectController) - : DropdownButtonFormField( - value: selectedSubject, - decoration: const InputDecoration( - labelText: "Select Subject"), - onChanged: (String? newValue) { - setState(() { - selectedSubject = newValue; - }); - }, - validator: (value) { - if (value == null) { - return 'Please select a subject.'; - } - return null; - }, - items: - _subjects.map((String value) { - return DropdownMenuItem( - value: value, - child: Text(value)); - }).toList(), - ) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - DropdownButtonFormField( - value: selectedGradeLevel, - decoration: const InputDecoration( - labelText: "Select Grade Level"), - onChanged: (String? newValue) { - setState(() { - selectedGradeLevel = newValue; - }); - }, - validator: (value) { - if (value == null) { - return 'Please select a grade level.'; - } - return null; - }, - items: LearningLensConstants.gradeLevels - .map((String value) { - return DropdownMenuItem( - value: value, child: Text(value)); - }).toList(), - ) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - NumberEntry._( - 'Total Multiple Choice Questions', - true, - CreateAssessment - .multipleChoiceController) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - NumberEntry._( - 'Total True / False Questions', - true, - CreateAssessment.trueFalseController) - ]), - TableRow(children: [ - SizedBox(height: paddingHeight) - ]), - TableRow(children: [ - NumberEntry._( - 'Total Short Answer Questions', - true, - CreateAssessment.shortAnswerController) - ]), - ], - ), - ), - ) - ], - ), - ), - SizedBox(width: paddingWidth), - Expanded( - flex: 3, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: paddingHeight), - Text( - "Choose a total number of questions equal to four or five times the number of students in the course to guarantee unique quizzes per student", - ), - SizedBox(height: paddingHeight), - DropdownButtonFormField( - value: selectedLLM, - decoration: - const InputDecoration(labelText: "Select Model"), - onChanged: (LlmType? newValue) { - setState(() { - selectedLLM = newValue; - CreateAssessment.llmController.text = - newValue!.displayName; - }); - }, - validator: (value) { - if (value == null) { - return 'Please select an LLM model to generate the quiz.'; - } - return null; - }, - items: LlmType.values.map((LlmType llm) { - return DropdownMenuItem( - value: llm, - enabled: LocalStorageService.userHasLlmKey(llm), - child: Text( - llm.displayName, - style: TextStyle( - color: LocalStorageService.userHasLlmKey(llm) - ? Colors.black87 - : Colors.grey, - ), - ), - ); - }).toList(), - ), - SizedBox(height: paddingHeight), - ElevatedButton( - onPressed: () => generateQuiz({ - "name": CreateAssessment.nameController, - "description": CreateAssessment.descriptionController, - "subject": CreateAssessment.subjectController, - "multipleChoice": - CreateAssessment.multipleChoiceController, - "trueFalse": CreateAssessment.trueFalseController, - "shortAns": CreateAssessment.shortAnswerController, - }), - child: Text("Submit"), - ) - ], - ), - ) - ], - ), - ), - ), - ); - } -} - -class NumberEntry extends StatelessWidget { - final String title; - final bool needsValidation; - final TextEditingController controller; - - NumberEntry._(this.title, this.needsValidation, this.controller); - - @override - Widget build(BuildContext context) { - return TextFormField( - controller: controller, - inputFormatters: [FilteringTextInputFormatter.digitsOnly], - validator: (value) { - if (value == null || value.isEmpty) { - controller.text = '0'; // Default to 0 if empty - return null; - } - int? numValue = int.tryParse(value); - if (numValue == null) { - return 'Please enter a valid number for $title.'; - } - return null; - }, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: title, - ), - ); - } -} - -class TextEntry extends StatelessWidget { - final String title; - final bool needsValidation, isTextArea; - final TextEditingController controller; - - TextEntry._(this.title, this.needsValidation, this.controller, - {this.isTextArea = false}); - - @override - Widget build(BuildContext context) { - return TextFormField( - controller: controller, - validator: (value) { - if (needsValidation && (value == null || value.isEmpty)) { - return 'Please enter a value for $title'; - } - return null; - }, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: title, - ), - maxLines: isTextArea ? 6 : 1, - ); - } -} diff --git a/team_a/teamA/lib/Views/send_essay_to_moodle.dart b/team_a/teamA/lib/Views/send_essay_to_moodle.dart deleted file mode 100644 index 65d567b3..00000000 --- a/team_a/teamA/lib/Views/send_essay_to_moodle.dart +++ /dev/null @@ -1,586 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/Views/dashboard.dart'; -import 'dart:convert'; - -class EssayAssignmentSettings extends StatefulWidget { - final String updatedJson; - final String description; - - EssayAssignmentSettings(this.updatedJson, this.description); - - @override - EssayAssignmentSettingsState createState() => EssayAssignmentSettingsState(); -} - -class EssayAssignmentSettingsState extends State { - // Global key for the form - final _formKey = GlobalKey(); - - // Date selection variables for "Allow submissions from" - String selectedDaySubmission = '01'; - String selectedMonthSubmission = 'January'; - String selectedYearSubmission = '2025'; - String selectedHourSubmission = '00'; - String selectedMinuteSubmission = '00'; - - // Date selection variables for "Due date" - String selectedDayDue = '01'; - String selectedMonthDue = 'January'; - String selectedYearDue = '2025'; - String selectedHourDue = '00'; - String selectedMinuteDue = '00'; - - // Checkbox states - bool isSubmissionEnabled = true; - bool isDueDateEnabled = true; - - List days = - List.generate(31, (index) => (index + 1).toString().padLeft(2, '0')); - List months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December' - ]; - List years = ['2023', '2024', '2025']; - List hours = - List.generate(24, (index) => index.toString().padLeft(2, '0')); - List minutes = - List.generate(60, (index) => index.toString().padLeft(2, '0')); - - TextEditingController _assignmentNameController = TextEditingController(); - TextEditingController _assignmentSectionController = TextEditingController(); - TextEditingController _descriptionController = TextEditingController(); - - // List of courses fetched from the controller - List courses = []; - String selectedCourse = 'Select a course'; - - @override - void initState() { - super.initState(); - fetchCourses(); // Fetch courses on page load - populateHeadersAndRows(); - _descriptionController = TextEditingController(text: widget.description); - } - - // Fetch courses from the controller - Future fetchCourses() async { - try { - List? courseList = LmsFactory.getLmsService().courses; - setState(() { - courses = courseList ?? []; - // Don't auto-select any course here, leave it to the user to select. - selectedCourse = 'Select a course'; - }); - } catch (e) { - debugPrint('Error fetching courses: $e'); - setState(() { - selectedCourse = 'No courses available'; // Handle the empty case - }); - } - } - - // Headers and Rows for Rubric Display - List headers = []; - List rows = []; - - // Function to populate headers and rows for rubric display - void populateHeadersAndRows() { - try { - Map jsonData = jsonDecode(widget.updatedJson); - - List levels = - List.from(jsonData['criteria'][0]['levels'] as List); - headers = [ - {"title": 'Criteria', 'index': 1, 'key': 'name'}, - ]; - - for (int i = 0; i < levels.length; i++) { - headers.add({ - "title": '${levels[i]['score']}', // The score (5, 3, 1) as headers - 'index': i + 2, - 'key': 'level_$i' - }); - } - - rows = (jsonData['criteria'] ?? []).map((criterion) { - Map row = { - "name": criterion['description'], - }; - - for (int i = 0; i < (criterion['levels'] as List).length; i++) { - row['level_$i'] = (criterion['levels'] as List)[i]['definition']; - } - - return row; - }).toList(); - } catch (e) { - // debugPrint('Error parsing rubric JSON: $e');// i dnt want to see this jason rubrick on console.this wass for testing only - } - - setState(() {}); - } - - // Dropdown to display courses with "Select a course" as the default option - DropdownButtonFormField _buildCourseDropdown() { - return DropdownButtonFormField( - value: selectedCourse == 'Select a course' - ? null - : selectedCourse, // Set initial value to null if 'Select a course' - decoration: InputDecoration( - labelText: 'Course name', - border: OutlineInputBorder(), - ), - validator: (value) { - if (value == null || value == 'Select a course') { - return 'Please select a course'; - } - return null; - }, - onChanged: (String? newValue) { - setState(() { - selectedCourse = newValue!; - }); - // debugPrint('Selected course: $selectedCourse');//i dnt want to see this on console.this wass for testing only - }, - items: [ - DropdownMenuItem( - value: 'Select a course', - child: Text('Select a course'), - ), - ...courses.map>((Course course) { - return DropdownMenuItem( - value: course.fullName, - child: Text(course.fullName), - ); - // }).toList(),/// trying to see if warning go away safia - }), - ], - isExpanded: true, - ); - } - - // Custom Widget to build rubric table without editable package - Widget buildRubricTable() { - return Table( - border: TableBorder.all(), - children: [ - TableRow(children: [ - _buildTableCell('Criteria'), - for (var header in headers.skip(1)) _buildTableCell(header['title']), - ]), - for (var row in rows) - TableRow(children: [ - _buildTableCell(row['name']), - for (var i = 0; i < headers.length - 1; i++) - _buildTableCell(row['level_$i']), - ]), - ], - ); - } - - Widget _buildTableCell(String text) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - text, - style: TextStyle(fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - ); - } - - // Function to validate if the availability date selections are not default values - bool _validateAvailabilityDates() { - if (selectedDaySubmission == '01' && - selectedMonthSubmission == 'January' && - selectedYearSubmission == '2025' && - selectedHourSubmission == '00' && - selectedMinuteSubmission == '00') { - return false; // If the default date for submission is selected, return false - } - - if (selectedDayDue == '01' && - selectedMonthDue == 'January' && - selectedYearDue == '2025' && - selectedHourDue == '00' && - selectedMinuteDue == '00') { - return false; // If the default due date is selected, return false - } - - return true; // If both dates have been customized, validation passes - } - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - double screenWidth = constraints.maxWidth; - - // Example: Calculate sizes dynamically based on screen width - double buttonWidth = - screenWidth * 0.4; // Buttons take 40% of screen width - double descriptionHeight = screenWidth * - 0.2; // Description box takes 20% of screen width height - - return Scaffold( - appBar: CustomAppBar( - title: 'Assign Essay', - userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: SingleChildScrollView( - padding: EdgeInsets.all(14.0), - child: Form( - key: _formKey, // Assigning the global form key - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Padding( - padding: const EdgeInsets.only(top: 14.0), - child: Text( - 'Send Essay to Moodle', - style: TextStyle( - fontSize: 18, fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - ), - ), - SizedBox(height: 20), - sectionTitle(title: 'General'), - _buildCourseDropdown(), - SizedBox(height: 12), - TextFormField( - controller: _assignmentSectionController, - decoration: InputDecoration( - labelText: 'Section Number', - border: OutlineInputBorder(), - ), - // Adding validator to ensure assignment name is not empty - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter a section number'; - } - return null; - }, - ), - SizedBox(height: 12), - TextFormField( - controller: _assignmentNameController, - decoration: InputDecoration( - labelText: 'Assignment name', - border: OutlineInputBorder(), - ), - // Adding validator to ensure assignment name is not empty - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter an assignment name'; - } - return null; - }, - ), - SizedBox(height: 12), - sectionTitle(title: 'Rubric'), - buildRubricTable(), - SizedBox(height: 20), - sectionTitle(title: 'Description'), - Container( - height: descriptionHeight, // Responsive height - padding: EdgeInsets.all(8.0), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - child: TextFormField( - controller: _descriptionController, - maxLines: null, // Allows multiline input - expands: true, - decoration: InputDecoration( - hintText: 'Enter description here.', - border: InputBorder.none, - ), - validator: (value) { - if (value == null || value.trim().isEmpty) { - return 'Description cannot be empty'; - } - return null; - }, - ), - ), - SizedBox(height: 20), - sectionTitle(title: 'Availability'), - SizedBox(height: 14), - Row( - children: [ - Checkbox( - value: isSubmissionEnabled, - onChanged: (value) { - setState(() { - isSubmissionEnabled = value!; - }); - }, - ), - Text('Enable'), - SizedBox(width: 10), - Expanded( - child: _buildDropdown( - 'Allow submissions from', - selectedDaySubmission, - selectedMonthSubmission, - selectedYearSubmission, - selectedHourSubmission, - selectedMinuteSubmission, - isSubmissionEnabled, - (String? newValue) { - setState(() { - selectedDaySubmission = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedMonthSubmission = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedYearSubmission = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedHourSubmission = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedMinuteSubmission = newValue!; - }); - }, - ), - ), - ], - ), - SizedBox(height: 14), - Row( - children: [ - Checkbox( - value: isDueDateEnabled, - onChanged: (value) { - setState(() { - isDueDateEnabled = value!; - }); - }, - ), - Text('Enable'), - SizedBox(width: 10), - Expanded( - child: _buildDropdown( - 'Due date', - selectedDayDue, - selectedMonthDue, - selectedYearDue, - selectedHourDue, - selectedMinuteDue, - isDueDateEnabled, - (String? newValue) { - setState(() { - selectedDayDue = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedMonthDue = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedYearDue = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedHourDue = newValue!; - }); - }, - (String? newValue) { - setState(() { - selectedMinuteDue = newValue!; - }); - }, - ), - ), - ], - ), - SizedBox(height: 14), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SizedBox( - width: buttonWidth, // Responsive button width - child: ElevatedButton( - onPressed: () async { - // Validate the form before submitting - if (_formKey.currentState!.validate() && - _descriptionController.text.trim().isNotEmpty && - _validateAvailabilityDates()) { - var api = LmsFactory.getLmsService(); - bool? token = api.isLoggedIn(); - - if (token) { - String courseId = courses - .firstWhere((course) => - course.fullName == selectedCourse) - .id - .toString(); - String assignmentName = - _assignmentNameController.text; - String sectionNumber = - _assignmentSectionController.text; - String description = _descriptionController.text.trim(); - String dueDate = - '$selectedDayDue $selectedMonthDue $selectedYearDue $selectedHourDue:$selectedMinuteDue'; - String allowSubmissionFrom = - '$selectedDaySubmission $selectedMonthSubmission $selectedYearSubmission $selectedHourSubmission:$selectedMinuteSubmission'; - - await api.createAssignment( - courseId, - sectionNumber, // Section ID - assignmentName, - allowSubmissionFrom, - dueDate, - widget.updatedJson, - description, - ); - - - if (mounted) { - - final snackBar = SnackBar( - content: Text('Assignment submitted successfully!'), - duration: Duration(seconds: 2), - ); - ScaffoldMessenger.of(context).showSnackBar(snackBar); - await Future.delayed(snackBar.duration); - if (mounted) { - Navigator.pop(context); - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => TeacherDashboard(), - ), - ); - } - - } - - - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Failed to retrieve user token.'))); - } - } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - 'Please fill out all fields and ensure a course, description, and valid availability dates are selected.'))); - } - }, - child: Text('Send to Moodle'), - ), - ), - SizedBox( - width: buttonWidth, // Responsive button width - child: ElevatedButton( - onPressed: () { - Navigator.pop(context); - }, - child: Text('Go Back to Edit Essay'), - ), - ), - ], - ), - ], - ), - ), - ), - ); - }, - ); - } - - // Dropdown Builder for each section - Widget _buildDropdown( - String label, - String selectedDay, - String selectedMonth, - String selectedYear, - String selectedHour, - String selectedMinute, - bool isEnabled, - ValueChanged onDayChanged, - ValueChanged onMonthChanged, - ValueChanged onYearChanged, - ValueChanged onHourChanged, - ValueChanged onMinuteChanged) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label), - Wrap( - spacing: 10.0, // Space between dropdowns - runSpacing: 8.0, // Space between rows when wrapping - children: [ - _buildDropdownButton(days, selectedDay, onDayChanged, isEnabled), - _buildDropdownButton( - months, selectedMonth, onMonthChanged, isEnabled), - _buildDropdownButton(years, selectedYear, onYearChanged, isEnabled), - _buildDropdownButton(hours, selectedHour, onHourChanged, isEnabled), - _buildDropdownButton( - minutes, selectedMinute, onMinuteChanged, isEnabled), - ], - ), - ], - ); - } - - // Dropdown Button Builder - Widget _buildDropdownButton(List items, String selectedValue, - ValueChanged onChanged, bool isEnabled) { - return SizedBox( - width: 103, // Adjust width as necessary - child: DropdownButton( - value: selectedValue, - onChanged: isEnabled ? onChanged : null, - items: items.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - ); - } - - // Section Title Widget - Widget sectionTitle({required String title}) { - return Text( - title, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/send_quiz_to_moodle.dart b/team_a/teamA/lib/Views/send_quiz_to_moodle.dart deleted file mode 100644 index b9c0117d..00000000 --- a/team_a/teamA/lib/Views/send_quiz_to_moodle.dart +++ /dev/null @@ -1,632 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/google_classroom/google_lms_service.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/Views/dashboard.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import '../Api/lms/moodle/moodle_lms_service.dart'; // Make sure this path is correct - -class QuizMoodle extends StatefulWidget { - final Quiz quiz; - QuizMoodle({required this.quiz}); - - @override - QuizMoodleState createState() => QuizMoodleState(); -} - -class QuizMoodleState extends State { - // Submission form dates - String selectedDaySubmission = '01'; - String selectedMonthSubmission = 'January'; - String selectedYearSubmission = '2025'; // Start from 2025 - String selectedHourSubmission = '00'; - String selectedMinuteSubmission = '00'; - late String quizasxml; - late MoodleLmsService api; - List courses = []; - String selectedCourse = 'Select a course'; - - LmsType? lmsType; - bool isLoading = false; // Added to track loading state - - @override - void initState() { - super.initState(); - quizNameController = TextEditingController(text: widget.quiz.name ?? ''); - quizQuestionsController = TextEditingController(); - quizasxml = widget.quiz.toXmlString(); - fetchCourses(); - _getLmsType(); // Fetch LMS type on init - } - - // Fetch LMS type from local storage - Future _getLmsType() async { - LmsType retrievedLmsType = LocalStorageService.getSelectedClassroom(); - setState(() { - lmsType = retrievedLmsType; - }); - } - - // Fetch courses from the controller - Future fetchCourses() async { - try { - List? courseList = LmsFactory.getLmsService().courses; - setState(() { - courses = courseList ?? []; - selectedCourse = 'Select a course'; - }); - } catch (e) { - debugPrint('Error fetching courses: $e'); - setState(() { - selectedCourse = 'No courses available'; // Handle the empty case - }); - } - } - - // Dropdown to display courses with "Select a course" as the default option - DropdownButtonFormField _buildCourseDropdown() { - return DropdownButtonFormField( - value: selectedCourse == 'Select a course' ? null : selectedCourse, - decoration: InputDecoration( - labelText: 'Course name', - border: OutlineInputBorder(), - ), - validator: (value) { - if (value == null || value == 'Select a course') { - return 'Please select a course'; - } - return null; - }, - onChanged: (String? newValue) { - setState(() { - selectedCourse = newValue!; - }); - debugPrint('Selected course: $selectedCourse'); - }, - items: [ - DropdownMenuItem( - value: 'Select a course', - child: Text('Select a course'), - ), - ...courses.map>((Course course) { - return DropdownMenuItem( - value: course.id.toString(), - child: Text(course.fullName), - ); - }), - ], - isExpanded: true, - ); - } - - // Due date selection - String selectedDayDue = '01'; - String selectedMonthDue = 'January'; - String selectedYearDue = '2025'; // Start from 2025 - String selectedHourDue = '00'; - String selectedMinuteDue = '00'; - - // Checkbox states - bool isSubmissionEnabled = true; - bool isDueDateEnabled = true; - - List days = - List.generate(31, (index) => (index + 1).toString().padLeft(2, '0')); - List months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December' - ]; - List years = ['2025', '2026', '2027']; // Years starting from 2025 - List hours = - List.generate(24, (index) => index.toString().padLeft(2, '0')); - List minutes = - List.generate(60, (index) => index.toString().padLeft(2, '0')); - - // Initial selected values for dropdowns - String selectedCategory = 'No Category Selected'; - String selectedAttempt = 'No attempt limit'; - String selectedGradingMethod = 'No grading method selected'; - - // Lists of static items for dropdowns - var categoryItems = [ - 'No Category Selected', - 'Category 1', - 'Category 2', - 'Category 3' - ]; - var attemptItems = [ - 'No attempt limit', - 'Unlimited', - 'First', - 'Second', - 'Last' - ]; - var gradingMethodItems = [ - 'No grading method selected', - 'Highest Grade', - 'Average Grade', - 'Low Grade' - ]; - - late TextEditingController quizNameController; - TextEditingController gradeController = TextEditingController(); - late TextEditingController quizQuestionsController; - TextEditingController quizSectionController = TextEditingController(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar( - title: 'Assign Assessment', - userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: SingleChildScrollView( - padding: EdgeInsets.all(15.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Padding( - padding: const EdgeInsets.only(top: 15.0), - child: Text( - 'Assign Quiz', - textDirection: TextDirection.ltr, - style: TextStyle(fontSize: 25, fontWeight: FontWeight.normal), - textAlign: TextAlign.center, - ), - ), - ), - SizedBox(height: 30), - sectionTitle(title: 'Course Name'), - _buildCourseDropdown(), - SizedBox(height: 15), - sectionTitle(title: 'Quiz Name'), - SizedBox(height: 15), - TextField( - controller: quizNameController, - decoration: InputDecoration( - labelText: 'Quiz name', - border: OutlineInputBorder(), - ), - enabled: false, - ), - SizedBox(height: 15), - sectionTitle(title: 'Section Number'), - SizedBox(height: 15), - TextField( - controller: quizSectionController, - decoration: InputDecoration( - labelText: 'Course Section Number', - border: OutlineInputBorder(), - ), - keyboardType: TextInputType.number, // Set keyboard type to number - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly // Allow only digits - ], - ), - SizedBox(height: 15), - sectionTitle(title: 'Number of Questions'), - SizedBox(height: 15), - TextField( - controller: quizQuestionsController, - decoration: InputDecoration( - labelText: 'Number of questions', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 15), - sectionTitle(title: 'Availability'), - SizedBox(height: 15), - // Submission Date - Directionality( - textDirection: TextDirection.ltr, - child: Row( - children: [ - Checkbox( - value: isSubmissionEnabled, - onChanged: (value) { - setState(() { - isSubmissionEnabled = value!; - }); - }), - Text('Enable'), - SizedBox(width: 10), - _buildDropdown( - 'Allow Submissions From Date:', - selectedDaySubmission, - selectedMonthSubmission, - selectedYearSubmission, - selectedHourSubmission, - selectedMinuteSubmission, - isSubmissionEnabled, (String? newValue) { - setState(() { - selectedDaySubmission = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedMonthSubmission = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedYearSubmission = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedHourSubmission = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedMinuteSubmission = newValue!; - }); - }), - ], - ), - ), - SizedBox(height: 16), - // Due Date - Directionality( - textDirection: TextDirection.ltr, - child: Row( - children: [ - Checkbox( - value: isDueDateEnabled, - onChanged: (value) { - setState(() { - isDueDateEnabled = value!; - }); - }, - ), - Text('Enable'), - SizedBox(width: 10), - _buildDropdown( - 'Due Date:', - selectedDayDue, - selectedMonthDue, - selectedYearDue, - selectedHourDue, - selectedMinuteDue, - isDueDateEnabled, (String? newValue) { - setState(() { - selectedDayDue = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedMonthDue = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedYearDue = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedHourDue = newValue!; - }); - }, (String? newValue) { - setState(() { - selectedMinuteDue = newValue!; - }); - }), - ], - ), - ), - SizedBox(height: 16), - Directionality( - textDirection: TextDirection.ltr, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (lmsType == LmsType.MOODLE) - ElevatedButton( - onPressed: isLoading - ? null - : () async { - setState(() { - isLoading = true; - }); - - if (selectedCourse == 'Select a course') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Please select a course to proceed.')), - ); - setState(() { - isLoading = false; - }); - return; - } - - try { - DateTime submissionDate = DateTime( - int.parse(selectedYearSubmission), - months.indexOf(selectedMonthSubmission) + 1, - int.parse(selectedDaySubmission), - int.parse(selectedHourSubmission), - int.parse(selectedMinuteSubmission), - ); - - DateTime dueDate = DateTime( - int.parse(selectedYearDue), - months.indexOf(selectedMonthDue) + 1, - int.parse(selectedDayDue), - int.parse(selectedHourDue), - int.parse(selectedMinuteDue), - ); - - String formattedDueDate = - "${dueDate.year}-${dueDate.month.toString().padLeft(2, '0')}-${dueDate.day.toString().padLeft(2, '0')}-${dueDate.hour.toString().padLeft(2, '0')}-${dueDate.minute.toString().padLeft(2, '0')}"; - - var quizid = await LmsFactory.getLmsService() - .createQuiz( - selectedCourse, - widget.quiz.name ?? 'Quiz Name', - widget.quiz.description ?? 'Quiz Description', - quizSectionController.text, - '$selectedDaySubmission $selectedMonthSubmission $selectedYearSubmission $selectedHourSubmission:$selectedMinuteSubmission', - '$selectedDayDue $selectedMonthDue $selectedYearDue $selectedHourDue:$selectedMinuteDue', - ); - print('Quiz ID: $quizid'); - - var categoryid = await LmsFactory.getLmsService() - .importQuizQuestions( - selectedCourse, quizasxml); - print('Category ID: $categoryid'); - - var randomresult = await LmsFactory.getLmsService() - .addRandomQuestions( - categoryid.toString(), - quizid.toString(), - quizQuestionsController.text); - print('Random Result: $randomresult'); - - if (randomresult == 'true') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Quiz submitted successfully to Moodle!')), - ); - await Future.delayed(Duration(seconds: 2)); - if (mounted) { - Navigator.pop(context); - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => TeacherDashboard(), - ), - ); - } - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Failed to update grades in Moodle.')), - ); - } - } catch (e) { - print('Error during quiz creation: $e'); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('An error occurred: ${e}')), - ); - } finally { - setState(() { - isLoading = false; - }); - } - }, - child: isLoading - ? CircularProgressIndicator( - color: Colors.white, - ) - : Text( - 'Send to Moodle', - textDirection: TextDirection.ltr, - ), - ), - if (lmsType == LmsType.GOOGLE) - ElevatedButton( - onPressed: isLoading - ? null - : () async { - setState(() { - isLoading = true; - }); - - if (selectedCourse == 'Select a course') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Please select a course to proceed.')), - ); - setState(() { - isLoading = false; - }); - return; - } - - try { - DateTime submissionDate = DateTime( - int.parse(selectedYearSubmission), - months.indexOf(selectedMonthSubmission) + 1, - int.parse(selectedDaySubmission), - int.parse(selectedHourSubmission), - int.parse(selectedMinuteSubmission), - ); - - DateTime dueDate = DateTime( - int.parse(selectedYearDue), - months.indexOf(selectedMonthDue) + 1, - int.parse(selectedDayDue), - int.parse(selectedHourDue), - int.parse(selectedMinuteDue), - ); - - String formattedDueDate = - "${dueDate.year}-${dueDate.month.toString().padLeft(2, '0')}-${dueDate.day.toString().padLeft(2, '0')}-${dueDate.hour.toString().padLeft(2, '0')}-${dueDate.minute.toString().padLeft(2, '0')}"; - - bool success = await GoogleLmsService() - .createAndAssignQuizFromXml( - selectedCourse, - quizNameController.text, - widget.quiz.description ?? 'Quiz Description', - quizasxml, - formattedDueDate, - ); - if (success) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Quiz submitted successfully to Google Classroom!')), - ); - await Future.delayed(Duration(seconds: 2)); - if (mounted) { - Navigator.pop(context); - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => TeacherDashboard(), - ), - ); - } - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Failed to create quiz in Google Classroom.')), - ); - } - } catch (e) { - print('Error during quiz creation: $e'); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('An error occurred: ${e}')), - ); - } finally { - setState(() { - isLoading = false; - }); - } - }, - child: isLoading - ? CircularProgressIndicator( - color: Colors.white, - ) - : Text( - 'Send to Google Classroom', - textDirection: TextDirection.ltr, - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Widget _buildDropdown( - String label, - String selectedDay, - String selectedMonth, - String selectedYear, - String selectedHour, - String selectedMinute, - bool isEnabled, - ValueChanged onDayChanged, - ValueChanged onMonthChanged, - ValueChanged onYearChanged, - ValueChanged onHourChanged, - ValueChanged onMinuteChanged) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label), - Row( - children: [ - DropdownButton( - value: selectedDay, - onChanged: isEnabled ? onDayChanged : null, - items: days.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - SizedBox(width: 5), - DropdownButton( - value: selectedMonth, - onChanged: isEnabled ? onMonthChanged : null, - items: months.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - SizedBox(width: 5), - DropdownButton( - value: selectedYear, - onChanged: isEnabled ? onYearChanged : null, - items: years.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - SizedBox(width: 5), - DropdownButton( - value: selectedHour, - onChanged: isEnabled ? onHourChanged : null, - items: hours.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - SizedBox(width: 5), - DropdownButton( - value: selectedMinute, - onChanged: isEnabled ? onMinuteChanged : null, - items: minutes.map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - ], - ), - ], - ); - } - - Widget sectionTitle({required String title}) { - return Padding( - padding: EdgeInsets.only(bottom: 8.0), - child: Text( - title, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/Views/template_view.dart b/team_a/teamA/lib/Views/template_view.dart deleted file mode 100644 index 139623e0..00000000 --- a/team_a/teamA/lib/Views/template_view.dart +++ /dev/null @@ -1,59 +0,0 @@ -import "package:flutter/material.dart"; -import "package:learninglens_app/Api/lms/factory/lms_factory.dart"; -import "package:learninglens_app/Controller/custom_appbar.dart"; - -/// -/// Template for views -/// Need to change the class name to the name based on the view you -/// are creating to include the constructor as well. -/// Need to change the class that extends State as well. Make sure -/// that the createState function returns the same name. -/// -/// The CustomAppBar is already included, but you will need to update -/// the title string. -/// -/// The content for the page begins in the children array. There is -/// a single text box as a place holder. -/// -/// To add your view to the rest of the app, you will have to add it -/// to the dashboard.dart file. On line ~213, there is a List called -/// buttonData. You will need to update the 'onPressed' section with -/// your new template. You can see examples that Derek has already -/// done on other buttons. -/// -class TemplateView extends StatefulWidget{ - TemplateView(); - - @override - State createState(){ - return _TemplateState(); - } -} - -class _TemplateState extends State{ - - @override - Widget build(BuildContext context){ - return Scaffold( - appBar: CustomAppBar( - title: 'Template View', - onRefresh: () { - // Add refresh logic here - }, - userprofileurl: LmsFactory.getLmsService().profileImage ?? '' - ), - body: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children:[ - // Add Content here - Text( - 'Place content here', - style: TextStyle(fontSize: 20), - ), - ] - ) - ) - ); - } -} diff --git a/team_a/teamA/lib/Views/user_settings.dart b/team_a/teamA/lib/Views/user_settings.dart deleted file mode 100644 index f781d7da..00000000 --- a/team_a/teamA/lib/Views/user_settings.dart +++ /dev/null @@ -1,332 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_colorpicker/flutter_colorpicker.dart'; -import 'package:learninglens_app/Api/lms/moodle/moodle_lms_service.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/notifiers/login_notifier.dart'; -import 'package:learninglens_app/notifiers/theme_notifier.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; - -class UserSettings extends StatefulWidget { - @override - UserSettingsState createState() => UserSettingsState(); -} - -class UserSettingsState extends State { - final TextEditingController _usernameController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - final TextEditingController _moodleUrlController = TextEditingController(); - - final TextEditingController _apiKeyController = TextEditingController(); - final TextEditingController _grokKeyController = TextEditingController(); - final TextEditingController _preplexityKeyController = TextEditingController(); - - final TextEditingController _googleClientIdController = - TextEditingController(); - - @override - void initState() { - super.initState(); - _loadStoredValues(); - } - - Future _loadStoredValues() async { - final username = LocalStorageService.getUsername(); - final password = LocalStorageService.getPassword(); - final moodleUrl = LocalStorageService.getMoodleUrl(); - final apiKey = LocalStorageService.getOpenAIKey(); - final preplexityKey = LocalStorageService.getPerplexityKey(); - final grokKey = LocalStorageService.getGrokKey(); - final googleClientId = LocalStorageService.getGoogleClientId(); - - setState(() { - _usernameController.text = username; - _passwordController.text = password; - _moodleUrlController.text = moodleUrl; - _apiKeyController.text = apiKey; - _preplexityKeyController.text = preplexityKey; - _grokKeyController.text = grokKey; - _googleClientIdController.text = googleClientId; - }); - } - - @override - Widget build(BuildContext context) { - final loginNotifier = Provider.of(context); - final themeColor = Provider.of(context).primaryColor; - - return Scaffold( - appBar: CustomAppBar( - title: 'User Settings', - onRefresh: () { - // Add refresh logic here - }, - userprofileurl: MoodleLmsService().profileImage ?? '', - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - child: Column( - children: [ - // Moodle Login Block - _buildMoodleLoginBlock(loginNotifier), - - const SizedBox(height: 20), - const Divider(), - - // Google Classroom Login Block - _buildGoogleClassroomLoginBlock(loginNotifier), - - const SizedBox(height: 20), - const Divider(), - - // API Key Block - _buildApiKeyBlock(loginNotifier), - - const SizedBox(height: 20), - const Divider(), - - // Theme Color Picker - Text( - 'Theme Color Picker:', - style: TextStyle(fontSize: 20), - ), - ElevatedButton( - onPressed: _pickColor, - style: ElevatedButton.styleFrom( - backgroundColor: themeColor, - foregroundColor: Theme.of(context).colorScheme.onPrimary, - ), - child: Text('Pick Theme Color'), - ), - ], - ), - ), - ), - ); - } - - // ------------------------------------------- - // Moodle Login Block - // ------------------------------------------- - Widget _buildMoodleLoginBlock(LoginNotifier loginNotifier) { - final moodleState = loginNotifier.moodleState; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Moodle Login:', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - TextField( - controller: _usernameController, - decoration: InputDecoration(labelText: 'Username'), - enabled: !moodleState.isLoggedIn, - ), - TextField( - controller: _passwordController, - decoration: InputDecoration(labelText: 'Password'), - obscureText: true, - enabled: !moodleState.isLoggedIn, - ), - TextField( - controller: _moodleUrlController, - decoration: InputDecoration(labelText: 'Moodle URL'), - enabled: !moodleState.isLoggedIn, - ), - const SizedBox(height: 10), - if (!moodleState.isLoggedIn) - ElevatedButton( - onPressed: () { - loginNotifier.signInWithMoodle( - _usernameController.text, - _passwordController.text, - _moodleUrlController.text, - ); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.green, - foregroundColor: Colors.white, - ), - child: Text('Login to Moodle'), - ), - if (moodleState.isLoggedIn) - ElevatedButton( - onPressed: loginNotifier.signOutFromMoodle, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - foregroundColor: Colors.white, - ), - child: Text('Logout from Moodle'), - ), - if (moodleState.errorMessage?.isNotEmpty ?? false) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - moodleState.errorMessage!, - style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), - ), - ), - ], - ); - } - - // ------------------------------------------- - // Google Classroom Login Block - // ------------------------------------------- - Widget _buildGoogleClassroomLoginBlock(LoginNotifier loginNotifier) { - final googleState = loginNotifier.googleState; // convenience variable - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Google Classroom Login:', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - TextField( - controller: _googleClientIdController, - decoration: InputDecoration(labelText: 'Client ID'), - enabled: false, // Make it non-editable - ), - const SizedBox(height: 10), - if (!googleState.isLoggedIn) - ElevatedButton( - onPressed: loginNotifier.signInWithGoogle, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.green, - foregroundColor: Colors.white, - ), - child: Text('Login to Google Classroom'), - ), - if (googleState.isLoggedIn) - ElevatedButton( - onPressed: loginNotifier.signOutFromGoogle, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.red, - foregroundColor: Colors.white, - ), - child: Text('Logout from Google Classroom'), - ), - if (googleState.errorMessage?.isNotEmpty ?? false) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - googleState.errorMessage!, - style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), - ), - ), - ], - ); - } - - // ------------------------------------------- - // API Key Block - // ------------------------------------------- - Widget _buildApiKeyBlock(LoginNotifier loginNotifier) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'API Keys:', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - _buildApiKeyField( - label: 'OpenAI API Key', - controller: _apiKeyController, - loginNotifier: loginNotifier, - keyType: LLMKey.openAI, - ), - _buildApiKeyField( - label: 'Preplexity AI API Key', - controller: _preplexityKeyController, - loginNotifier: loginNotifier, - keyType: LLMKey.perplexity, - ), - _buildApiKeyField( - label: 'Grok AI API Key', - controller: _grokKeyController, - loginNotifier: loginNotifier, - keyType: LLMKey.grok, - ), - ], - ); - } - - Widget _buildApiKeyField({ - required String label, - required TextEditingController controller, - required LoginNotifier loginNotifier, - required LLMKey keyType, - }) { - return Column( - children: [ - TextField( - controller: controller, - obscureText: true, - decoration: InputDecoration(labelText: label), - enabled: controller.text.isEmpty, - // If you want to disable the TextField once it has a value, - // keep this. Otherwise, feel free to remove "enabled: controller.text.isEmpty". - ), - const SizedBox(height: 10), - ElevatedButton( - onPressed: () { - loginNotifier.saveLLMKey(keyType, controller.text); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - ), - child: Text('Save'), - ), - const Divider(), - ], - ); - } - - // ------------------------------------------- - // Theme Color Picker - // ------------------------------------------- - void _pickColor() async { - await showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text( - 'Pick a theme color', - style: TextStyle(color: Theme.of(context).colorScheme.inversePrimary), - ), - content: SingleChildScrollView( - child: SizedBox( - width: 300, - height: 50, - child: BlockPicker( - pickerColor: - Provider.of(context, listen: false).primaryColor, - onColorChanged: (color) { - Provider.of(context, listen: false) - .updateTheme(color); - }, - availableColors: [ - Colors.red, - Colors.green, - Colors.blue, - Colors.orange, - Colors.purple, - ], - ), - ), - ), - actions: [ - TextButton( - child: Text('Select'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ), - ); - } -} diff --git a/team_a/teamA/lib/Views/view_quiz.dart b/team_a/teamA/lib/Views/view_quiz.dart deleted file mode 100644 index 4d23d49e..00000000 --- a/team_a/teamA/lib/Views/view_quiz.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/quiz_type.dart'; - -class ViewQuiz extends StatelessWidget { - final int quizId; - final bool showAppBar = false; - - ViewQuiz({required this.quizId}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: showAppBar - ? CustomAppBar( - title: 'Assessments', - userprofileurl: LmsFactory.getLmsService().profileImage ?? '', - ) - : null, - body: SingleChildScrollView( - child: Center( - child: Column( - children: [ - Text('Questions', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - FutureBuilder?>( - future: LmsFactory.getLmsService().getQuestionsFromQuiz(quizId), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error loading questions')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No questions found')); - } else { - final questionList = snapshot.data!; - List> questionsData = []; - questionsData = questionList.map((question) { - return { - 'questionNumber': question.name, - 'questionType': question.questionType, - 'questionText': question.questionText, - }; - }).toList(); - - return SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: BorderRadius.circular(8.0), - ), - margin: EdgeInsets.all(8.0), - child: DataTable( - headingRowColor: MaterialStateProperty.all( - Theme.of(context) - .colorScheme - .primary - .withOpacity(0.1)), - columns: const [ - DataColumn(label: Text('Question No.')), - DataColumn(label: Text('Type')), - DataColumn(label: Text('Question Text')), - ], - rows: questionsData.map((row) { - return DataRow(cells: [ - DataCell( - SizedBox( - width: 90, - child: Text( - row['questionNumber'].toString(), - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - ), - ), - DataCell( - SizedBox( - width: 90, - child: Text( - row['questionType'].toString(), - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - ), - ), - DataCell( - SizedBox( - child: Text( - row['questionText'].toString(), - softWrap: true, - overflow: TextOverflow.ellipsis, - maxLines: 4, - ), - ), - ), - ]); - }).toList(), - ), - ), - ); - } - }, - ), - ], - ), - )), - ); - } -} diff --git a/team_a/teamA/lib/Views/view_submission_detail.dart b/team_a/teamA/lib/Views/view_submission_detail.dart deleted file mode 100644 index 4bc3994f..00000000 --- a/team_a/teamA/lib/Views/view_submission_detail.dart +++ /dev/null @@ -1,377 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Controller/custom_appbar.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/moodle_rubric.dart'; -import 'package:learninglens_app/Views/essays_view.dart'; -import 'dart:math'; - -class SubmissionDetail extends StatefulWidget { - final Participant participant; - final Submission submission; - final String courseId; - - SubmissionDetail( - {required this.participant, - required this.submission, - required this.courseId}); - - @override - SubmissionDetailState createState() => SubmissionDetailState(); -} - -class SubmissionDetailState extends State { - MoodleRubric? rubric; - List? scores; - bool isLoading = true; - String errorMessage = ''; - Map selectedLevels = {}; // Map to store selected levels - Map remarks = {}; // Map to store remarks - Map remarkControllers = - {}; // Controllers for each remark - - @override - void initState() { - super.initState(); - fetchRubric(); - } - - Future fetchRubric() async { - print('Fetching Rubric for assignment ID: ${widget.submission.assignmentId}'); - int? contextId = await LmsFactory.getLmsService() - .getContextId(widget.submission.assignmentId, widget.courseId); - if (contextId != null) { - var fetchedRubric = await LmsFactory.getLmsService() - .getRubric(widget.submission.assignmentId.toString()); - print('Fetched Rubric: $fetchedRubric'); - var submissionScores = await LmsFactory.getLmsService().getRubricGrades( - widget.submission.assignmentId, widget.participant.id); - print('Submission Scores: $submissionScores'); - - setState(() { - rubric = fetchedRubric; - scores = submissionScores; - // Populate selectedLevels and remarks from submissionScores - for (var score in scores!) { - selectedLevels[score['criterionid']] = score['levelid']; - remarks[score['criterionid']] = score['remark'] ?? ''; - remarkControllers[score['criterionid']] = - TextEditingController(text: remarks[score['criterionid']]); - } - isLoading = false; - }); - - if (fetchedRubric == null) { - setState(() { - errorMessage = 'No rubric available for this assignment.'; - }); - } - } else { - setState(() { - isLoading = false; - errorMessage = 'Failed to retrieve context ID for the assignment.'; - }); - } - } - - // Save updated submission scores and remarks as JSON - void saveSubmissionScores() async { - List> updatedScores = []; - selectedLevels.forEach((criterionid, levelid) { - updatedScores.add({ - 'criterionid': criterionid, - 'levelid': levelid, - 'remark': remarks[criterionid] ?? '' - }); - }); - - String jsonScores = jsonEncode(updatedScores); - print('Updated Submission Scores and Remarks: $jsonScores'); - // Handle further actions like saving to a database or API here. - // SubmissionListState? submissionListState = context.findAncestorStateOfType(); - bool results = await LmsFactory.getLmsService().setRubricGrades( - widget.submission.assignmentId, widget.participant.id, jsonScores); - print('Results: $results'); - if (mounted) { - if (results) { - final snackBar = SnackBar( - content: Text('Grades updated successfully!'), - duration: Duration(seconds: 2), - ); - ScaffoldMessenger.of(context).showSnackBar(snackBar); - await Future.delayed(snackBar.duration); - if (mounted) { - Navigator.pop(context); - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => EssaysView(), - ), - ); - } - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to update grades.')), - ); - } - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: CustomAppBar(title: 'Submission Details From here', userprofileurl: LmsFactory.getLmsService().profileImage ?? ''), - body: isLoading - ? Center(child: CircularProgressIndicator()) - : Padding( - padding: EdgeInsets.all(16.0), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // User ID - Text( - widget.participant.fullname, - style: - TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(height: 8), - - // Status - Text( - 'Status: ${widget.submission.status}', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 8), - - // Submission Time - Text( - 'Submitted on: ${widget.submission.submissionTime.toLocal()}', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 16), - - // Online Text - Text( - 'Online Text:', - style: - TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(height: 8), - widget.submission.onlineText.isNotEmpty - ? Text( - widget.submission.onlineText.replaceAll(RegExp(r"<[^>]*>"), ""), - style: TextStyle(fontSize: 16), - ) - : Text( - 'No content provided.', - style: TextStyle( - fontSize: 16, fontStyle: FontStyle.italic), - ), - SizedBox(height: 16), - - // Rubric Section - rubric != null - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Rubric:', - style: TextStyle( - fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(height: 8), - - // Rubric table (replace rubricTable with new table) - buildInteractiveRubricTable(), - SizedBox(height: 16), - ElevatedButton( - onPressed: saveSubmissionScores, - child: Text('Save'), - ), - ], - ) - : errorMessage.isNotEmpty - ? Text( - errorMessage, - style: TextStyle( - fontSize: 50, - fontStyle: FontStyle.italic, - color: Colors.red), - ) - : Text( - 'No rubric available.', - style: TextStyle( - fontSize: 16, fontStyle: FontStyle.italic), - ), - ], - ), - ), - ), - ); - } - -// Interactive rubric table with dynamic width expansion - Widget buildInteractiveRubricTable() { - if (rubric == null) - return Container(); // No rubric, return an empty container - - List tableRows = []; - - // First row: Header row with scores and remarks - tableRows.add( - TableRow( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, - ), - children: [ - TableCell( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text( - 'Criteria', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - softWrap: true, - overflow: TextOverflow.visible, - ), - ), - ), - ...rubric!.criteria.first.levels.map((level) { - return TableCell( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Align( - alignment: Alignment.center, - child: Text( - '${level.score} pts', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - softWrap: true, - overflow: TextOverflow.visible, - ), - ), - ), - ); - }).toList(), - TableCell( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text( - 'Remarks', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - softWrap: true, - overflow: TextOverflow.visible, - ), - ), - ), - ], - ), - ); - - // Add rows for each criterion - for (var criterion in rubric!.criteria) { - tableRows.add( - TableRow( - children: [ - TableCell( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text( - criterion.description, - softWrap: true, - overflow: TextOverflow.visible, - ), - ), - ), - ...criterion.levels.map((level) { - bool isSelected = selectedLevels[criterion.id] == level.id; - return TableCell( - verticalAlignment: TableCellVerticalAlignment.fill, - child: InkWell( - onTap: () { - setState(() { - selectedLevels[criterion.id] = level.id; - }); - }, - child: Container( - color: isSelected - ? Theme.of(context).colorScheme.primary.withOpacity(0.5) - : Colors.transparent, - padding: EdgeInsets.all(8.0), - child: Align( - alignment: Alignment.topLeft, - child: Text( - level.description, - softWrap: true, - overflow: TextOverflow.visible, - ), - ), - ), - ), - ); - }), - TableCell( - child: Padding( - padding: EdgeInsets.all(8.0), - child: TextField( - controller: remarkControllers[criterion.id], - onChanged: (text) { - remarks[criterion.id] = text; - }, - decoration: InputDecoration( - hintText: 'Enter remark', - border: OutlineInputBorder(), - ), - minLines: 4, - maxLines: 6, - ), - ), - ), - ], - ), - ); - } - - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - double minWidth = 800; - double tableWidth = max(minWidth, constraints.maxWidth); - - return SingleChildScrollView( - scrollDirection: Axis.vertical, // Enable vertical scrolling - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: tableWidth), - child: Table( - border: TableBorder.all( - color: Colors.black, - width: 1.0), // Outer border for the table - columnWidths: { - 0: FlexColumnWidth(.5), // Criteria column - for (int i = 1; - i <= rubric!.criteria.first.levels.length; - i++) - i: FlexColumnWidth(1), // Score columns - rubric!.criteria.first.levels.length + 1: - FlexColumnWidth(1.8), // Remarks column - }, - children: tableRows, - ), - ), - ), - ); - }, - ); - } -} diff --git a/team_a/teamA/lib/Views/view_submissions.dart b/team_a/teamA/lib/Views/view_submissions.dart deleted file mode 100644 index 0ed3eca7..00000000 --- a/team_a/teamA/lib/Views/view_submissions.dart +++ /dev/null @@ -1,638 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; -import 'package:learninglens_app/Api/llm/grok_api.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/Api/llm/openai_api.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; -import 'package:learninglens_app/beans/participant.dart'; -import 'view_submission_detail.dart'; -import '../Api/llm/perplexity_api.dart'; -import 'dart:convert'; -import 'package:intl/intl.dart'; - -class SubmissionList extends StatefulWidget { - final int assignmentId; - final String courseId; - - SubmissionList({ - Key? key, - required this.assignmentId, - required this.courseId, - }) : super(key: key); - - @override - SubmissionListState createState() => SubmissionListState(); -} - -class SubmissionListState extends State { - LmsInterface api = LmsFactory.getLmsService(); - Map isLoadingMap = {}; - Map llmSelectionMap = {}; - - late Future> futureSubmissionsWithGrades = - api.getSubmissionsWithGrades(widget.assignmentId); - late Future> futureParticipants = - api.getCourseParticipants(widget.courseId); - - final LlmType defaultLlm = LlmType.PERPLEXITY; - - final perplexityApiKey = LocalStorageService.getPerplexityKey(); - final openApiKey = LocalStorageService.getOpenAIKey(); - final grokApiKey = LocalStorageService.getGrokKey(); - - LlmType? selectedLLM; - - String filterOption = 'All'; - String fullNameFilter = ''; - - String getApiKey(LlmType selectedLLM) { - switch (selectedLLM) { - case LlmType.CHATGPT: - return openApiKey; - case LlmType.GROK: - return grokApiKey; - default: - return perplexityApiKey; - } - } - - @override - void initState() { - super.initState(); - _fetchData(); - } - - void _fetchData() { - setState(() { - futureSubmissionsWithGrades = - api.getSubmissionsWithGrades(widget.assignmentId); - futureParticipants = api.getCourseParticipants(widget.courseId); - }); - } - - void _handleLLMChanged(int participantId, LlmType? newValue) { - setState(() { - if (newValue != null) { - llmSelectionMap[participantId] = newValue; - } - }); - } - - void _handleFilterChanged(String? newValue) { - setState(() { - if (newValue != null) { - filterOption = newValue; - } - }); - } - - void _handleFullNameFilterChanged(String newValue) { - setState(() { - fullNameFilter = newValue; - }); - } - - // Widget to display the "under development" error with icon and back button - Widget _buildUnderDevelopmentError(BuildContext context) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.construction, // Construction icon to indicate "under development" - size: 60, - color: Theme.of(context).colorScheme.error, - ), - SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Text( - 'Submissions/Grading feature is currently not available for Google Classroom. Please reach out to the developer for more information.', - style: TextStyle( - color: Theme.of(context).colorScheme.error, - fontSize: 16, - ), - textAlign: TextAlign.center, - ), - ), - SizedBox(height: 24), - ElevatedButton( - onPressed: () { - Navigator.pop(context); // Navigate back to the previous screen - }, - child: Text('Back'), - ), - ], - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Expanded( - child: DropdownButton( - value: filterOption, - onChanged: _handleFilterChanged, - items: ['All', 'With Submission', 'Without Submission'] - .map>((String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), - ), - ), - SizedBox(width: 8.0), - Expanded( - child: TextField( - decoration: InputDecoration( - labelText: 'Filter by Name', - border: OutlineInputBorder(), - ), - onChanged: _handleFullNameFilterChanged, - ), - ), - ], - ), - ), - Expanded( - child: Stack( - children: [ - FutureBuilder>( - future: futureParticipants, - builder: (BuildContext context, - AsyncSnapshot> participantSnapshot) { - if (participantSnapshot.connectionState == - ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (participantSnapshot.hasError) { - if (participantSnapshot.error is UnimplementedError) { - return _buildUnderDevelopmentError(context); - } - return Center( - child: Text('Error: ${participantSnapshot.error}')); - } else if (!participantSnapshot.hasData || - participantSnapshot.data!.isEmpty) { - return Center(child: Text('No participants found.')); - } else { - return FutureBuilder>( - future: futureSubmissionsWithGrades, - builder: (BuildContext context, - AsyncSnapshot> - submissionSnapshot) { - if (submissionSnapshot.connectionState == - ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (submissionSnapshot.hasError) { - if (submissionSnapshot.error is UnimplementedError) { - return _buildUnderDevelopmentError(context); - } - return Center( - child: - Text('Error: ${submissionSnapshot.error}')); - } else { - List participants = - participantSnapshot.data!; - List submissionsWithGrades = - submissionSnapshot.data ?? []; - - participants.sort((a, b) { - int lastNameComparison = - a.lastname.compareTo(b.lastname); - if (lastNameComparison != 0) { - return lastNameComparison; - } else { - return a.firstname.compareTo(b.firstname); - } - }); - - if (filterOption == 'With Submission') { - participants = participants.where((participant) { - return submissionsWithGrades.any((sub) => - sub.submission.userid == participant.id); - }).toList(); - } else if (filterOption == 'Without Submission') { - participants = participants.where((participant) { - return !submissionsWithGrades.any((sub) => - sub.submission.userid == participant.id); - }).toList(); - } - - if (fullNameFilter.isNotEmpty) { - participants = participants.where((participant) { - return participant.fullname - .toLowerCase() - .contains(fullNameFilter.toLowerCase()); - }).toList(); - } - - return SingleChildScrollView( - child: Wrap( - spacing: 8.0, - runSpacing: 8.0, - alignment: WrapAlignment.center, - children: participants.map((participant) { - SubmissionWithGrade? submissionWithGrade = - submissionsWithGrades - .where((sub) => - sub.submission.userid == - participant.id) - .firstOrNull; - - bool isLoading = - isLoadingMap[participant.id] ?? false; - LlmType selectedLLM = llmSelectionMap[ - participant.id] ?? - defaultLlm; - return SizedBox( - width: MediaQuery.of(context).size.width < - 450 - ? double.infinity - : 450, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer, - border: Border.all( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - width: 2.0, - ), - borderRadius: - BorderRadius.circular(12.0), - ), - margin: EdgeInsets.symmetric( - vertical: 8, horizontal: 16), - child: Card( - color: Theme.of(context) - .colorScheme - .secondaryContainer, - elevation: 0, - child: ListTile( - leading: CircleAvatar( - backgroundColor: Theme.of(context) - .colorScheme - .onSecondary, - child: Text( - participant.fullname - .substring(0, 1) - .toUpperCase(), - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - ), - ), - ), - title: Text(participant.fullname), - subtitle: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - if (submissionWithGrade != null) - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - 'Grade Status: ${submissionWithGrade.submission.gradingStatus}'), - Text( - 'Status: ${submissionWithGrade.submission.status}'), - Text( - 'Submitted on: ${DateFormat('MMM d, yyyy h:mm a').format(submissionWithGrade.submission.submissionTime.toLocal())}'), - Text( - 'Grade: ${submissionWithGrade.grade != null ? submissionWithGrade.grade!.grade.toString() : "Not graded yet"}'), - SizedBox(height: 6), - // DropdownButton( - DropdownButtonFormField( - value: selectedLLM, - decoration: InputDecoration( - labelText: 'AI', - ), - onChanged: (newValue) => - _handleLLMChanged( - participant.id, - newValue), - items: LlmType.values - .map((LlmType llm) { - return DropdownMenuItem< - LlmType>( - value: llm, - enabled: - LocalStorageService - .userHasLlmKey( - llm), - child: Text( - llm.displayName, - style: TextStyle( - color: LocalStorageService - .userHasLlmKey( - llm) - ? Colors - .black87 - : Colors.grey, - ), - ), - ); - }).toList(), - ), - SizedBox(height: 4), - ], - ) - else - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox(height: 52), - Text('No Submission', - style: TextStyle( - fontWeight: - FontWeight.bold, - fontSize: 16, - color: Theme.of( - context) - .colorScheme - .error)), - SizedBox(height: 84), - ], - ), - SizedBox(height: 8), - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - if (submissionWithGrade != - null) - isLoading - ? CircularProgressIndicator() - : ElevatedButton( - onPressed: - () async { - try { - setState(() { - isLoadingMap[ - participant - .id] = - true; - }); - - var submissionText = - submissionWithGrade - .submission - .onlineText; - int? contextId = - await LmsFactory - .getLmsService() - .getContextId( - widget - .assignmentId, - widget - .courseId); - - var fetchedRubric; - if (contextId != - null) { - fetchedRubric = - await LmsFactory - .getLmsService() - .getRubric(widget - .assignmentId - .toString()); - if (fetchedRubric == - null) { - print( - 'Failed to fetch rubric.'); - return; - } - fetchedRubric = - jsonEncode(fetchedRubric - ?.toJson() ?? - {}); - } - - String - queryPrompt = - ''' - I am building a program that generates essay rubric assignments that teachers can distribute to students - who can then submit their responses to be graded. Here is an example format of a rubric roughly: - [ - { - "id": 82, - "rubric_criteria": [ - { - "id": 52, - "description": "Content", - "levels": [ - { - "id": 157, - "score": 1, - "definition": "Poor" - }, - { - "id": 156, - "score": 3, - "definition": "Good" - }, - { - "id": 155, - "score": 5, - "definition": "Excellent" - } - ] - }, - { - "id": 53, - "description": "Clarity", - "levels": [ - { - "id": 160, - "score": 1, - "definition": "Unclear" - }, - { - "id": 159, - "score": 3, - "definition": "Somewhat Clear" - }, - { - "id": 158, - "score": 5, - "definition": "Very Clear" - } - ] - } - ] - } - ] - - I have the following generated essay rubric: - Rubric: $fetchedRubric - - Grade the following submission based on that rubric: - Submission: $submissionText - - You must reply with a representation of the rubric in JSON format that matches this example format, - obviously put your generated scores in and be specific with the remarks on the scoring and give specific examples from the - submitted assignment that were either good or bad depending on the score given. Also cut out anything that is not - the json response. No extraneous comments outside that: - [ - { - "criterionid": 67, - "criterion_description": "Content", - "levelid": 236, - "level_description": "Essay is mostly well-organized, with few issues in flow", - "score": 6, - "remark": "The essay has a clear structure and transitions between paragraphs. Each paragraph focuses on a different aspect of having a park, such as relaxation, activity, and aesthetics. However, there are a few places where the flow could be improved, like the transition between the third and fourth paragraphs." - }, - { - "criterionid": 68, - "criterion_description": "Use of Evidence", - "levelid": 243, - "level_description": "Good use of evidence with occasional gaps", - "score": 6, - "remark": "The essay uses good evidence to support its claims, such as 'Spending time outside can make us feel happier and less anxious, which would help us do better in class.' However, there are occasional gaps where more specific or detailed evidence could strengthen the arguments further." - } - ] - '''; - - String apiKey = - getApiKey( - selectedLLM); - dynamic - llmInstance; - if (selectedLLM == - LlmType - .CHATGPT) { - llmInstance = - OpenAiLLM( - apiKey); - } else if (selectedLLM == - LlmType - .GROK) { - llmInstance = - GrokLLM( - apiKey); - } else { - llmInstance = - PerplexityLLM( - apiKey); - } - dynamic - gradedResponse = - await llmInstance - .postToLlm( - queryPrompt); - gradedResponse = - gradedResponse - .replaceAll( - '```json', - '') - .replaceAll( - '```', - '') - .trim(); - var results = await LmsFactory - .getLmsService() - .setRubricGrades( - widget - .assignmentId, - participant - .id, - gradedResponse); - _fetchData(); - Navigator.push( - context, - MaterialPageRoute( - builder: - (context) => - SubmissionDetail( - participant: - participant, - submission: - submissionWithGrade - .submission, - courseId: widget - .courseId, - ), - ), - ); - print( - 'Results: $results'); - } catch (e) { - print( - 'An error occurred: $e'); - } finally { - setState(() { - isLoadingMap[ - participant - .id] = - false; - }); - } - }, - child: - Text('Grade'), - ), - SizedBox(width: 8), - if (submissionWithGrade != - null) - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - SubmissionDetail( - participant: - participant, - submission: - submissionWithGrade - .submission, - courseId: widget - .courseId, - ), - ), - ); - }, - child: - Text('View Details'), - ), - ], - ), - ], - ), - isThreeLine: true, - ), - ), - ), - ); - }).toList(), - ), - ); - } - }, - ); - } - }, - ), - ], - ), - ), - ], - ), - ); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/answer.dart b/team_a/teamA/lib/beans/answer.dart deleted file mode 100644 index f953cc89..00000000 --- a/team_a/teamA/lib/beans/answer.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; - -// A single answer for a Question object. Used by all question types except for essay. -class Answer { - String answerText; // Multiple choice text - required - String fraction; // Point value from 0 (incorrect) to 100 (correct) - required - String? feedbackText; // Feedback for the choice - optional - - // Simple constructor. Feedback param is optional. - Answer(this.answerText, this.fraction, [this.feedbackText]); - - // XML factory constructor - factory Answer.fromXml(XmlElement answerElement) { - return Answer( - answerElement.getElement(XmlConsts.text)?.innerText ?? 'UNKNOWN', - answerElement.getAttribute(XmlConsts.fraction) ?? '100', - answerElement - .getElement(XmlConsts.feedback) - ?.getElement(XmlConsts.text) - ?.innerText); - } - - void buildXml(XmlBuilder builder) { - builder.element(XmlConsts.answer, attributes: {XmlConsts.fraction: fraction}, nest: () { - builder.element(XmlConsts.text, nest: answerText); - if (feedbackText != null) { - builder.element(XmlConsts.feedback, nest: () { - builder.element(XmlConsts.text, nest: feedbackText); - }); - } - }); - } - - @override - String toString() { - final sb = StringBuffer(); - sb.write(answerText); - sb.write(' <= ($fraction%)'); - if (feedbackText != null) { - sb.write(' - $feedbackText'); - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/assignment.dart b/team_a/teamA/lib/beans/assignment.dart deleted file mode 100644 index bee75071..00000000 --- a/team_a/teamA/lib/beans/assignment.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; -import 'package:learninglens_app/beans/submission_with_grade.dart'; - -class Assignment implements LearningLensInterface { - final int? id; - final String name; - final String description; - final DateTime? dueDate; - final DateTime? allowsubmissionsfromdate; - final DateTime? cutoffDate; - final bool isDraft; - final int maxAttempts; - final int gradingStatus; - final int courseId; - - final List? submissionsWithGrades; - - Assignment({ - this.id, - required this.name, - required this.description, - this.dueDate, - this.allowsubmissionsfromdate, - this.cutoffDate, - required this.isDraft, - required this.maxAttempts, - required this.gradingStatus, - required this.courseId, - this.submissionsWithGrades, - }); - - Assignment.empty() - : id = null, - name = '', - description = '', - dueDate = null, - allowsubmissionsfromdate = null, - cutoffDate = null, - isDraft = false, - maxAttempts = 0, - gradingStatus = 0, - courseId = 0, - submissionsWithGrades = null; - - @override - Assignment fromMoodleJson(Map json) { - return Assignment( - id: json['id'] ?? 0, - name: json['name'] ?? 'Untitled', - description: json['description'] ?? json['intro'] ?? '', - dueDate: json['duedate'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['duedate'] * 1000) - : null, - allowsubmissionsfromdate: json['allowsubmissionsfromdate'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['allowsubmissionsfromdate'] * 1000) - : null, - cutoffDate: json['cutoffdate'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['cutoffdate'] * 1000) - : null, - isDraft: json['submissiondrafts'] == 1, - maxAttempts: json['maxattempts'] ?? 0, - gradingStatus: json['gradingstatus'] ?? 0, - courseId: json['course'] ?? 0, - ); - } - - @override - Assignment fromGoogleJson(Map json) { - return Assignment( - id: int.parse(json['id']), - name: json['title'] ?? 'Untitled', - description: json['description'] ?? '', - dueDate: json['dueDate'] != null - ? DateTime(json['dueDate']['year'], - json['dueDate']['month'], - json['dueDate']['day']) - : null, - allowsubmissionsfromdate: json['creationTime'] != null - ? DateTime.parse(json['creationTime']) - : null, - cutoffDate: json['dueDate'] != null - ? DateTime(json['dueDate']['year'], - json['dueDate']['month'], - json['dueDate']['day']) - : null, - isDraft: false, - maxAttempts: 1, - gradingStatus: 0, // TODO: figure out grading status - courseId: int.parse(json['courseId']), - ); - } - @override - String toString() { - return "$name"; - } - -} diff --git a/team_a/teamA/lib/beans/assignment_form.dart b/team_a/teamA/lib/beans/assignment_form.dart deleted file mode 100644 index 611cb6b9..00000000 --- a/team_a/teamA/lib/beans/assignment_form.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Object to pass user-specified parameters to LLM API. -class AssignmentForm { - String? gradingCriteria; - String subject; - String topic; - String gradeLevel; - int maximumGrade; - int? assignmentCount; - int trueFalseCount; - int shortAnswerCount; - int multipleChoiceCount; - String? codingLanguage; - String title; - - AssignmentForm( - {required this.subject, - required this.topic, - required this.gradeLevel, - required this.title, - required this.trueFalseCount, - required this.shortAnswerCount, - required this.multipleChoiceCount, - required this.maximumGrade, - this.assignmentCount, - this.gradingCriteria, - this.codingLanguage}); -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/course.dart b/team_a/teamA/lib/beans/course.dart deleted file mode 100644 index 52f10961..00000000 --- a/team_a/teamA/lib/beans/course.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/assignment.dart'; - -class Course implements LearningLensInterface { - int id; - String shortName; - String fullName; - DateTime startdate; - DateTime enddate; - String courseId; - String? teacherFolderId; - String? subject; - - List? quizzes; - List? essays; - int? quizTopicId; - int? essayTopicId; - - Course(this.id, this.shortName, this.courseId, this.fullName, this.startdate, - this.enddate, {this.teacherFolderId, this.subject, this.quizzes, this.essays}); - - Course.empty() - : id = 0, - shortName = '', - courseId = '', - fullName = '', - startdate = DateTime.now(), - enddate = DateTime.now(), - teacherFolderId = '', - subject = null, - quizzes = null, - essays = null; - - static String dateFormatted(DateTime date) { - return '${date.month}/${date.day}/${date.year}'; - } - - @override - Course fromMoodleJson(Map json) { - return Course( - json['id'], - json['shortname'] ?? '', - json['idnumber'] ?? '', - json['fullname'] ?? '', - DateTime.fromMillisecondsSinceEpoch(json['startdate'] * 1000), - DateTime.fromMillisecondsSinceEpoch(json['enddate'] * 1000), - subject: json['subject'] ?? 'General', - ); - } - - @override - Course fromGoogleJson(Map json) { - // TODO: Figure out an end date. - return Course( - int.parse(json['id']), - json['name'], - json['section'], - json['name'], - DateTime.parse(json['creationTime']), - DateTime.parse(json['updateTime']).add(Duration(days: 180)), - teacherFolderId: json['teacherFolder']['id'], - ); - } - - @override - String toString() { - return "$shortName ($fullName) $id"; - } -} diff --git a/team_a/teamA/lib/beans/criterion.dart b/team_a/teamA/lib/beans/criterion.dart deleted file mode 100644 index 526e1a9e..00000000 --- a/team_a/teamA/lib/beans/criterion.dart +++ /dev/null @@ -1,38 +0,0 @@ -//A criterion represents a single criteria for use in rubric data -class Criterion -{ - //The name of the criterion, represents the quality being assessed - String name; - //The weight of the criterion, represents the grade percentage of the category - num points; - /// First String in map represents the scale level (e.g. Excellent, Poor) - /// Second String represents the description of the critiera - Map descriptions; - //Holds the default description before it's filled in with scale information - String defaultDesc; - //Defines the available scale descriptions - final List scale3 = ["High", "Moderate", "Low"]; - final List scale4 = ["Outstanding", "Excellent", "Good", "Poor"]; - final List scale5 = [ - "Exceptional", - "Highly effective", - "Effective", - "Inconsistent", - "Unsatisfactory" - ]; - //Creates Criterion object - Criterion(this.name, this.points, this.descriptions, this.defaultDesc); - //Creates Criterion object from JSON asset - Criterion.fromJson(Map json) - : name = json['Name'], - points = 0, - descriptions = {}, - defaultDesc = json['Description']; - - void setWeight(num weight) { - points = weight; - } - void addDescriptions(List scale, List values) { - descriptions = Map.fromIterables(scale, values); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/file_name_and_bytes.dart b/team_a/teamA/lib/beans/file_name_and_bytes.dart deleted file mode 100644 index 168a9ee1..00000000 --- a/team_a/teamA/lib/beans/file_name_and_bytes.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'dart:typed_data'; - -// Helper bean class for file uploading. -class FileNameAndBytes { - final String filename; - final Uint8List bytes; - - FileNameAndBytes(this.filename, this.bytes); - - @override - String toString() { - return "$filename: ${bytes.lengthInBytes} bytes"; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/g_question_form_data.dart b/team_a/teamA/lib/beans/g_question_form_data.dart deleted file mode 100644 index e6947192..00000000 --- a/team_a/teamA/lib/beans/g_question_form_data.dart +++ /dev/null @@ -1,27 +0,0 @@ -class QuestionData { - final String question; - final List options; - - QuestionData({required this.question, required this.options}); -} - -// Define a class to hold the form title, questions, and additional assignment details -class FormData { - final String title; - final List questions; - final String? startDate; - final String? endDate; - final String? formUrl; - final String? status; - - FormData({ - required this.title, - required this.questions, - this.startDate, - this.endDate, - this.formUrl, - this.status, - }); -} - - diff --git a/team_a/teamA/lib/beans/grade.dart b/team_a/teamA/lib/beans/grade.dart deleted file mode 100644 index 1a8cb32b..00000000 --- a/team_a/teamA/lib/beans/grade.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class Grade implements LearningLensInterface { - final int id; - final int userid; - final double grade; - final int grader; - final DateTime timecreated; - final DateTime timemodified; - - Grade({ - required this.id, - required this.userid, - required this.grade, - required this.grader, - required this.timecreated, - required this.timemodified, - }); - - Grade.empty() - : id = 0, - userid = 0, - grade = 0.0, - grader = 0, - timecreated = DateTime.now(), - timemodified = DateTime.now(); - - @override - Grade fromMoodleJson(Map json) { - return Grade( - id: json['id'] ?? 0, - userid: json['userid'] ?? 0, - grade: json['grade'] != null ? double.parse(json['grade']) : 0.0, - grader: json['grader'] ?? 0, - timecreated: DateTime.fromMillisecondsSinceEpoch(json['timecreated'] * 1000), - timemodified: DateTime.fromMillisecondsSinceEpoch(json['timemodified'] * 1000), - ); - } - - @override - Grade fromGoogleJson(Map json) { - // TODO: Map Google Classroom JSON to Grade. - throw UnimplementedError(); - } -} diff --git a/team_a/teamA/lib/beans/learning_lens_interface.dart b/team_a/teamA/lib/beans/learning_lens_interface.dart deleted file mode 100644 index 21adb0fa..00000000 --- a/team_a/teamA/lib/beans/learning_lens_interface.dart +++ /dev/null @@ -1,8 +0,0 @@ -abstract class LearningLensInterface { - // Force all subclasses to implement this method - LearningLensInterface fromMoodleJson(Map json); - - // TODO: Implement this method - LearningLensInterface fromGoogleJson(Map json); - -} diff --git a/team_a/teamA/lib/beans/lesson_plan.dart b/team_a/teamA/lib/beans/lesson_plan.dart deleted file mode 100644 index 069898b8..00000000 --- a/team_a/teamA/lib/beans/lesson_plan.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class LessonPlan implements LearningLensInterface { - final int id; - final String name; - final String intro; - final int timemodified; - - LessonPlan({ - required this.id, - required this.name, - required this.intro, - required this.timemodified, - }); - - // Empty constructor - LessonPlan.empty() - : id = 0, - name = '', - intro = '', - timemodified = 0; - - @override - LessonPlan fromMoodleJson(Map json) { - return LessonPlan( - id: json['id'], - name: json['name'], - intro: json['intro'], - timemodified: json['timemodified'], - ); - } - - @override - LessonPlan fromGoogleJson(Map json) { - print('LessonPlan.fromGoogleJson: $json'); - - return LessonPlan( - id: json['id'] != null ? int.tryParse(json['id'].toString()) ?? 0 : 0, // Ens - name: json['title'] ?? '', - intro: json['description'] ?? '', - timemodified: json['updateTime'] != null - ? DateTime.parse(json['updateTime']).millisecondsSinceEpoch // Convert to int - : 0, - ); - } -} diff --git a/team_a/teamA/lib/beans/level.dart b/team_a/teamA/lib/beans/level.dart deleted file mode 100644 index a72b94b0..00000000 --- a/team_a/teamA/lib/beans/level.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class Level implements LearningLensInterface { - final int id; - final String description; - final int score; - - Level({required this.id, required this.description, required this.score}); - - // Empty constructor - Level.empty() - : id = 0, - description = '', - score = 0; - - @override - Level fromMoodleJson(Map json) { - return Level( - id: json['id'] ?? 0, - description: json['definition'] ?? '', - score: json['score'] ?? 0, - ); - } - - @override - Level fromGoogleJson(Map json) { - // TODO: Dinesh, try to map the Google JSON to the Level object - throw UnimplementedError(); - } - - Map toJson() { - return { - 'id': id, - 'description': description, - 'score': score, - }; - } -} diff --git a/team_a/teamA/lib/beans/moodle_rubric.dart b/team_a/teamA/lib/beans/moodle_rubric.dart deleted file mode 100644 index 4604f681..00000000 --- a/team_a/teamA/lib/beans/moodle_rubric.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; -import 'package:learninglens_app/beans/moodle_rubric_criteria.dart'; - -class MoodleRubric implements LearningLensInterface { - final String title; - final List criteria; - - MoodleRubric({required this.title, required this.criteria}); - - // Empty constructor - MoodleRubric.empty() - : title = 'Rubric', - criteria = []; - - @override - MoodleRubric fromMoodleJson(Map json) { - var criteriaList = (json['rubric_criteria'] as List) - .map((c) => MoodleRubricCriteria.fromMoodleJson(c)) - .toList(); - - return MoodleRubric( - title: json['criteria_title'] ?? 'Rubric', - criteria: criteriaList, - ); - } - - @override - MoodleRubric fromGoogleJson(Map json) { - // TODO: Dinesh, try to map the Google JSON to the MoodleRubric object and maybe change this class to be more generic - throw UnimplementedError(); - } - - Map toJson() { - return { - 'title': title, - 'criteria': criteria.map((c) => c.toJson()).toList(), - }; - } -} diff --git a/team_a/teamA/lib/beans/moodle_rubric_criteria.dart b/team_a/teamA/lib/beans/moodle_rubric_criteria.dart deleted file mode 100644 index d9a586c1..00000000 --- a/team_a/teamA/lib/beans/moodle_rubric_criteria.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:learninglens_app/beans/level.dart'; - -class MoodleRubricCriteria { - final int id; - final String description; - final List levels; - - MoodleRubricCriteria({required this.id, required this.description, required this.levels}); - - factory MoodleRubricCriteria.fromMoodleJson(Map json) - { - var levelsList = (json['levels'] as List) - .map((l) => Level.empty().fromMoodleJson(l)) - .toList(); - - return MoodleRubricCriteria( - id: json['id'] ?? 0, - description: json['description'] ?? '', - levels: levelsList, - ); - } - - Map toJson() - { - return { - 'id': id, - 'description': description, - 'levels': levels.map((l) => l.toJson()).toList(), - }; - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/override.dart b/team_a/teamA/lib/beans/override.dart deleted file mode 100644 index d41440b6..00000000 --- a/team_a/teamA/lib/beans/override.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class Override implements LearningLensInterface { - int id; - String type; - int assignmentId; - String assignmentName; - int courseId; - String courseName; - int userid; - String fullname; - DateTime? endTime; - DateTime? timelimit; - DateTime? cutoffTime; - int? attempts; - - Override( - this.id, - this.type, - this.assignmentId, - this.assignmentName, - this.courseId, - this.courseName, - this.userid, - this.fullname, - this.endTime, - this.timelimit, - this.cutoffTime, - this.attempts, - ); - - Override.empty() - : id = 0, - type = 'quiz', - assignmentId = 0, - assignmentName = '', - courseId = 0, - courseName = '', - userid = 0, - fullname = '', - endTime = null, - timelimit = null, - cutoffTime = null, - attempts = 0; - - @override - Override fromMoodleJson(Map json) { - return Override( - json['override_id'], - json['assignment_type'], - json['assignment_id'], - json['assignment_name'], - json['course_id'], - json['course_name'], - json['userid'], - json['fullname'], - json['end_time'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['end_time'] * 1000) - : null, - json['timelimit'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['timelimit'] * 1000) - : null, - json['cutoff_time'] != null - ? DateTime.fromMillisecondsSinceEpoch(json['cutoff_time'] * 1000) - : null, - json['attempts'] - ); - } - - @override - String toString() { - return "Override(user: $fullname | assignment: $assignmentName | course: $courseName)"; - } - - @override - Override fromGoogleJson(Map json) { - // TODO: Map Google Classroom JSON to Participant. - throw UnimplementedError(); - } -} diff --git a/team_a/teamA/lib/beans/participant.dart b/team_a/teamA/lib/beans/participant.dart deleted file mode 100644 index 2783b50b..00000000 --- a/team_a/teamA/lib/beans/participant.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class Participant implements LearningLensInterface { - final int id; - final String fullname; - final String firstname; - final String lastname; - final List roles; - double? avgGrade; - - Participant({ - required this.id, - required this.fullname, - required this.firstname, - required this.lastname, - required this.roles, - this.avgGrade, - }); - - Participant.empty() - : id = 0, - fullname = '', - firstname = '', - lastname = '', - roles = [], - avgGrade = null; - - @override - Participant fromMoodleJson(Map json) { - // Parse roles from the JSON. - List rolesList = []; - if (json['roles'] != null) { - rolesList = (json['roles'] as List) - .map((role) => role['shortname'] as String) - .toList(); - } - return Participant( - id: json['id'] as int, - fullname: json['fullname'] as String, - firstname: json['firstname'] as String, - lastname: json['lastname'] as String, - roles: rolesList, - // Parse avgGrade if available; otherwise, leave as null. - avgGrade: json['avggrade'] != null ? double.tryParse(json['avggrade'].toString()) : null, - ); - } - - @override - String toString() { - return "$fullname"; - } - - @override - Participant fromGoogleJson(Map json) { - // TODO: Map Google Classroom JSON to Participant. - throw UnimplementedError(); - } -} diff --git a/team_a/teamA/lib/beans/question.dart b/team_a/teamA/lib/beans/question.dart deleted file mode 100644 index 8175eee7..00000000 --- a/team_a/teamA/lib/beans/question.dart +++ /dev/null @@ -1,141 +0,0 @@ -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/answer.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; - -// Abstract class that represents a single question. -class Question { - - Question copyWith({String? name, List? answerList, String? type, String? questionText, bool? isFavorite}) => - Question(name: this.name, answerList: this.answerList,type: this.type, questionText: this.questionText, isFavorite: isFavorite ?? this.isFavorite); - - String name; // question name - required. - String type; // question type (multichoice, truefalse, shortanswer, essay) - required. - String questionText; // question text - required. - String? generalFeedback; - String? defaultGrade; - String? responseFormat; - String? responseRequired; - String? attachmentsRequired; - String? responseTemplate; - String? graderInfo; - final bool isFavorite; - // String description; - List answerList = - []; // list of answers. Not needed for essay. - - // Simple constructor. - Question({ - required this.name, - required this.type, - required this.questionText, - this.generalFeedback, - this.defaultGrade, - this.responseFormat, - this.responseRequired, - this.attachmentsRequired, - this.responseTemplate, - this.graderInfo, - this.isFavorite = false, - List? answerList, - }) : answerList = answerList ?? []; - - // XML factory constructor - factory Question.fromXml(XmlElement questionElement) { - Question question = Question( - name: questionElement - .getElement(XmlConsts.name) - ?.getElement(XmlConsts.text) - ?.innerText ?? - 'UNKNOWN', - type: questionElement.getAttribute(XmlConsts.type) ?? XmlConsts.essay, - questionText: questionElement - .getElement(XmlConsts.questiontext) - ?.getElement(XmlConsts.text) - ?.innerText ?? - 'UNKNOWN', - generalFeedback: questionElement - .getElement(XmlConsts.generalfeedback) - ?.getElement(XmlConsts.text) - ?.innerText, - defaultGrade: questionElement.getElement(XmlConsts.defaultgrade)?.innerText, - responseFormat: questionElement.getElement(XmlConsts.responseformat)?.innerText, - responseRequired: questionElement.getElement(XmlConsts.responserequired)?.innerText, - attachmentsRequired: questionElement.getElement(XmlConsts.attachmentsrequired)?.innerText, - responseTemplate: questionElement.getElement(XmlConsts.responsetemplate)?.innerText, - graderInfo: questionElement.getElement(XmlConsts.graderinfo)?.getElement(XmlConsts.text)?.innerText, - ); - - for (XmlElement answerElement - in questionElement.findElements(XmlConsts.answer).toList()) { - question.answerList.add(Answer.fromXml(answerElement)); - } - return question; - } - - set setName(String newname) { - name = newname; - } - -void buildXml(XmlBuilder builder) { - builder.element(XmlConsts.question, attributes: {XmlConsts.type: type}, nest: () { - builder.element(XmlConsts.name, nest: () { - builder.element(XmlConsts.text, nest: name); - }); - - builder.element(XmlConsts.questiontext, nest: () { - builder.element(XmlConsts.text, nest: questionText); - }); - - if (generalFeedback != null) { - builder.element(XmlConsts.generalfeedback, nest: () { - builder.element(XmlConsts.text, nest: generalFeedback); - }); - } - - if (defaultGrade != null) { - builder.element(XmlConsts.defaultgrade, nest: defaultGrade); - } - - if (responseFormat != null) { - builder.element(XmlConsts.responseformat, nest: responseFormat); - } - - if (responseRequired != null) { - builder.element(XmlConsts.responserequired, nest: responseRequired); - } - - if (attachmentsRequired != null) { - builder.element(XmlConsts.attachmentsrequired, nest: attachmentsRequired); - } - - if (responseTemplate != null) { - builder.element(XmlConsts.responsetemplate, nest: responseTemplate); - } - - if (graderInfo != null) { - builder.element(XmlConsts.graderinfo, nest: () { - builder.element(XmlConsts.text, nest: graderInfo); - }); - } - - // Answers - for (var answer in answerList) { - answer.buildXml(builder); - } - }); - } - - @override - String toString() { - final sb = StringBuffer(); - sb.write('$name\n$questionText'); - int charcode = 'A'.codeUnitAt(0); - for (Answer answer in answerList) { - String letter = String.fromCharCode(charcode); - String answerStr = answer.toString(); - sb.write('\n $letter. $answerStr'); - charcode++; - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/question_stat_type.dart b/team_a/teamA/lib/beans/question_stat_type.dart deleted file mode 100644 index 2c61e257..00000000 --- a/team_a/teamA/lib/beans/question_stat_type.dart +++ /dev/null @@ -1,35 +0,0 @@ -class QuestionStatsType { - final int id; - final String name; - final String questionText; - final String questionType; - final int numCorrect; - final int numIncorrect; - final int numPartial; - final int totalAttempts; - - QuestionStatsType({ - required this.id, - required this.name, - required this.questionText, - required this.questionType, - required this.numCorrect, - required this.numIncorrect, - required this.numPartial, - required this.totalAttempts, - }); - - // Optional: a factory constructor to build from JSON - factory QuestionStatsType.fromJson(Map json) { - return QuestionStatsType( - id: json['id'] ?? 0, - name: json['name'] ?? '', - questionText: json['questiontext'] ?? '', - questionType: json['qtype'] ?? '', - numCorrect: json['numcorrect'] ?? 0, - numIncorrect: json['numincorrect'] ?? 0, - numPartial: json['numpartial'] ?? 0, - totalAttempts: json['totalattempts'] ?? 0, - ); - } -} diff --git a/team_a/teamA/lib/beans/quiz.dart b/team_a/teamA/lib/beans/quiz.dart deleted file mode 100644 index e05ef45e..00000000 --- a/team_a/teamA/lib/beans/quiz.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/question.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; - -// A Moodle quiz containing a list of questions. -class Quiz { - String? name; // quiz name - optional. - String? description; // quiz description - optional. - List questionList = []; // list of questions on the quiz. - String? promptUsed; - int? id; // quiz id, null if the quiz doesn't exist in Moodle yet - int? coursedId; - - DateTime? timeOpen; - DateTime? timeClose; - // Constructor with all optional params. - Quiz( - {this.name, - this.coursedId, - this.description, - this.id, - this.timeOpen, - this.timeClose, - List? questionList}) - : questionList = questionList ?? []; - - // XML factory constructor using XML string - factory Quiz.fromXmlString(String xmlStr) { - Quiz quiz = Quiz(); - final document = XmlDocument.parse(xmlStr); - final quizElement = document.getElement(XmlConsts.quiz); - - quiz.name = quizElement - ?.getElement(XmlConsts.name) - ?.getElement(XmlConsts.text) - ?.innerText; - - quiz.description = - quizElement!.getElement(XmlConsts.description)?.innerText; - - for (XmlElement questionElement - in quizElement.findElements(XmlConsts.question)) { - if (questionElement.getAttribute(XmlConsts.type) == 'category') { - continue; // Skip category type questions - } - quiz.questionList.add(Question.fromXml(questionElement)); - } - quiz.promptUsed = quizElement.getElement(XmlConsts.promptUsed)?.innerText; - return quiz; - } - - static Quiz fromGoogleJson(Map json) { - Quiz tmpQuiz = Quiz(); - tmpQuiz.name = json['title']; - tmpQuiz.description = json['description']; - tmpQuiz.questionList = []; - tmpQuiz.promptUsed = ''; - tmpQuiz.id = int.parse(json['id']); - tmpQuiz.coursedId = int.parse(json['courseId']); - - return tmpQuiz; - } - - String toXmlString() { - final builder = XmlBuilder(); - builder.element(XmlConsts.quiz, nest: () { - // Name element - if (name != null) { - builder.element(XmlConsts.name, nest: () { - builder.element(XmlConsts.text, nest: name); - }); - } - - // Description element - if (description != null) { - builder.element(XmlConsts.description, nest: description); - } - - // Insert a "category" type question using the description as the category name - if (description != null) { - builder.element(XmlConsts.question, - attributes: {XmlConsts.type: 'category'}, nest: () { - builder.element(XmlConsts.category, nest: () { - builder.element(XmlConsts.text, - nest: '\$course\$/Top/$description'); - }); - }); - } - - // PromptUsed element - if (promptUsed != null) { - builder.element(XmlConsts.promptUsed, nest: promptUsed); - } - - // Questions - for (var question in questionList) { - question.buildXml(builder); - } - }); - - return builder.buildDocument().toXmlString(pretty: true); - } - - bool isNew() { - return id == null; - } - - @override - String toString() { - final sb = StringBuffer(); - sb.write('Quiz Name: $name\n'); - sb.write('Quiz Description: $description\n\n'); - for (var i = 1; i <= questionList.length; i++) { - sb.write('Q$i: '); - sb.write(questionList[i - 1].toString()); - sb.write('\n\n'); - } - return sb.toString(); - } -} diff --git a/team_a/teamA/lib/beans/quiz_override b/team_a/teamA/lib/beans/quiz_override deleted file mode 100644 index 4a661e1b..00000000 --- a/team_a/teamA/lib/beans/quiz_override +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class QuizOverride implements LearningLensInterface { - final int overrideId; - - QuizOverride({required this.overrideId}); - - QuizOverride.empty() : overrideId = 0; - - @override - QuizOverride fromMoodleJson(Map json) { - return QuizOverride( - overrideId: json['overrideid'] as int, - ); - } - - @override - QuizOverride fromGoogleJson(Map json) { - throw UnimplementedError(); - } - - @override - String toString() { - return "QuizOverride(overrideId: $overrideId)"; - } -} diff --git a/team_a/teamA/lib/beans/quiz_type.dart b/team_a/teamA/lib/beans/quiz_type.dart deleted file mode 100644 index c9a88e03..00000000 --- a/team_a/teamA/lib/beans/quiz_type.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class QuestionType implements LearningLensInterface { - final int id; - final String name; - final String questionText; - final String questionType; - - QuestionType({ - required this.id, - required this.name, - required this.questionText, - required this.questionType, - }); - - QuestionType.empty() - : id = 0, - name = '', - questionText = '', - questionType = ''; - - @override - QuestionType fromMoodleJson(Map json) { - return QuestionType( - id: json['id'] as int, - name: json['name'] as String? ?? 'Unnamed Question', - questionText: json['questiontext'] as String? ?? 'No Question Text', - questionType: json['qtype'] as String? ?? 'unknown', - ); - } - - @override - QuestionType fromGoogleJson(Map json) { - // TODO: Map Google Classroom JSON to Questions object. - throw UnimplementedError(); - } - - @override - String toString() { - return "Questions(id: $id, name: $name, type: $questionType, text: $questionText)"; - } -} diff --git a/team_a/teamA/lib/beans/rubric.dart b/team_a/teamA/lib/beans/rubric.dart deleted file mode 100644 index 07934807..00000000 --- a/team_a/teamA/lib/beans/rubric.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/rubric_criteria.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; - -// A generated rubric containing criteria for an essay prompt. -// Commented out as the only other instance of Rubric being used is the other one. -class Rubric { - String title; - String subject; - String gradeLevel; - int maxPoints; - List criteriaList; - - Rubric({ - required this.title, - required this.subject, - required this.gradeLevel, - required this.maxPoints, - required this.criteriaList, - }); - - // Factory constructor to create a Rubric from XML - factory Rubric.fromXmlString(String xmlStr) - { - final document = XmlDocument.parse(xmlStr); - final rubricElement = document.getElement(XmlConsts.rubric); - - return Rubric( - title: rubricElement?.getElement(XmlConsts.title)?.innerText ?? 'Untitled', - subject: rubricElement?.getElement(XmlConsts.subject)?.innerText ?? 'Unknown', - gradeLevel: rubricElement?.getElement(XmlConsts.gradeLevel)?.innerText ?? 'Unknown', - maxPoints: int.parse(rubricElement?.getElement(XmlConsts.maxPoints)?.innerText ?? '0'), - criteriaList: rubricElement - ?.findElements(XmlConsts.criteria) - .map((e) => RubricCriteria.fromXml(e)) - .toList() ?? [], - ); - } - - // Convert the Rubric object to an XML string - String toXmlString() { - final builder = XmlBuilder(); - builder.element(XmlConsts.rubric, nest: () { - builder.element(XmlConsts.title, nest: title); - builder.element(XmlConsts.subject, nest: subject); - builder.element(XmlConsts.gradeLevel, nest: gradeLevel); - builder.element(XmlConsts.maxPoints, nest: maxPoints.toString()); - - for (var criteria in criteriaList) { - builder.element(XmlConsts.criteria, nest: criteria.toXml); - } - }); - return builder.buildDocument().toXmlString(pretty: true); - } - - @override - String toString() { - return toXmlString(); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/rubric_criteria.dart b/team_a/teamA/lib/beans/rubric_criteria.dart deleted file mode 100644 index 60dc2bc8..00000000 --- a/team_a/teamA/lib/beans/rubric_criteria.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:xml/xml.dart'; -import 'package:learninglens_app/beans/xml_consts.dart'; - -// Specific Rubric Criteria -class RubricCriteria { - String description; - int points; - String feedback; - - RubricCriteria({ - required this.description, - required this.points, - this.feedback = '', - }); - - // Factory constructor to create criteria from XML - factory RubricCriteria.fromXml(XmlElement criteriaElement) - { - return RubricCriteria( - description: criteriaElement.getElement(XmlConsts.description)?.innerText ?? 'Unknown', - points: int.parse(criteriaElement.getElement(XmlConsts.points)?.innerText ?? '0'), - feedback: criteriaElement.getElement(XmlConsts.feedback)?.innerText ?? '', - ); - } - - // Convert the criteria to XML format - void toXml(XmlBuilder builder) - { - builder.element(XmlConsts.description, nest: description); - builder.element(XmlConsts.points, nest: points.toString()); - builder.element(XmlConsts.feedback, nest: feedback); - } - - @override - String toString() { - final builder = XmlBuilder(); - toXml(builder); - return builder.buildFragment().toXmlString(); - } -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/submission.dart b/team_a/teamA/lib/beans/submission.dart deleted file mode 100644 index 7918ca20..00000000 --- a/team_a/teamA/lib/beans/submission.dart +++ /dev/null @@ -1,122 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class Submission implements LearningLensInterface { - final int id; - final int userid; - final String status; - final DateTime submissionTime; - final DateTime? modificationTime; - final int attemptNumber; - final int groupId; - final String gradingStatus; - final String onlineText; - final String comments; - final int assignmentId; // Added field - - Submission({ - required this.id, - required this.userid, - required this.status, - required this.submissionTime, - this.modificationTime, - required this.attemptNumber, - required this.groupId, - required this.gradingStatus, - required this.onlineText, - required this.comments, - required this.assignmentId, - }); - - // empty constructor - Submission.empty() - : id = 0, - userid = 0, - status = '', - submissionTime = DateTime.fromMillisecondsSinceEpoch(0), - modificationTime = DateTime.fromMillisecondsSinceEpoch(0), - attemptNumber = 0, - groupId = 0, - gradingStatus = '', - onlineText = '', - comments = '', - assignmentId = 0; - - @override - Submission fromMoodleJson(Map json) { - String onlineText = ''; - String comments = ''; - - // Debug: Print entire submission JSON - // ignore: avoid_print - print('Processing submission: ${json.toString()}'); - int assignmentId = json['assignmentid'] ?? 0; - Map submission = json['submission'] ?? {}; - - if (submission['plugins'] != null && submission['plugins'] is List) { - for (var plugin in submission['plugins']) { - // Extract 'onlineText' - if (plugin['type'] != null && - plugin['type'].toString().toLowerCase() == 'onlinetext') { - var editorFields = plugin['editorfields']; - if (editorFields != null && - editorFields is List && - editorFields.isNotEmpty) { - for (var field in editorFields) { - if (field['name'] != null && - field['name'].toString().toLowerCase() == 'onlinetext') { - onlineText = field['text'] ?? ''; - print('Extracted onlineText: $onlineText'); - break; // Exit loop once the correct field is found - } - } - } - } - - // Extract 'comments' - if (plugin['type'] != null && - plugin['type'].toString().toLowerCase() == 'comments') { - var editorFields = plugin['editorfields']; - if (editorFields != null && - editorFields is List && - editorFields.isNotEmpty) { - for (var field in editorFields) { - if (field['name'] != null && - field['name'].toString().toLowerCase() == 'comments') { - comments = field['text'] ?? ''; - print('Extracted comments: $comments'); - break; // Exit loop once the correct field is found - } - } - } - } - } - } else { - print('No plugins found in submission.'); - } - - return Submission( - id: submission['id'] ?? 0, - userid: submission['userid'] ?? 0, - status: submission['status'] ?? '', - submissionTime: submission['timecreated'] != null - ? DateTime.fromMillisecondsSinceEpoch( - submission['timecreated'] * 1000) - : DateTime.fromMillisecondsSinceEpoch(0), - modificationTime: submission['timemodified'] != null - ? DateTime.fromMillisecondsSinceEpoch( - submission['timemodified'] * 1000) - : null, - attemptNumber: submission['attemptnumber'] ?? 0, - groupId: submission['groupid'] ?? 0, - gradingStatus: submission['gradingstatus'] ?? '', - onlineText: onlineText, - comments: comments, - assignmentId: assignmentId); - } - - @override - Submission fromGoogleJson(Map json) { - // TODO: Dinesh, try to map the Google JSON to the Submission object - throw UnimplementedError(); - } -} diff --git a/team_a/teamA/lib/beans/submission_status.dart b/team_a/teamA/lib/beans/submission_status.dart deleted file mode 100644 index 5b02d98c..00000000 --- a/team_a/teamA/lib/beans/submission_status.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:learninglens_app/beans/learning_lens_interface.dart'; - -class SubmissionStatus implements LearningLensInterface { - final int assignmentId; - final int userId; - final String status; - final DateTime? timeSubmitted; - final DateTime? timeGraded; - final double? grade; - final bool needsGrading; - - SubmissionStatus({ - required this.assignmentId, - required this.userId, - required this.status, - this.timeSubmitted, - this.timeGraded, - this.grade, - required this.needsGrading, - }); - - // Empty constructor - SubmissionStatus.empty() - : assignmentId = 0, - userId = 0, - status = 'unknown', - timeSubmitted = null, - timeGraded = null, - grade = null, - needsGrading = false; - - // Factory method to create a SubmissionStatus object from a JSON response - @override - SubmissionStatus fromMoodleJson(Map json) { - return SubmissionStatus( - assignmentId: json['assignid'] ?? 0, - userId: json['userid'] ?? 0, - status: json['lastattempt']['submission']['status'] ?? 'unknown', - timeSubmitted: json['lastattempt']['submission']['timemodified'] != null - ? DateTime.fromMillisecondsSinceEpoch( - json['lastattempt']['submission']['timemodified'] * 1000) - : null, - timeGraded: json['lastattempt']['grades'] != null && - json['lastattempt']['grades']['grade'] != null - ? DateTime.fromMillisecondsSinceEpoch( - json['lastattempt']['grades']['timemodified'] * 1000) - : null, - grade: json['lastattempt']['grades'] != null && - json['lastattempt']['grades']['grade'] != null - ? double.tryParse(json['lastattempt']['grades']['grade'].toString()) - : null, - needsGrading: json['lastattempt']['gradingstatus'] == 'notgraded', - ); - } - - @override - SubmissionStatus fromGoogleJson(Map json) { - // TODO: Dinesh, try to map the Google JSON to the SubmissionStatus object - throw UnimplementedError(); - } - - // Convert the SubmissionStatus object back to JSON if necessary - Map toJson() { - return { - 'assignid': assignmentId, - 'userid': userId, - 'status': status, - 'timemodified': timeSubmitted?.millisecondsSinceEpoch, - 'timegraded': timeGraded?.millisecondsSinceEpoch, - 'grade': grade, - 'needsgrading': needsGrading, - }; - } -} diff --git a/team_a/teamA/lib/beans/submission_with_grade.dart b/team_a/teamA/lib/beans/submission_with_grade.dart deleted file mode 100644 index 4da4a0f9..00000000 --- a/team_a/teamA/lib/beans/submission_with_grade.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:learninglens_app/beans/submission.dart'; -import 'package:learninglens_app/beans/grade.dart'; - -class SubmissionWithGrade { - final Submission submission; - final Grade? grade; - - SubmissionWithGrade({ - required this.submission, - this.grade, - }); -} \ No newline at end of file diff --git a/team_a/teamA/lib/beans/user.dart b/team_a/teamA/lib/beans/user.dart deleted file mode 100644 index 01c5ba44..00000000 --- a/team_a/teamA/lib/beans/user.dart +++ /dev/null @@ -1,29 +0,0 @@ -class User { - int id; - String firstname; - String lastname; - String email; - - User({ - required this.id, - required this.firstname, - required this.lastname, - required this.email, - }); - - // empty constructor - User.empty() - : id = 0, - firstname = '', - lastname = '', - email = ''; - - factory User.fromJson(Map json) { - return User( - id: json['id'], - firstname: json['firstname'], - lastname: json['lastname'], - email: json['email'] - ); - } -} diff --git a/team_a/teamA/lib/beans/xml_consts.dart b/team_a/teamA/lib/beans/xml_consts.dart deleted file mode 100644 index 7fd68e3b..00000000 --- a/team_a/teamA/lib/beans/xml_consts.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Tags and attributes used in Moodle XML. Useful for preventing typos. -class XmlConsts { - // Quiz tags - static const quiz = 'quiz'; - static const question = 'question'; - static const name = 'name'; - static const description = 'description'; - static const type = 'type'; - static const text = 'text'; - static const questiontext = 'questiontext'; - static const format = 'format'; - static const answer = 'answer'; - static const fraction = 'fraction'; - static const feedback = 'feedback'; - static const generalfeedback = 'generalfeedback'; - static const attachmentsrequired = 'attachmentsrequired'; - static const responseformat = 'responseformat'; - static const responserequired = 'responserequired'; - static const defaultgrade = 'defaultgrade'; - static const responsetemplate = 'responsetemplate'; - static const graderinfo = 'graderinfo'; - static const promptUsed = 'promptused'; - static const category = 'category'; - - // Essay Rubric Tags - static const rubric = 'rubric'; - static const title = 'title'; - static const subject = 'subject'; - static const gradeLevel = 'gradeLevel'; - static const maxPoints = 'maxPoints'; - static const criteria = 'criteria'; - static const points = 'points'; - - // not tags but useful constants - static const multichoice = 'multichoice'; - static const truefalse = 'truefalse'; - static const shortanswer = 'shortanswer'; - static const essay = 'essay'; - static const html = 'html'; -} \ No newline at end of file diff --git a/team_a/teamA/lib/content_carousel.dart b/team_a/teamA/lib/content_carousel.dart deleted file mode 100644 index b580b72e..00000000 --- a/team_a/teamA/lib/content_carousel.dart +++ /dev/null @@ -1,334 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; - -import 'package:learninglens_app/Views/essay_generation.dart'; -import 'package:learninglens_app/Views/g_assignment_create.dart'; -import 'package:learninglens_app/Views/g_quiz_question_page.dart'; - -import 'package:learninglens_app/Views/m_assessment_view.dart'; -import 'package:learninglens_app/Views/quiz_generator.dart'; -import 'package:learninglens_app/Views/essays_view.dart'; -import 'package:learninglens_app/beans/quiz.dart'; -import 'package:learninglens_app/beans/assignment.dart'; -import 'package:learninglens_app/beans/course.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -//Provides a carousel of either assessments, essays, or submission -class ContentCarousel extends StatefulWidget { - final String type; - final List? children; - final int? courseId; - - ContentCarousel(this.type, this.children, {this.courseId}); - - @override - State createState() { - return _ContentState(type, children, courseId ?? 0); - } -} - -//State of the carousel (allows for filtering in the future) -class _ContentState extends State { - final String type; - //original list of content - final List _children; - //filtered list to be shown - var children = []; - final int courseId; - _ContentState._(this.type, this._children, this.courseId) { - children = _children; - } - - factory _ContentState(String type, List? input, int? courseId) { - { - //generate the full list of cards - if (type == "assessment") { - return _ContentState._( - type, - CarouselCard.fromQuizzes(input) ?? - [ - Text( - 'There are no generated quizzes that match the requirements.', - style: TextStyle(fontSize: 32)) - ], - courseId ?? 0); - } else if (type == 'essay') { - return _ContentState._( - type, - CarouselCard.fromEssays(input) ?? - [ - Text( - 'This are no generated essays that match the requirements.', - style: TextStyle(fontSize: 32)) - ], - courseId ?? 0); - } - //todo: add submission type - else { - return _ContentState._( - type, [Text('Invalid type input.')], courseId ?? 0); - } - } - } - //todo filtering features - - bool isMoodle() { - print(LocalStorageService.getSelectedClassroom()); - return LocalStorageService.getSelectedClassroom() == LmsType.MOODLE; - } - - @override - Widget build(BuildContext context) { - //For empty contents, we don't build a carousel - if (_children.length == 1 && _children[0].runtimeType == Text) { - return Padding( - padding: EdgeInsets.all(20), - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: 400), - child: Center(child: _children[0]))); - } else { - // return Padding( - // padding: EdgeInsets.symmetric(vertical: 10), - // child: ConstrainedBox( - // constraints: BoxConstraints(maxHeight: 250), //testing width - // child: CarouselView( - // backgroundColor: Theme.of(context).primaryColor, - // itemExtent: 400, - // shrinkExtent: 250, - // onTap: (value) { - // if (type == 'assessment') { - - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => AssessmentsView( - // quizID: (children[value] as CarouselCard).id, - // courseID: - // (children[value] as CarouselCard).courseId)), - // ); - // } else if (type == 'essay') { - // print( - // (children[value] as CarouselCard).courseId?.toString()); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => EssaysView( - // essayID: (children[value] as CarouselCard).id, - // courseID: (children[value] as CarouselCard) - // .courseId))); - // } - // }, - // children: children, - // ))); - - return Padding( - padding: EdgeInsets.symmetric(vertical: 10), - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: 250), - child: CarouselView( - backgroundColor: Theme.of(context).primaryColor, - itemExtent: 400, - shrinkExtent: 250, - onTap: (value) { - if (type == 'assessment') { - bool isMoodleSelected = isMoodle(); - String courseIdStr = (children[value] as CarouselCard) - .courseId - ?.toString() ?? - ''; - String assessmentIdStr = - (children[value] as CarouselCard).id.toString(); - - print('Course ID I am sending: $courseIdStr'); - print('Assessment ID I am sending: $assessmentIdStr'); - - if (!isMoodleSelected) { - // Assuming "google" is !isMoodle() - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QuizQuestionPage( - coursedId: courseIdStr, - assessmentId: assessmentIdStr, - ), - ), - ); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => MAssessmentsView( - quizID: (children[value] as CarouselCard).id, - courseID: - (children[value] as CarouselCard).courseId ?? 0, - ), - ), - ); - } - } else if (type == 'essay') { - print( - (children[value] as CarouselCard).courseId?.toString()); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EssaysView( - essayID: (children[value] as CarouselCard).id, - courseID: (children[value] as CarouselCard) - .courseId))); - } - }, - children: children, - ))); - } - } -} - -//Cards for the Carousel -class CarouselCard extends StatelessWidget { - //assignment name - final String title; - //assignment information (may want to get a specific format, need to look into the various settings for each) - final String information; - //acceptable types: assessment, essay, submission - final String type; - final int id; - final int? courseId; - - CarouselCard(this.title, this.information, this.type, this.id, - {this.courseId}); - - static CarouselCard fromQuiz(Quiz input) { - return CarouselCard( - input.name ?? "Unnamed Quiz", - input.description?.replaceAll(RegExp(r"<[^>]*>"), "") ?? '', - 'assessment', - input.id ?? 0, - courseId: input.coursedId); - } - - static List? fromQuizzes(List? input) { - if (input == null) { - return null; - } - List output = []; - for (Object c in input) { - if (c is Quiz) { - output.insert(output.length, fromQuiz(c)); - } - } - return output; - } - - static CarouselCard fromEssay(Assignment input) { - return CarouselCard( - input.name, - input.description.replaceAll(RegExp(r"<[^>]*>"), ""), - 'essay', - input.id ?? 0, - courseId: input.courseId); - } - - static List? fromEssays(List? input) { - if (input == null) { - return null; - } - List output = []; - for (Object c in input) { - if (c is Assignment) { - output.insert(output.length, fromEssay(c)); - } - } - return output; - } - - @override - Widget build(BuildContext context) { - List? theCourses = LmsFactory.getLmsService().courses; - Course matchedCourse = - theCourses!.firstWhere((element) => element.id == courseId); - return Card( - color: Theme.of(context).colorScheme.secondaryContainer, - elevation: 2, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(25.0), // Rounded corners - ), - child: SizedBox( - height: 200, // Adjust this value based on the desired height - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: - Text(title, style: Theme.of(context).textTheme.titleLarge), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(information), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text('Course: ${matchedCourse.fullName}'), - ), - Spacer(), // Pushes the buttons to the bottom - ], - )), - ); - } -} - -//buttons navigating to the create pages -class CreateButton extends StatelessWidget { - //todo: maybe autofill filter information into the assignment creation settings? - final String filters = ''; - //acceptable types: assessment, essay - final String type; - final String text; - - CreateButton._(this.type, this.text); - - factory CreateButton(String type) { - if (type == "assessment") { - return CreateButton._(type, "Create New Assessment"); - } else if (type == "essay") { - return CreateButton._(type, "Create New Essay Assignment"); - } else { - return CreateButton._(type, ""); - } - } - - bool isMoodle() { - print(LocalStorageService.getSelectedClassroom()); - return LocalStorageService.getSelectedClassroom() == LmsType.MOODLE; - } - - @override - Widget build(BuildContext context) { - return OutlinedButton( - onPressed: () { - MaterialPageRoute? route; - if (type == 'assessment') { - route = MaterialPageRoute(builder: (context) => CreateAssessment()); - } else if (type == 'essay') { - bool isMoodleSelected = isMoodle(); - if (!isMoodleSelected) { - // Assuming "google" is !isMoodle() - - route = MaterialPageRoute( - builder: (context) => CreateAssignmentPage()); - } else { - route = MaterialPageRoute( - builder: (context) => EssayGeneration(title: 'New Essay')); - } - } - if (route != null) { - Navigator.push(context, route); - } - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [Icon(Icons.add), Text(text)], - )); - } -} diff --git a/team_a/teamA/lib/main.dart b/team_a/teamA/lib/main.dart deleted file mode 100644 index c7ba3ba2..00000000 --- a/team_a/teamA/lib/main.dart +++ /dev/null @@ -1,177 +0,0 @@ -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:learninglens_app/Views/assessments_view.dart'; -import 'package:learninglens_app/Views/user_settings.dart'; -import 'package:learninglens_app/notifiers/login_notifier.dart'; -import 'package:learninglens_app/notifiers/theme_notifier.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:provider/provider.dart'; -import 'Views/dashboard.dart'; -import 'Views/essay_generation.dart'; -import 'Views/quiz_generator.dart'; -import 'Views/edit_questions.dart'; - - -void main() async{ - await dotenv.load(); - // runApp(MyApp()); - await LocalStorageService.init(); // Initialize SharedPreferences - - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => ThemeNotifier()), // Theme provider - ChangeNotifierProvider(create: (_) => LoginNotifier()), // Login provider - ], - child: MyApp(), - ), - ); -} - -//click and drag for intuitiveness -class CustomScrollBehavior extends ScrollBehavior { - @override - Set get dragDevices => { - PointerDeviceKind.touch, - PointerDeviceKind.mouse, - }; -} - -//below is an app builder, leave it here for now -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - Provider.of(context); - - // used to determine which dashboard to show based on the local storage system - var selectedClassroom = LocalStorageService.getSelectedClassroom(); - var home = selectedClassroom == LmsType.MOODLE ? TeacherDashboard() : TeacherDashboard(); //GoogleTeacherDashboard(); - - return MaterialApp( - debugShowCheckedModeBanner: false, - title: "Learning Lens", - home: home, - theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Provider.of(context).primaryColor), - ), - scrollBehavior: CustomScrollBehavior(), - routes: { - // '/EssayEditPage': (context) => EssayEditPage(jsonData), - // '/Content': (context) => ViewCourseContents(), - '/EssayGenerationPage': (context) => EssayGeneration(title: 'Essay Generation'), - '/QuizGenerationPage': (context) => CreateAssessment(), - '/EditQuestions': (context) => EditQuestions(''), - // '/create': (context) => const CreatePage(), - '/dashboard': (context) => TeacherDashboard(), - '/user': (context) => UserSettings(), - //'/send_essay_to_moodle': (context) => EssayAssignmentSettings(''), - '/assessments': (context) => AssessmentsView(), - // '/viewExams': (context) => const ViewExamPage(), - // '/settings': (context) => Setting(themeModeNotifier: _themeModeNotifier) - }, - ); - } -} - -class DevLaunch extends StatefulWidget { - @override - State createState() { - return _DevLaunch(); - } -} - -class _DevLaunch extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('Dev Launch Page')), - body: Column(children: [ - ElevatedButton( - child: const Text('dashboard'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => TeacherDashboard()), - ); - }), - // ElevatedButton( - // child: const Text('Open Edit Essay'), - // onPressed: () { - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => EssayEditPage(jsonData)), - // ); - // }), - // ElevatedButton( - // child: const Text('Open Contents Carousel'), - // onPressed: () async { - // if (MoodleApiSingleton().isLoggedIn()){ - // MainController().selectCourse(0); - // } - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => ViewCourseContents()), - // ); - // }), - ElevatedButton( - child: const Text('Open Essay Generation'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - EssayGeneration(title: 'Essay Generation')), - ); - }), - ElevatedButton( - child: const Text('Teacher Dashboard'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => TeacherDashboard()), - ); - }), - // ElevatedButton( - // child: const Text('Send essay to Moodle'), - // onPressed: () { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => EssayAssignmentSettings(tempRubricXML)), - // ); - // }), - ElevatedButton( - child: const Text('Quiz Generator'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => CreateAssessment())); - }, - ), - ElevatedButton( - child: const Text('Edit Questions'), - onPressed: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) => EditQuestions(''))); - }, - ), - ElevatedButton( - child: const Text('View Quizzes'), - onPressed: (){ - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AssessmentsView()) - ); - } - ) - ])); - } - -} \ No newline at end of file diff --git a/team_a/teamA/lib/notifiers/login_notifier.dart b/team_a/teamA/lib/notifiers/login_notifier.dart deleted file mode 100644 index d10203ff..00000000 --- a/team_a/teamA/lib/notifiers/login_notifier.dart +++ /dev/null @@ -1,255 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:learninglens_app/Api/lms/factory/lms_factory.dart'; -import 'package:learninglens_app/Api/lms/lms_interface.dart'; -import 'package:learninglens_app/notifiers/login_state.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; - -enum LLMKey { openAI, perplexity, claude, grok } - -class LoginNotifier with ChangeNotifier { - // --------------------------------------- - // New: use these model objects - // --------------------------------------- - final LoginState _moodleState = LoginState(); - final LoginState _googleState = LoginState(); - - // If you want external access to them, you can provide getters: - LoginState get moodleState => _moodleState; - LoginState get googleState => _googleState; - - // You can still store other fields here as needed - bool _hasLLMKey = false; - String? _username; - String? _password; - String? _moodleUrl; - String? _clientID; // for Google - String? _otherError; // If you want any global error, or remove if not needed - - final LmsInterface _api = LmsFactory.getLmsService(); // Moodle API instance - - bool get hasLLMKey => _hasLLMKey; - String? get username => _username; - String? get password => _password; - String? get moodleUrl => _moodleUrl; - - // Constructor - LoginNotifier() { - _loadLoginState(); // Load any saved login state on creation - } - - // --------------------------------------- - // Load from local storage - // --------------------------------------- - Future _loadLoginState() async { - // Moodle - _moodleState.isLoggedIn = LocalStorageService.isLoggedIntoMoodle(); - _username = LocalStorageService.getUsername(); - _password = LocalStorageService.getPassword(); - _moodleUrl = LocalStorageService.getMoodleUrl(); - - // Google - _googleState.isLoggedIn = LocalStorageService.isLoggedIntoGoogle(); - _clientID = LocalStorageService.getGoogleClientId(); - - // LLM Key - _hasLLMKey = await _checkHasLLMKey(); - - // Attempt auto-login if we had credentials - _autoLogin(); - notifyListeners(); - } - - // --------------------------------------- - // Check existence of any LLM keys - // --------------------------------------- - Future _checkHasLLMKey() async { - final openAIKey = LocalStorageService.getOpenAIKey(); - final perplexityKey = LocalStorageService.getPerplexityKey(); - final grokKey = LocalStorageService.getGrokKey(); - - return (openAIKey != null && openAIKey.isNotEmpty) || - (perplexityKey != null && perplexityKey.isNotEmpty) || - (grokKey != null && grokKey.isNotEmpty); - } - - // --------------------------------------- - // Auto-login if we have saved credentials - // --------------------------------------- - Future _autoLogin() async { - if ((_username != null && _username!.isNotEmpty) && - (_password != null && _password!.isNotEmpty) && - (_moodleUrl != null && _moodleUrl!.isNotEmpty)) { - try { - await signInWithMoodle(_username!, _password!, _moodleUrl!); - } catch (e) { - print('Auto-login Error: $e'); - } - } else { - print('Auto-login skipped: Missing or empty credentials.'); - } - } - - // --------------------------------------- - // Moodle: Sign-in - // --------------------------------------- - Future signInWithMoodle(String username, String password, String moodleUrl) async { - try { - await _api.login(username, password, moodleUrl); - - if (_api.isLoggedIn()) { - _moodleState.isLoggedIn = true; - _moodleState.errorMessage = null; // Clear any old error - _username = username; - _password = password; - _moodleUrl = moodleUrl; - - // Save to local storage - LocalStorageService.saveMoodleLoginState(_moodleState.isLoggedIn); - LocalStorageService.saveCredentials(username, password); - LocalStorageService.saveMoodleUrl(moodleUrl); - - } else { - // Logged in is false; set a custom error - _moodleState.isLoggedIn = false; - _moodleState.errorMessage = "Invalid username or password."; - } - - notifyListeners(); - } catch (e) { - // Catch the exception, set isLoggedIn = false, set error - _moodleState.isLoggedIn = false; - _moodleState.errorMessage = "Moodle login failed: ${e.toString()}"; - notifyListeners(); - } - } - - // --------------------------------------- - // Moodle: Sign-out - // --------------------------------------- - Future signOutFromMoodle() async { - _moodleState.isLoggedIn = false; - _moodleState.errorMessage = null; - _username = null; - _password = null; - _moodleUrl = null; - - // Clear from local storage - LocalStorageService.clearMoodleLoginState(); - LocalStorageService.clearCredentials(); - LocalStorageService.clearMoodleUrl(); - - // Reset LMS - LmsFactory.getLmsService().resetLMSUserInfo(); - - notifyListeners(); - } - - // --------------------------------------- - // Google: Sign-in - // --------------------------------------- - Future signInWithGoogle() async { - if (_clientID == null) { - throw Exception("GOOGLE_CLIENT_ID not found in .env file."); - } - - try { - await LmsFactory.getLmsServiceGoogle().loginOath(_clientID!); - - // if (_api.isLoggedIn()) { - if (LmsFactory.getLmsServiceGoogle().isLoggedIn()) { - _googleState.isLoggedIn = true; - _googleState.errorMessage = null; - - // Save to local storage - LocalStorageService.saveGoogleLoginState(_googleState.isLoggedIn); - LocalStorageService.saveGoogleAccessToken( - LmsFactory.getLmsServiceGoogle().getGoogleAccessToken() - ); - - notifyListeners(); - } else { - _googleState.isLoggedIn = false; - _googleState.errorMessage = 'Google login failed.'; - notifyListeners(); - throw Exception('Google login failed.'); - } - } catch (e) { - _googleState.isLoggedIn = false; - _googleState.errorMessage = "Google login failed: ${e.toString()}"; - notifyListeners(); - rethrow; // Or remove if you don't want to rethrow - } - } - - // --------------------------------------- - // Google: Sign-out - // --------------------------------------- - Future signOutFromGoogle() async { - try { - LmsFactory.getLmsServiceGoogle().logout(); - _googleState.isLoggedIn = false; - _googleState.errorMessage = null; - - LocalStorageService.clearGoogleLoginState(); - LocalStorageService.clearGoogleAccessToken(); - - notifyListeners(); - } catch (error) { - print("Google Sign-Out Error: $error"); - // Optionally set _googleState.errorMessage - throw Exception("Google Sign-Out failed: $error"); - } - } - - // --------------------------------------- - // Example Classroom API request for Google - // --------------------------------------- - Future makeClassroomApiRequest(String apiEndpoint, dynamic http) async { - final accessToken = LocalStorageService.getGoogleAccessToken(); - - if (accessToken != null) { - try { - final response = await http.get( - Uri.parse(apiEndpoint), - headers: {'Authorization': 'Bearer $accessToken'}, - ); - - if (response.statusCode == 200) { - print('Classroom API Response: ${response.body}'); - } else { - print('Classroom API Error: ${response.statusCode} - ${response.body}'); - throw Exception("Classroom API request failed: ${response.statusCode}"); - } - } catch (e) { - print('Error making Classroom API request: $e'); - throw Exception("Failed to make Classroom API request: $e"); - } - } else { - print('No Google access token available. User needs to sign in.'); - throw Exception("No access token available. Please sign in again."); - } - } - - // --------------------------------------- - // Save the LLM key to local storage - // --------------------------------------- - Future saveLLMKey(LLMKey key, String value) async { - switch (key) { - case LLMKey.openAI: - LocalStorageService.saveOpenAIKey(value); - break; - case LLMKey.perplexity: - LocalStorageService.savePerplexityKey(value); - break; - case LLMKey.grok: - LocalStorageService.saveGrokKey(value); - break; - case LLMKey.claude: - // If you had a Claude key, you could handle it here - break; - } - - _hasLLMKey = await _checkHasLLMKey(); - notifyListeners(); - } -} diff --git a/team_a/teamA/lib/notifiers/login_state.dart b/team_a/teamA/lib/notifiers/login_state.dart deleted file mode 100644 index b5f4f882..00000000 --- a/team_a/teamA/lib/notifiers/login_state.dart +++ /dev/null @@ -1,9 +0,0 @@ -class LoginState { - bool isLoggedIn; - String? errorMessage; - - LoginState({ - this.isLoggedIn = false, - this.errorMessage, - }); -} diff --git a/team_a/teamA/lib/notifiers/theme_notifier.dart b/team_a/teamA/lib/notifiers/theme_notifier.dart deleted file mode 100644 index 5400db49..00000000 --- a/team_a/teamA/lib/notifiers/theme_notifier.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:flutter/material.dart'; - -class ThemeNotifier extends ChangeNotifier { - Color _primaryColor = Colors.deepPurple; - - Color get primaryColor => _primaryColor; - - void updateTheme(Color color) { - _primaryColor = color; - print('Theme updated to: $color'); - notifyListeners(); // Notify listeners (like the whole app) to rebuild - } -} - diff --git a/team_a/teamA/lib/services/api_service.dart b/team_a/teamA/lib/services/api_service.dart deleted file mode 100644 index 61490d33..00000000 --- a/team_a/teamA/lib/services/api_service.dart +++ /dev/null @@ -1,109 +0,0 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; -import 'package:logger/logger.dart'; - -class ApiService { - // Create a single Logger instance to reuse. - // We read the 'LOGGING_ENABLED' environment variable as a string, - // compare it to 'true', and then decide the log level. - final Logger _logger = Logger( - printer: PrettyPrinter( - methodCount: 0, // Number of stacktrace methods to show - errorMethodCount: 5, // Number of stacktrace methods for errors - colors: true, - printEmojis: true, - printTime: true, - ), - // if we ever want to turn this logging off, we can use the following: - // level: dotenv.env['LOGGING_ENABLED'] == 'true' - // ? Level.verbose - // : Level.nothing, - ); - - /// Sends an HTTP POST request to the specified [url]. - /// - /// Optional parameters: - /// - [headers] for custom headers - /// - [body] for post data - /// - [encoding] to specify the encoding for the request - /// - /// Returns the [http.Response] from the server. - Future httpPost( - Uri url, { - Map? headers, - Object? body, - Encoding? encoding, - }) async { - final stopwatch = Stopwatch()..start(); - try { - final response = await http.post( - url, - headers: headers, - body: body, - encoding: encoding, - ); - stopwatch.stop(); - _handleResponse(response, method: 'POST', duration: stopwatch.elapsed); - return response; - } catch (e, stackTrace) { - stopwatch.stop(); - _logger.e( - 'Exception (POST) -> $url (${stopwatch.elapsedMilliseconds}ms)', - e, - stackTrace, - ); - rethrow; - } - - } - - /// Sends an HTTP GET request to the specified [url]. - /// - /// Optional parameters: - /// - [headers] for custom headers - /// - /// Returns the [http.Response] from the server. - Future httpGet( - Uri url, { - Map? headers, - }) async { - final stopwatch = Stopwatch()..start(); - try { - final response = await http.get(url, headers: headers); - stopwatch.stop(); - - _handleResponse(response, method: 'GET', duration: stopwatch.elapsed); - return response; - } catch (e, stackTrace) { - stopwatch.stop(); - _logger.e( - 'Exception (GET) -> $url (${stopwatch.elapsedMilliseconds}ms)', - e, - stackTrace, - ); - rethrow; - } - } - - /// Handles the [response], logging success or error messages. - /// Includes [method] (GET/POST/...) and [duration] for helpful timing info. - void _handleResponse( - http.Response response, { - required String method, - required Duration duration, - }) { - final statusCode = response.statusCode; - final url = response.request?.url; - final ms = duration.inMilliseconds; - - if (statusCode == 200) { - _logger.i( - '[$method] $url -> SUCCESS ($statusCode) in ${ms}ms', - ); - } else { - _logger.w( - '[$method] $url -> ERROR ($statusCode) in ${ms}ms\nBody: ${response.body}', - ); - } - } -} diff --git a/team_a/teamA/lib/services/local_storage_service.dart b/team_a/teamA/lib/services/local_storage_service.dart deleted file mode 100644 index cbbea01e..00000000 --- a/team_a/teamA/lib/services/local_storage_service.dart +++ /dev/null @@ -1,240 +0,0 @@ -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:learninglens_app/Api/lms/enum/lms_enum.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:learninglens_app/Api/llm/enum/llm_enum.dart'; - -/// This class manages local storage operations using SharedPreferences and dotenv. -/// TODO: -/// - Encrypt sensitive data stored in SharedPreferences. -/// - Implement periodic server checks for API availability (Moodle, OpenAI, Claude, Perplexity). -class LocalStorageService { - static late SharedPreferences _prefs; - - /// Initializes SharedPreferences. MUST be called once at app startup. - static Future init() async { - _prefs = await SharedPreferences.getInstance(); - } - - /// Saves user credentials. - static void saveCredentials(String username, String password) { - _prefs.setStringList('credentials', [username, password]); - } - - /// Retrieves stored username, falling back to dotenv. - static String getUsername() { - final credentials = _prefs.getStringList('credentials'); - return credentials != null && credentials.isNotEmpty - ? credentials[0] - : dotenv.env['MOODLE_USERNAME'] ?? ''; - } - - /// Retrieves stored password, falling back to dotenv. - static String getPassword() { - final credentials = _prefs.getStringList('credentials'); - return credentials != null && credentials.length > 1 - ? credentials[1] - : dotenv.env['MOODLE_PASSWORD'] ?? ''; - } - - /// Clears stored credentials. - static void clearCredentials() { - _prefs.remove('credentials'); - } - - /// Saves theme preference. - static void saveTheme(String themeName) { - _prefs.setString('theme', themeName); - } - - /// Retrieves stored theme preference. - static String getTheme() { - return _prefs.getString('theme') ?? 'light'; // Default to 'light' theme - } - - /// Clears theme preference. - static void clearTheme() { - _prefs.remove('theme'); - } - - /// Saves login state. - static void saveMoodleLoginState(bool isLoggedIn) { - _prefs.setBool('isLoggedIntoMoodle', isLoggedIn); - } - - /// Retrieves login state. - static bool isLoggedIntoMoodle() { - return _prefs.getBool('isLoggedIntoMoodle') ?? false; - } - - /// Clears login state. - static void clearMoodleLoginState() { - _prefs.remove('isLoggedIntoMoodle'); - } - - /// Saves login state. - static void saveGoogleLoginState(bool isLoggedIn) { - _prefs.setBool('isLoggedIntoGoogle', isLoggedIn); - } - - /// Retrieves login state. - static bool isLoggedIntoGoogle() { - return _prefs.getBool('isLoggedIntoGoogle') ?? false; - } - - /// Clears login state. - static void clearGoogleLoginState() { - _prefs.remove('isLoggedIntoGoogle'); - } - - /// Saves Moodle URL. - static void saveMoodleUrl(String moodleUrl) { - _prefs.setString('moodleUrl', moodleUrl); - } - - /// Retrieves Moodle URL from storage or dotenv. - static String getMoodleUrl() { - return _prefs.getString('moodleUrl') ?? dotenv.env['MOODLE_URL'] ?? ''; - } - - /// Clears Moodle URL. - static void clearMoodleUrl() { - _prefs.remove('moodleUrl'); - } - - /// Saves primary color. - static void savePrimaryColor(String colorHex) { - _prefs.setString('primaryColor', colorHex); - } - - /// Retrieves primary color. - static String getPrimaryColor() { - return _prefs.getString('primaryColor') ?? '#FFFFFF'; // Default to white - } - - /// Saves OpenAI API key. - static void saveOpenAIKey(String openAIKey) { - _prefs.setString('openAIKey', openAIKey); - } - - /// Retrieves OpenAI API key from storage or dotenv. - static String getOpenAIKey() { - return _prefs.getString('openAIKey') ?? dotenv.env['openai_apikey'] ?? ''; - } - - static bool hasOpenAIKey() { - return getOpenAIKey().isNotEmpty; - } - - /// Clears OpenAI API key. - static void clearOpenAIKey() { - _prefs.remove('openAIKey'); - } - - // /// Saves Claude API key. - // static void saveClaudeKey(String claudeKey) { - // _prefs.setString('claudeKey', claudeKey); - // } - - // /// Retrieves Claude API key from storage or dotenv. - // static String getClaudeKey() { - // return _prefs.getString('claudeKey') ?? dotenv.env['claude_apiKey'] ?? ''; - // } - - // /// Clears Claude API key. - // static void clearClaudeKey() { - // _prefs.remove('claudeKey'); - // } - - /// Saves Perplexity API key. - static void savePerplexityKey(String perplexityKey) { - _prefs.setString('perplexityKey', perplexityKey); - } - - /// Retrieves Perplexity API key from storage or dotenv. - static String getPerplexityKey() { - return _prefs.getString('perplexityKey') ?? dotenv.env['perplexity_apikey'] ?? ''; - } - - static bool hasPerplexityKey() { - return getPerplexityKey().isNotEmpty; - } - - /// Clears Perplexity API key. - static void clearPerplexityKey() { - _prefs.remove('perplexityKey'); - } - - /// Saves Grok API key. - static void saveGrokKey(String grokKey) { - _prefs.setString('grokKey', grokKey); - } - - /// Retrieves Grok API key from storage or dotenv. - static String getGrokKey() { - return _prefs.getString('grokKey') ?? dotenv.env['grok_apiKey'] ?? ''; - } - - static bool hasGrokKey() { - return getGrokKey().isNotEmpty; - } - - /// Clears Grok API key. - static void clearGrokKey() { - _prefs.remove('grokKey'); - } - - static String getGoogleClientId() { - return _prefs.getString('GOOGLE_CLIENT_ID') ?? dotenv.env['GOOGLE_CLIENT_ID'] ?? ''; - } - - static void saveGoogleClientId(String clientId) { - _prefs.setString('GOOGLE_CLIENT_ID', clientId); - } - - static void clearGoogleClientId() { - _prefs.remove('GOOGLE_CLIENT_ID'); - } - - static saveGoogleAccessToken(String accessToken) { - _prefs.setString('GOOGLE_ACCESS_TOKEN', accessToken); - } - - static String? getGoogleAccessToken() { - return _prefs.getString('GOOGLE_ACCESS_TOKEN'); - } - - static clearGoogleAccessToken() { - _prefs.remove('GOOGLE_ACCESS_TOKEN'); - } - // Save LmsType as an INTEGER - static void saveSelectedClassroom(LmsType type) { - _prefs.setInt('selectedClassroom', type.index); - } - - // Get LmsType from stored INTEGER - static LmsType getSelectedClassroom() { - int? storedValue = _prefs.getInt('selectedClassroom'); - return storedValue != null ? LmsType.values[storedValue] : LmsType.MOODLE; - } - - // Clear stored selection - static void clearSelectedClassroom() { - _prefs.remove('selectedClassroom'); - } - - static hasLLMKey() { - return getOpenAIKey().isNotEmpty || getGrokKey().isNotEmpty || getPerplexityKey().isNotEmpty; - } - - static bool userHasLlmKey(LlmType llm) { - if (llm == LlmType.CHATGPT) { - return LocalStorageService.hasOpenAIKey(); - } else if (llm == LlmType.GROK) { - return LocalStorageService.hasGrokKey(); - } else if (llm == LlmType.PERPLEXITY) { - return LocalStorageService.hasPerplexityKey(); - } - - return false; - } -} diff --git a/team_a/teamA/lib/stub/html_stub.dart b/team_a/teamA/lib/stub/html_stub.dart deleted file mode 100644 index a2940b42..00000000 --- a/team_a/teamA/lib/stub/html_stub.dart +++ /dev/null @@ -1,45 +0,0 @@ -// This stub will provide dummy implementations for dart:html classes so that code -// using dart:html can compile on non-web platforms. -class HtmlStyle { - String display = ''; -} - -// A stub for the AnchorElement from dart:html. -class AnchorElement { - AnchorElement({required String href}); - String? download; - // Provide a style property with a default instance. - final HtmlStyle style = HtmlStyle(); - - // Stub for the click() method. - void click() {} - - // Stub for the remove() method. - void remove() {} -} - -// A stub for the Body element. -class Body { - // Provide an append() method that does nothing. - void append(dynamic element) {} -} - -// A stub for the Document. -class Document { - // Provide a dummy body. - final Body? body = Body(); -} - -// A getter for the document. -Document get document => Document(); - -// A stub for the Blob class. -class Blob { - Blob(List parts); -} - -// A stub for the Url helper. -class Url { - static String createObjectUrlFromBlob(Blob blob) => ''; - static void revokeObjectUrl(String url) {} -} diff --git a/team_a/teamA/pubspec.yaml b/team_a/teamA/pubspec.yaml deleted file mode 100644 index 2c933c4b..00000000 --- a/team_a/teamA/pubspec.yaml +++ /dev/null @@ -1,51 +0,0 @@ -name: learninglens_app -description: A new Flutter project. - -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -version: 0.0.1+1 - -environment: - sdk: ^3.1.1 - -dependencies: - flutter: - sdk: flutter - - editable: ^2.0.0 - flutter_dotenv: ^5.1.0 - xml: ^6.2.2 - http: ^1.2.1 - flutter_quill: ^10.8.0 - english_words: ^4.0.0 - provider: ^6.0.0 - cached_network_image: ^3.4.1 - image_network: ^2.5.6 - path: ^1.8.0 - intl: ^0.19.0 - flutter_colorpicker: ^1.1.0 - shared_preferences: ^2.0.8 - logger: ^1.4.0 - google_sign_in: ^6.2.2 - flutter_secure_storage: ^9.2.4 - file_picker: ^9.0.2 - pdf: ^3.10.1 - excel: ^2.0.0 - printing: ^5.10.1 - -dev_dependencies: - flutter_test: - sdk: flutter - - flutter_lints: ^5.0.0 - mockito: ^5.4.2 - build_runner: ^2.4.7 - - -flutter: - assets: - - assets/login_image.png - - .env - - uses-material-design: true - diff --git a/team_a/teamA/test/Views/dashboard_test.dart b/team_a/teamA/test/Views/dashboard_test.dart deleted file mode 100644 index 877ece2c..00000000 --- a/team_a/teamA/test/Views/dashboard_test.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:learninglens_app/Views/dashboard.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -void main() { - setUp(() async { - SharedPreferences.setMockInitialValues({}); - await dotenv.load(fileName: ".env"); - await LocalStorageService.init(); - }); - - testWidgets('Buttons should be disabled when user cannot access the app', (WidgetTester tester) async { - // Manually override static methods - - // except Local - expect(LocalStorageService.isLoggedIntoMoodle(), false); - - await tester.pumpWidget( - const MaterialApp( - home: TeacherDashboard(), - ), - ); - - // Find all buttons - final coursesButton = find.text('Courses'); - final essaysButton = find.text('Essays'); - final iepButton = find.text('IEP'); - final analyticsButton = find.text('Analytics'); - final lessonPlanButton = find.text('Lesson Plan'); - final assessmentsButton = find.text('Assessments'); - - // Verify that all buttons are disabled, to verify this is working. change isNull to isNotNull. - expect(tester.widget(find.ancestor(of: coursesButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - expect(tester.widget(find.ancestor(of: essaysButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - expect(tester.widget(find.ancestor(of: iepButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - expect(tester.widget(find.ancestor(of: analyticsButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - expect(tester.widget(find.ancestor(of: lessonPlanButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - expect(tester.widget(find.ancestor(of: assessmentsButton, matching: find.byType(ElevatedButton))).onPressed, isNull); - }); -} diff --git a/team_a/teamA/test/services/local_storage_service_test.dart b/team_a/teamA/test/services/local_storage_service_test.dart deleted file mode 100644 index 5c63ae72..00000000 --- a/team_a/teamA/test/services/local_storage_service_test.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:learninglens_app/services/local_storage_service.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; - -// trigger github actions. - - -void main() { - setUpAll(() async { - // Load the dotenv file before running any test - await dotenv.load(fileName: ".env"); - }); - - setUp(() async { - // Set up a mock SharedPreferences instance - SharedPreferences.setMockInitialValues({}); - await LocalStorageService.init(); - }); - - test('saveCredentials stores and retrieves credentials', () { - LocalStorageService.saveCredentials('testUser', 'testPass'); - - expect(LocalStorageService.getUsername(), 'testUser'); - expect(LocalStorageService.getPassword(), 'testPass'); - }); - - test('getUsername defaults to dotenv if no stored credentials', () { - expect(LocalStorageService.getUsername(), dotenv.env['MOODLE_USERNAME'] ?? ''); - }); - - test('clearCredentials removes stored credentials', () { - LocalStorageService.saveCredentials('testUser', 'testPass'); - LocalStorageService.clearCredentials(); - - expect(LocalStorageService.getUsername(), dotenv.env['MOODLE_USERNAME'] ?? ''); - expect(LocalStorageService.getPassword(), dotenv.env['MOODLE_PASSWORD'] ?? ''); - }); - - test('saveTheme and getTheme work correctly', () { - LocalStorageService.saveTheme('dark'); - - expect(LocalStorageService.getTheme(), 'dark'); - }); - - test('saveLoginState and getIsLoggedIn work correctly', () { - LocalStorageService.saveMoodleLoginState(true); - - expect(LocalStorageService.isLoggedIntoMoodle(), true); - }); - - test('clearLoginState resets login state', () { - LocalStorageService.saveMoodleLoginState(true); - LocalStorageService.clearMoodleLoginState(); - - expect(LocalStorageService.isLoggedIntoMoodle(), false); - }); - - test('save and retrieve API keys', () { - LocalStorageService.saveOpenAIKey('test-api-key'); - - expect(LocalStorageService.getOpenAIKey(), 'test-api-key'); - }); - - test('clearOpenAIKey removes stored API key', () { - LocalStorageService.saveOpenAIKey('test-api-key'); - LocalStorageService.clearOpenAIKey(); - - expect(LocalStorageService.getOpenAIKey(), dotenv.env['openai_apikey'] ?? ''); - }); -} diff --git a/team_b/README.md b/team_b/README.md deleted file mode 100644 index 867d5a07..00000000 --- a/team_b/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Team Members for Team B - -Kenneth Jones -Zander Forsythe -Racheal Amuneke -Aly Clark -Bernhard Zwahlen -Patrick Staunton -Brian Klemfuss diff --git a/team_b/yappy/.gitignore b/team_b/yappy/.gitignore deleted file mode 100644 index f8b6864d..00000000 --- a/team_b/yappy/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ -.env -env.g.dart - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release -/android/app/.cxx - -# Ignore native build artifacts -*.cc -*.h -*.cmake -*.swift \ No newline at end of file diff --git a/team_b/yappy/.metadata b/team_b/yappy/.metadata deleted file mode 100644 index 5b39692b..00000000 --- a/team_b/yappy/.metadata +++ /dev/null @@ -1,45 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "d8a9f9a52e5af486f80d932e838ee93861ffd863" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: android - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: ios - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: linux - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: macos - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: web - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - platform: windows - create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/team_b/yappy/.vscode/settings.json b/team_b/yappy/.vscode/settings.json deleted file mode 100644 index 0e14d8e2..00000000 --- a/team_b/yappy/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "java.configuration.updateBuildConfiguration": "disabled" -} \ No newline at end of file diff --git a/team_b/yappy/README.md b/team_b/yappy/README.md deleted file mode 100644 index fe23b675..00000000 --- a/team_b/yappy/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# yappy! - -yappy! is an application that allows you to store transcripts of recorded audio created by Sherpa within the medical, restaurant, and mechanic industry contexts. These transcripts are then summarized via ChatGPT and parsed for relevant information in those respective industry contexts. Users can then search for specific transcripts and ask an AI assistant for more details about each industry's transcripts. - -### Feature Overview -* Real-time speech-to-text conversion -* Speaker identification -* Industry-specific parsing (restaurant, mechanic, medical) -* Order identification and menu item validation (restaurant) -* Vehicle and part identification (mechanic) -* Visit summarization and question/answer extraction (medical) -* Interactive dashboard with role-based access -* Data export capabilities -* Order history review and customer preference tracking - -## Getting Started with yappy! -Refer to the Programmer's Guide for additional detailed instructions on the structure of the codebase. -Refer to the Deployment and Operations Guide for environment setup and running yappy! -Refer to the User Guide for information about how users interact with yappy! - -### Project File Structure Overview -* This project subfolder shall contain the standard Flutter project structure, initially generated using the `flutter new` command. -* UI element code shall be placed in the root of the default “lib” folder. -* Backend code shall be placed in a subfolder under “lib” named “services”. -* Assets, including the icon pack, the database, and test documents shall be placed in the default “assets” folder. -* Unit tests and other UI testing code shall be placed within the default “test” folder. -* Android specific configurations shall be made under the default “android” folder. - -### Database Setup SQL File -[yappy_sql_command_v1.1.txt](https://github.com/user-attachments/files/19398862/yappy_sql_command_v1.1.txt) -To update this file: -1. Delete current database in assets/ directory -2. Delete the database from the emulator (data/data/com.spring2025.yappy/databases/yappy_database.db) - only if the application has been run before -3. Update the SQL file as needed -4. Run SQL commands in a database integrated development environmnent (e.g. SQLite DB Browser) -5. Copy the updated database file to the assets/ directory -6. Update table creation methods and any associated queries in database_helper.dart - -And remember, be **super** happy you have **yappy!** diff --git a/team_b/yappy/analysis_options.yaml b/team_b/yappy/analysis_options.yaml deleted file mode 100644 index d83f5f77..00000000 --- a/team_b/yappy/analysis_options.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -analyzer: - exclude: - - lib/env.dart - - lib/*.g.dart - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/team_b/yappy/android/.gitignore b/team_b/yappy/android/.gitignore deleted file mode 100644 index 55afd919..00000000 --- a/team_b/yappy/android/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/team_b/yappy/android/app/build.gradle b/team_b/yappy/android/app/build.gradle deleted file mode 100644 index 89802d2e..00000000 --- a/team_b/yappy/android/app/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - -android { - namespace = "com.spring2025.yappy" - compileSdkVersion 35 // Latest stable version - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 - } - - defaultConfig { - applicationId = "com.spring2025.yappy" - minSdkVersion 23 - targetSdkVersion 34 // Latest stable version - versionCode = project.hasProperty('flutterVersionCode') ? flutterVersionCode.toInteger() : 1 - versionName = project.hasProperty('flutterVersionName') ? flutterVersionName : "1.0.0" - } - - buildTypes { - release { - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = "../.." -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/team_b/yappy/android/app/src/debug/AndroidManifest.xml b/team_b/yappy/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index ab1aac76..00000000 --- a/team_b/yappy/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/team_b/yappy/android/app/src/main/AndroidManifest.xml b/team_b/yappy/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index ae0e391a..00000000 --- a/team_b/yappy/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/android/app/src/main/java/com/spring2025/yappy/MainActivity.java b/team_b/yappy/android/app/src/main/java/com/spring2025/yappy/MainActivity.java deleted file mode 100644 index 5193ce97..00000000 --- a/team_b/yappy/android/app/src/main/java/com/spring2025/yappy/MainActivity.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.spring2025.yappy; - -import android.os.Bundle; -import io.flutter.embedding.android.FlutterActivity; -import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.plugin.common.MethodChannel; -import android.media.MediaScannerConnection; -import android.net.Uri; - -public class MainActivity extends FlutterActivity { - private static final String CHANNEL = "com.yourcompany.yappy/files"; - - @Override - public void configureFlutterEngine(FlutterEngine flutterEngine) { - super.configureFlutterEngine(flutterEngine); - new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) - .setMethodCallHandler( - (call, result) -> { - if (call.method.equals("scanFile")) { - String filePath = (String) call.argument("filePath"); - scanFile(filePath); - result.success(null); - } else { - result.notImplemented(); - } - } - ); - } - - private void scanFile(String path) { - MediaScannerConnection.scanFile(this, new String[]{path}, null, (path1, uri) -> { - // File scanned - }); - } -} \ No newline at end of file diff --git a/team_b/yappy/android/app/src/main/kotlin/com/example/yappy/MainActivity.kt b/team_b/yappy/android/app/src/main/kotlin/com/example/yappy/MainActivity.kt deleted file mode 100644 index 6ef3bfbe..00000000 --- a/team_b/yappy/android/app/src/main/kotlin/com/example/yappy/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.yappy - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() diff --git a/team_b/yappy/android/app/src/main/res/drawable-v21/launch_background.xml b/team_b/yappy/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3..00000000 --- a/team_b/yappy/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/team_b/yappy/android/app/src/main/res/drawable/launch_background.xml b/team_b/yappy/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f8..00000000 --- a/team_b/yappy/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/team_b/yappy/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/team_b/yappy/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 257944e567798b8385066e0f3e3cda0af4dfbaa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8069 zcmV;0A9~=4P)EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}0014BNklF%Tbodbs&cQ@^<*;rrSd7?9sPRU>UxW86_3MTrb zMcbR^*lD-UXlnfJiA*2FiborU^^fFZ&}=WqeKmzJiJQ*A-06f2eX^g}nS9 zZflDSME+d8zGmHlKh$h(+IKqgb;;Kf#uKLzGB|D z=lts9|Jd-O+Ry6xE>e_X?JEIfciFJ)*(Fs={`RIf1WBCDv_vBXe;itz-l4id z%{)Q{D9WRJ9_D+faV5n?;6+Ejh5+T)E~{F1<-#l1y!qtY&mY}-y#G?i6`HF z?1pV?c0In~CmZ*~!|{uf^`Zg#&M)p?Fn8s3?^B>eRwY$TOC6Q=of^z2LJ*5asb1dF zG%gy>Jy2{Gn%?lzp;& zvWaIbfKfo!-Ic( z`hSnDd93~Q2VQ?izCgNiL4a;}c;1AWcUQenDYA!oa7s)w&TU8cR{TYVAv`4}ucnX$ zfe29+Arb)+ksuHiEJ~50GSd7f1(_r{DEx3@x1*3I&8zsu zoj+XO@X3$=SbNC;F;~9w$18qCA(XHi%a+;K%taYMnhjny4-%>%1WB4!gpmcl#B?CqCXi#Fwz5m)Q|3DFJdHxw2(5{v(~4g zr5d9v@s*-|N~k3uO(+LURm_~5o>;uL?P$jh2R^RuxoCh`5cu6UzVib?6mJ{Ksmg?z zJd!HZuyjisKPAW%vN6d!2^EYnTiEbptm_7z}DIsPPADYX_%87!(Q3Q0#%Ky4=b@Rb9e;sHJ40DL*1?cu? zmd+@eJnl!#Yf@^}7S27YN$KGZJ4T64(lYZNl)?)Srh2c$wA`zZCuKwAP9Ii=P+8RK zpOh~|{+^kk1gG5%Uv4h0%9(~U;TALmkD)c$%8XDmIP3M=xH;Dm#Z0NLWcX=;lyAw4)xTaD;+T9dPLzLqC!TDz*PXX z+>c>5VdjLF7d*0X*Y3A=o*ENC_rLPM4~Qtvl1(Gm-8NOZ2!bBpXt52`7#R|>h!=|r zuScbK5^S(RPzOpio-hkOLL-C>`NDdMsM@bfbmE%KDJXM~$DTkn8U~s;sdKJTou}qV zHFKt_*Hd^&w@Ke^&o6(u?oWsB4RsAz+}bdJ=07xloUhFH937HEP#!iDBj}^12wKh5 ziEKlWSb)Xj7NW#ipaNrP$xzc8JzyNY>GvRpL1jrRgTH@w^QZs`l7L&DyyaO+k)z$zk`$oak(11D>J*bXB!=ZxJtkJInEkJt zUis73zP6yQMHYZ&-hEwuPI2CMIa3UYiZ%6AB4V|+qoF4g6iE44T)YtZwp<8ARD(CF zgJU)O%MTFO0uWr2HyxpL2>XIHkVR?%fvAx-cOa^Hu~&n-$PJ7B_SS`e{Fe{6j|k8$ zPu}_v(;hAE(p|WETqkG^DD?{uoVc-QE{bgVYR5zC&8GK5`DKKrncgri8Us{LV#gfc zweZJ#a5CDg^NP*b&#eUlv(*z@QPkNtk=s7qsXi+`IwViY9er>^g~DV za&-8aBQ_QaOwF2rqkY9V5pPzsNT5UdPz!5R>5nhU5sJbo#VaxjGJhWG8lW7Y{7HpU zMnUFXM%rMSEou<5W_VN$xUO)NVscgm&vS-Wx-3Nqt*oKOO9>iBTu$)h)FHUIiVKvQ zN)tqlwJ6dwjaWL)-#bJHBqBnjMm(jE>}U8)uq+%?mo)_nzrQX$ufirvp!REc5cer6>VbSpoA*lHEAq zR}yj(b%A@GB^>j-9I8ZOJ1_H=xSPfz~|5gOrIM^imG*V%@a z{uVrR%{P%}^C@)!DxzuNG~PM77TxK79yYLhboF&Pa6bX}knl5E2jo>B-ybF1?-f2a+;sUUKlxmY>nZusoE zNYfP3sW`sy@5Z5?Bd84=QTroEL*`CkS;eiW%Dq~NmPH%Z9DNrjdrl)(o`6Ggj%jin zf(^x<0(3@tm`d?VC$R*t21uriq`Y9tc$Z{z*(E^|%ZJr`RDWt@?L>F&9>I+qdoIW@ zrWuk|n)pYS(>y$K5I3BXi(kn~7#Yq?ejOXMOk_RrWkVKa8#3%!dM|EU1_ZF8nhbr> z;5_M^rtuO)jQ5VmfzUCfenQQfV+GUTBkFc#d5WaUo2GeXkQ|~qTiI-4927xEOetj$ z`0Uwm3pOX9}_OeWHc(J1z}??--l z4kzh7tzRNRk|@d?$20k{HU>nArvONakZp{hWd$7FYV?p%@ooY;Mx>0Q>_Q0?d8|fj z>@%RISjAkZF^;?KE{L2s$#BgXHZ%oT=BSCoj&PzEA2zPTw&pzurNiizLrStsWj&|T z0+f^}V|(X5GzL!cF?FSTdAwq?Igp@f*aQmEoGy$q26otMce1h@WTf;Owz;CIW&2u` z&Hjjz=#v1F!8R{hiP>7|*D`ljb7nX2+B_!nGNEs3`n@R7o#@2}4Id(q>;@48L}&tM zlWl5DqAe^6YF|c*!r~oPe{PrkYPnRYQdav9AzR469TiLArcT|ljFj1EtRe|^xM4>h z;%YQa^gfTK?XKL*ccEJu^4r&_JkcuZGodJaL-qH0q z5j&@atV*R%FP+HhccS8Q)#=bu0zIPBl$j7DkjCbY-NL`?(>BsD5Kp{e!(vBoh}5e+W+#WE^gxC*Nl~ZRIy%AQ?u2%5VyHWZFGQ z$`lRVjaYy5b3}wFBPAtOkQFmz(YZg?J<2XMW1`scq?|-F6}OgeOeqmHEqCbj0)&|c zG1riykR|n~4x+gZ1itN*a*%?_ey$xh&Ksl5n2H-)F-`NCqkJO))ch$Wq;asX22FcU zqB5rflkzGtKEnsQU_(c;2d#Y_Xy`hIv*B|{yOf1OR(s+*6xH!Cr{NJ@7mVc@u?OP= zh?0~ljsnJrq^>(Q|^S5xOJ@`&7JnA!Z;i01hp$fO7&or zm=-UGk#uWEU2}-@&OlfHq3kl>Loj9V&|@HCDsw1}4YaA}H0JoOfmaxL^;%H>O0Z*o z@f-}s2l4*VbqLWYly#9bWYK|H#WOM9S%{9PAK~aA(l$ZZ-(MRE3@F6h zR(ob=>74SkuHE{T#E4B`z6(KXJb;#P8>VJdm{J7mBxr-N$u=x0zXkc;e5`Bu1Wo;C zxa;o?_h5hHK0LkX`&d3{iBa)mmL~weul)p#txZUg6z8A}(Suti-hgFOmLXTlQnW$9 z$f~1SWQ@kKx1$cS&B&Ov_|~FyI+rTi)!!P}o{A@xn)Hb;>gun5{ML35TB>P|B|HuPN^Emo!3fXeJLzBo8+Hmum_rHiAz%{Ucn2lWU;_Bs;P zI@E7WlTU%vsjUrsg_Q%;*>E-y3&p;0X1X3VtBP6e%oSW-eIpcSqU|^lI*Y5aCZDIa zr`>_@1UFmCz>*0!;>ObXh$W+N*d1^ahdv=1S+ap$S6qe4f=K{P!)^D%P9zhhp1+2` zZWl_&u>I^oR%3w?4yvlHd5odCq_U5u@yyO6Cv|}2R2og2>ps5fp1F^xiIEW;s+XG6 zSE7dPVIhrOowb&T3;Fk zQDWsEQwPb?IOjR7Cqk?hH(qX#)s9%|Kv=Sp z#E!rrlxLQq$eE)GbpFiRT6fWeGosUx^WCR}{+lHt;$;&HxKsaoN z3DK(yrhfMxT=T_|VF0mq@ORtaxcP@Gz7J4SxlY@urScL{%CK52!Q$Rtc>tT+_F!fC zt#C0u8N+OkF6zZ!t?bcOf{~b<#-~j?&?WSN*fjkUbn`bhb{d5_T~2_W+FZ9f8VrxT zyQBW2-6wB&X89j%PTT#%eY^Ry<|`G?#qM@45(Ck|)r2d8j>}IPk{CKbr4r0Vp1dqI%8d7v?{8$32u%r*6~Q z_Bj()$__0hFJkZAq60Q!$K`)`XLLYJoQyC{;?t8mu_xF7!7Hj2#vzONx{Ybt4|6@5 zwpBO2*im~rX6|QL7<}-p&GpmozW(*h;@oG9@IZ_Dv}Ie_Y77L(wR>P6C91w$fN0Gu zvrJPsJLt!T6MJwv(FV~YDO#ge9+V4=EwDrb&P>n>XuG!lcxb*MYDN4hEqS z)n^zx$JmmHvaBMgZd7M0)h3f{W4N5;8YU29NPUlL6Wd<=@YCX1m213(*-w}w6RLHj zt-cb1EXl*u1%8ORe<)Acum=f(@esB&AHwnObC_B%0aFUDKxt+nFLa6eV+GJn*l-0} z%uM++9&tH|u1GKH{AW1Tico9Dmv&T|V0$aE#hl1)xc0gWxqRJco#A!RD0Co8iYN=0#?{TQ~Nt3{73 z1j%bdAXJY%y>-YYZj5*PFfKD6K6e)K+*xo7PM(S=6vqHbAs7vzI}${DxECFv06LQa zq@3Wuh@z+pO1XlV`Nm4lf+40p8+w}2vw!u5Rh_k`MtuVKysX+*-PB+6_Le8A9=drG z2t0aJ4X97>P}tKVre{^~!bU<)p*uE!nvUZ*)Oid6Ap#+jz%D42L@E)a90a}TK?GA_ z)CbNWou-h|gx7uqqU|P83w5IMOC$lr1rU#Nj$qagEiKZ_mYB3i=f{ zYkxd~^Rx@Po!zgl-!p#pUIjHp2N&2&z23l-HBaoM^NWKj^=1P(oPDJ zDJoCz@KsY|Zy^7b^y~_f3Pze&{$Pp3nI?!sQf3gCf>fwG_zj*hG9scn6Jn}S>WvPx z243Fu{I5S^dFWRHC@~nrx<_7Fv*NA4%gvu!`hv2%O%a0$-;)kw&9M!L%1IDA0kQ-& zMNxbzBGw@m0US9gV$~%!4`)ficRWE4dWiaLG6y|)%XxgW2yB80RTa4FRH}YDw zrPQM5cO&o-K%>0_@Bd-dPk$5(hA$-k*dC~h2E%mSBd@%?^4;f!yh-E#lTW;w{KX|1 zvX||$m#jq+m2lakP%|nw&hVHvxZO6Feq3$Ps_ z+S4;oP01vLvMG}7M@-?P&KM}7%VR8mq95CW^?1DGHk^#KTL(yn1`WeBC(+m9e|f{>Kl{;G z!MP}az=Oy^tb6p8cNYHBHyf%RzI82tDH<^tVVALjs=3qS(KeilbYR7}h4{q3hx5h* z<8Q?}|1MOx$D_cZJj~b-YQ~Xp3+^qv0Y?VUqBYiy-}`sqhZDbrb^hI0QMdq6Ie}7V zKK|T$7&n5L9&H&0htq zjvyi@`903Wx^Oz$iF=rd1{*Mtjv+C_g+BoqK;TetO zBmFJ@SGWB0Z~m*jy77|#)5%xLE<^1-^2dMuleeyYbm`7{&-~TTY%cq9P%?Zakq~U` zsX%8wurzlDIum`^-QS24kq)E? zL8ZGG4TI+pOvNAxA`XOF_~QlUtejbODwf<;`@2m~A6UJDOKKyXpaZc5ILuFNgx?QO}K@> zXHP~~Wt8FLuKoNT%;O!8b{d0F9xrNa-F@VxJwJW_z3!teUkw?xUAFoJ)26Ne_Rbgk zSAV)?_EUE)nznM`Q-UPi0bopfg|`Hca-p@IW_$Wi!mehZ>^tWCf7`JO=i?uIk5^K^63?Xnke2D|#?ZU6SWZM$B0f7`VC7M4~npS#jGrSx8# z%P~vY%{D@#Kp+*iY$yn(BM>;J8s9a?wWqiFHjT!v`qS%McGmsAVeOV9k*>b4OJ^<4noxK{X0h)&fRwA+#m6v|Xkjchu@|Nl zZDD_~roXv!N6XIoFV1W^bTW9V{o>uyMYg}lf598<>Z1*7x3x5^-S#FCg*UxLxg>9L zsmqz|De@NP773E*Q~pgLw2D9D50(e?g#Eq#L^#^vuR9%z1p4K4Jo%Rxvflm|*bMwW TK*Id!00000NkvXXu0mjf;D%Zg diff --git a/team_b/yappy/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/team_b/yappy/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index e1ec93d68e23698af54d51bacf5b1adacd65a958..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4724 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 P00000NkvXXu0mjf-^IH$ diff --git a/team_b/yappy/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/team_b/yappy/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 6eab2408f3057b93cdbebd1a12a5ba9297aedd52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19936 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
    g&QpKO~QA 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 diff --git a/team_b/yappy/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/team_b/yappy/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 5c732d5d2169974891ee237254c9e3ffa910ac1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28860 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

    08gvKd8nUGRgqGlnab2$?UoT*; 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 - - - - - - diff --git a/team_b/yappy/android/app/src/main/res/values/styles.xml b/team_b/yappy/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef880..00000000 --- a/team_b/yappy/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/team_b/yappy/android/app/src/profile/AndroidManifest.xml b/team_b/yappy/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index ab1aac76..00000000 --- a/team_b/yappy/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/team_b/yappy/android/build.gradle b/team_b/yappy/android/build.gradle deleted file mode 100644 index 660a685c..00000000 --- a/team_b/yappy/android/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -buildscript { - ext.kotlin_version = '1.8.22' // Latest stable version - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.2.1' // Latest stable version - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.10' - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/team_b/yappy/android/gradle.properties b/team_b/yappy/android/gradle.properties deleted file mode 100644 index 25971708..00000000 --- a/team_b/yappy/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true -android.enableJetifier=true diff --git a/team_b/yappy/android/gradle/wrapper/gradle-wrapper.properties b/team_b/yappy/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 7bb2df6b..00000000 --- a/team_b/yappy/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip diff --git a/team_b/yappy/android/settings.gradle b/team_b/yappy/android/settings.gradle deleted file mode 100644 index a42444de..00000000 --- a/team_b/yappy/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.2.1" apply false - id "org.jetbrains.kotlin.android" version "1.8.22" apply false -} - -include ":app" diff --git a/team_b/yappy/assets/icon/app_icon.png b/team_b/yappy/assets/icon/app_icon.png deleted file mode 100644 index 42a3a5532a83977a85caa7dd3e17b6583085f825..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96286 zcmZ^KbyQT}7w;X0?vfG&5s(H!X&DfZRJyxF8tI;)6a)cjB$X1RTWSWRyHjAKyPJV| z^ZmW`{(Ng@);;U4HRtYg&i?GrXYX@vl*U^{5<&(-002momE^Sm01MN^0`PG$mowkV z8vp=>*~`gkD9g#QxVgK&vv;xu0M4&LUtcQy(V&h{*Dhe?BlRZ#(5sQPr=`HC%16`w z%ATio$Kqrh@_sx%zfp{^90w0d^NW;!xJjasFce7^*^JEJVr5@Sr8erkLY_zu2W+}6 z2f;?mg{K%J!6onL=X752QtNjic(B8NT9LEA+u8nW^(cFH_mOnlvVvdAWh+Eqi7TD> zD5~>A;X|5Z+~dE61s+RJNoz{-$#baGA5O9yKbf&jT^7@4r15<>+iOP~`KQyWAZ}gy zovs{vHhU~*$?NM^?Y0r8G^)v31o@TW&xObz=S4B>RFW5%KIxKA z8K!!4|Dh-6ajIH51D$xndzpx}t9CT<(rM^KZSV~t2dtfT;XVx;t68SVc44`veo-8R z8bKsapNh^SP*1nZvT4MzUe||2?`Crxf>I?Bvx)rl2~Vzz!`Q8 z2jXv;VNyd5*SKP0*oE9ltp~>k-|v6l1r$lbnHy}}J7m;B8tD`YbBo?n!N60_)!EtB#S@To zx3%=NwPEqG_k7QysQgAlKZKMP09XKJd08Fb`MuV;RHsX?<;yv{pWlBq3*cfkBD$2Y zSbzj1iwZS+dbN{dWoyExPJwGYCvM6&K$5kc0uPyC|7XT@Y)+$k>&=&BhK7a%eV_S8 z5^PmcY*ZOLDcC^d!gw*4O9$l=cAJ*yVI8lMoylTt)2T)H7u}z2i@J9AcNacTXaH2y z_jF?@L)3Mt#qa;y7!HeqV=uMrf4p1O&!!gT*lbO^Zg>YFV$l*Vx1IBynS<|S#=T$n zF+!P@w}_E>_;2UqI(s~7mfFrKQjUW2y(h4v%B#C*PRE=`fE#a zmmXVYApx|PHIuLqd&Mj)={Vg@S6BXy>hqDP2fVdIX>bjfA`>~0o-tgr?PDV-87;SWmANEI2DG+fX(@t{5? z=*HPDWAMMdI=3UC-L;C8rDgAm2AJsL;agag-en?-u#EMIsLSnIC*%!gHUQ+%LV6|C z%JUv*q-gwp7TniLT9Z0|8&VSM@Z;L(NJIY8>X5rVDKS;T4&q9a_NT9iT_l&7)ZJT# zMYbr@x6e-<6uEad3knqt5v5qtxxM}}zUzg2ap}Lin#z1y8Y1fY2s4^`DpF~0(l&;# zw1-b5C+T>0=~Q!**~4aF%-k*fIF9kp@GE{F`eS@e7+7jq*9`W{YHhg)2D=pnENc2M z9{fP5(%G8#kn@`R;OXp^>`oIb+ups&d;}H@*r-0so65v4Lmhmx2ANU#eqA}oI+8k~ ztT%~YXI=9nfUaKj1SNd`zfJD9&%P6571xBLA>iJOT&ror8^8# zjbXPx^_W|>5$(Sa1Mvb6Th`1ft_ODiXIIvU5`?E}A&;}@q1E&IEQBfI!DT<|-NVd8 zG7&G6Y>+_|$lzrCcSfH<=o36ZNDrydLo8K~?~wLA)GatBc)v** zgHR__W^J<>co-)uBLFT;^P#SNbIZG|_ZgLJZ9%-va37ah=JnjJf_Nn%s%y>QJj+9`iU3Zbt1xG#B0PYW z5}2H$IFgG$WDsTGA+e>g9Kn5nW=nKL# zFf^Y&5c#_yya$5e0qlA#AaPJPOOJtWyAP}aY>v|wx=z{>!cJb8+t(ui`8Pn=>O2%k zncHAm`H(B&`oLo>m}6KwWoeP`jF%q&$h*C)yrTWh!S7Z)Ux7lNBVs*;BgPc@D?+`{ zt)UD%pv5%uJ!E2;xl!q!vc3>q8GW_9`vcAE0f{~dGnGvBiU^bfSMrQO^?mZ(nNHt^ zcasWwlcISLIrKca=3p~m$cT{{yxk)J?f;|VnhiSg=I86~KYIi`(wM@_`~y$?;dJOm z%XDAfe7q0JjV8s)cL`YU)}Sa9q_-ycMFv2k_$UIYe2v0g#k`S2M0Xl~r^K)Zj|azi zvrYHkJ&qczsL=tiPrB!(bVG2cH&c({CsICL?2!k+=tSE`g5TIx!QiXU_~uTk$G$|X(jLdCzxW$rR6S46ntAEfxVxV6^WK|$9n`gSrFt# zeUXi;66tb{>?4OVU9ldq_uvPT89xFv;8Msk)l*eqNyPHjfCK%&DG2@evrt<==IP}~ zb_0NyTrMd23pH`Y2iCh z4ldKZq46&RXcWu_bGwBB+APq|18p{Sy3EGQR2T$wKlu!6Ie$w|5SMZU-}k?Ha9)7D zD&1V<_y5hTdNJU6jS1%UvxNf$haaqWO%ZX{Q(*HCGAvZ|CzueAd1RLVxKpeuyq2Q~(fE*8*hy0dDKH=AkoRkpQ(rps3aEO&k`p*3_l7;ho&()vEVM zV%)tC7%*AeMyg@K)J)xC>~RAhsM4XRc=eIZ27Z==`PuYGdUnzTqYJDLEgY{etLcgjcWcNNh;I!sT!{9NVfqvTpm*))xKM-*znN2GjfSc=x ziy%{W&6?jecq_xfc}7yobo>kMdrS2Q-xomchf3V3RY0O|mcydHpu|$%M}4{ zF?0hUFuDbshdGdG0Pjj0Nd`l2!4Pyx!N(U*110)#p2M--st)g*=}fO=xK`lH;^?Ko zO}~2eKpx-~{&nXn0Ogq2JG7+# z6Nd#M44e&tEeJM2-rqR+a#*y==3mpGG|uWjs4nh0m#Q5NAegN%la9C4PZxr|AT<}+ zq6b_z2R)IQsAkhnv^64(e+6F4xnn+vok_O2yu(}j5})(Jc)rG$1?g;^a?a4W2D>LQ za6I@_CEqR}@f!J}^zqmK2ww8`E4nDafCjy2kahH_ia&^~Svfc2REl{RA{oY?30+_W z_@E0I$}Dn>vIe)|qn@QaIeJq{^)CaymJa;aK}{^=l%t{PJ^Cq(`GX9SDGk;u;c_-; z{shwO*NmjGnt}uvbdB7GEaOSX+2gm|84Cm(Ns%96&|0&Ox)dDC=1F^pR<}?NzO+=9 zmDQ&>Gkga$<)dGMk^3Gf0`%+l1a#zH#Jt`9qsZiD|S z+#PnOfL`e-onVw3#!}jDYGX<U)*b<7h1E>uSI^Lp|Yt$w@wEHQs~U1*g|y1B#efvXXW!|Fnd zF_FR9Co?#v?BC*ACb|cf)0u#J&A)SaW_Cyn&fN`q^Gp27ale_1Dz^?2fQwidHvFs$ zZrL$_LCH{fr6kA3h%tf1W3FYJUW^meZ=jQU74FEIBGG>gg3wH9S3R%uf){Ua3me$W zyj%J4Ifa3ymG31*xGnqdbm%M!+8eN#y$&xeF`nQigY<%S{bvr*MV#4<=XB#{5OqNi znN{6=5pYn8A>>8I{{Fa{@&KBqC79N+-1tJeJ7GF(G*$38S50Os*}UnbxC-u$kGH)sDx<7p_ghW52r5g|wfQCGgLHblx>Z&LB^Zx?ln%Cp?@qOqgEay` zu-~F|&oSQOk_Cyq9wy&1Ss(nNbi+;@OK5BO$mZ4RSX(DI>dSNL_J($D4lSHtz@1ms_uorm@)XJS z_J>wh*31aDuEYFMk}Hm*Lbw`+pr@CPiC)(&#(CXD3_Z}Ra=ZWc+I3X~6OBL!7XU_mhW(G>i1A1g0q>e8fs!e;{;z{?;%JcG z0-B%p7)qQsckq03>aOgs%E`AKy=k;42&i9?uX8zZ@gaSLUFyS}-}V0Q&8hbM`rfhX z!c+Y4-89c5W(k%f+tR?JH_Ph(p~Pd4x$W!{E9L|qQ+5d@zQWf#@F6hva1;yI_X%C- zw=iFz|5Y2DG_%++O+is44)eMTDXm_-h4OP~n&yOz@uh%Ne)U2bqV)X3<3eadAfR9} zW11@wJ$AwSbsqQ%a|4rL4tArlcb~!?b9XHY0{jhQpLJ3jbIo}2AtRw9O9H)*lf!fQ z_~%08jfMr!rHs!O<4-<3rw@_sC-unq`ir>3%j7Q#}fyd))`?|kDb3n9bo;rXE&E4Sv z@V$-t5wJO^{I;kEqd#7pjLbU+0|O^${6dV|3Sla7U~UW@yMwm3E{9BAeA@qX zm;%V`21}SKf&76{0zhn6`0GJ8SLs&>ylz)NDA=a!jfgZA4keP|$PNJq-;*3EAW4vG zsfTB(SdV~A*G*=S=ud}~y~~NT-VsxSmBEiiSxjJHKA95ZeHf4fqeE4$#6Z%%SE>2z$#s$8l|8@I3tqC0oc%ZUI<#`N&$DZT*Uiatp;KlTR|Sx6Hc z)o$1i4OlIGQoaes_Eq}#&eMZExF*&c>|r<1R&QkAw-9_WuXmE1B2qmh^?3)fK3VZ+ z*msXfOL$znnGy$!djH;cAXTSH@evp)J^E;RVvPf1zA+RXp$@+o&~I_iwF8D5@BXB^ zzeMvG*e@$C?t&CtU(YZ!coU^gk`3Vi1uu6cgnJmi>_=DZ8j)4i&K}MOEY+VLz8Bl& z&!ydV5Ne9lHu}J%AmT|v`!|R5xl)|0Id)s*Q2+}RJCMY8pGseP-Iyo<7pb-YP@P^= zAnhv8@0&xwI`Rv4BW29jyWjGB`JsOcDg7T(HF*BP+QY_<=QHc6*MD2Wslq@1V(Uc0 zC8aoC+*+ZDzU$>@>@9GqNhMz3wTD39&6K*yv2(;ru$xF8S`L{-y&|1{%3PdxXDk`d z&T#eSM^k^>49!r;@z6K* z+}rBdXT``0OFt0&Q!;TIhM&oR;rLawTH!XDrG6<#;l2S&j_9RVD>kp`9##h1?`;Y7 zj#p$&M)yZ^I6%{?oT2xX)VoWr@%0yt_}U9MGaAOyW?D6QG{ucx5Or7s%nk;PdqH($ zjbyhtiQ-YeA`BrN5&$`Mlfo1$McSZ`95+1ZwJ#($g(nm`k~$8y8~f-3-cCZonlDg& zdO0EZ##oJHzhdTnPB)k(H3TmXy5f>dzo2TmX~`^Cq?y6ek;>-XUYaw*g1|3nlBWCD zO(kI|{AB1sVZgn6SWeOg#P2{V(?cv1<~(Q(7)ghCDJEj|AUx9a5OA+Uf#8*XDl_R> zVL(!hT36A)6g>h!2{4bG+>j8>NGf>#uJ(MbYMSHZu$*?RZn4g@@=FZ~c7BcU+_Yb0 zQnrHW=HKSV47=wEi6S$uJD>UJIwnZrs8Y{U>|q!Tp>XeG#k+&Q71etfbPzEjb@$)+ zJ7q?Iz1X`jTF4z~%mrFpZSn9W|B3nB@$>9RFVnxR@369`nH2G6(MeWq<#dtz!l3F6 z4ZZpR!lu`2(6Q;eX86Z99wG8J*6PRvr(A;Rmq(DOUN|BFoO9Qi{IuL}WEF(a+ix&K zdDg!@e}Wj10FKD@?rG~82#2(mX!9)g!Fs?x(orw!s7zK>>KLZ_&K3 z?;x--UAy=52B!n;3UCpY+zf^zJ`>3K>F|M6pL;!X;eO1D-Uv#HBR7%998U3}ZReft zU1enWflm-J<0_>i8#McBjoEVdmKg|c7e`+fx&2WEev=)E0v!o3QXTQS4GDv?L1J&3L06i*bB6+! zp^zY`;eX{-XJL(=5ZJ>I=0DuOu#i3>6;`@nOwFTmtQXSx9<3Mxk4e6H8A^ciJk8xr zXf$b#`Y$IxXluxl+N8&5Rue|tT$E!2IyD5nmIi|o1#VL5XZtP$aFGEb>!>b;d*=3O z6qKfMS>aw5Z?)luXX=5=>Kqs_WnZ~w$6#ttei{Jmyg8(b0E^-7LO=$qg%m}RLU&aG za|Nv7jH81Xo$26BG!+iN)%du3mRGjc@?KB#>F_lXrfBXLCMS_5QUXt{H+N}^xOr3d zO(DN4RqwiFIM8&+ueA2i_H>|77i+g3?$0n?dTM@m@3k(etM6q|(7M|KE^*Y)tI043 z+HC%ZIz4rUkk0>|M7h5?cOU0Jo(%o_wgFAvI5*VyIhhC-F#!{xI3t#^`wA^Qx_pdr z&}hVyEq}-RnpPW|*toGTf4i$m5ly@@n_gGrfg1_Qzd!BNIrCTx20-h-%NOlJh~^Kt zwy2kSCG_8_5F@yql!WK6)dT@8s&rSR^!$b`n6$tb*S4=LW$q={wEWg()jAAH5Qrys zo#FF8e%)OlNy|SR`Mm|@{#UV{YmCH41oFWSmSl^>s}QqjomMi7QPB$tk{ zuV6EH^1TAw7L6f-`8kO1@x*td;^lx4c<9)DoE0m?k&ngk$tDD9;I%NUCn<4%&XL`{ zNZ=T*sP|TSQU$gAR>^SFODQ#3z0I2G{0phe;$)C(M(;C^^KXB{#Qn&|FPs=erWYrL z!koNsCsrLjioWlIVuFqz^kCaq$u0-&y*HxOqCRDjpq={I1P_G56FO1~W8n7H>jU(_Id|zAZokw}nG@z7Udep#r&1 z;I(2{_77zT61Hvvg@N5optKw^O9Ixoe@7%f|CSDRt?y11W-RH6bo9#0q=$~LsE7Cq)uU_x;8!B1cp8CSbA( z^v?>Ye05Pf3}^pUd$OoU+gz@KYyt!0J6AJ!fFtp*Zzp}{DZtyO89!9XNBIDQ2jSa+ zY~C9H%*pe%`uKFT&NrO_5bRC?2jdx&UXdYu6xgoUl6wNJa)s5u49-730$7>lUQAp- zEVkXFN~O$n7og}@a^vOxz#(t8SwXz2ihX9$C9zlaM|0uphA;FBrVz_|*wBJ_x`MyK z+{LG=d;~B35e}xmONkd>p|IlXMY2FOT`0}fv$_`rzJA!%{9qOyg_+F+(0hWr0)@xO zcXY4|Zr<^dv}Zi)f3xG`yhRdg0gwa_9efjA87o!A|(hoA6g92YO6iEqUU{l zWFFnij8zeQ(r;~jcrFFj@Wz)znyIZH3IK=Nji4!mR1zX*T7~x!4dZVzC+HiGer4aC zN%$x~w_kVs>1X)0nv~7~O16LXi?ns9c1~{~*HOfRiMq~Tvt&>laQ4CdkwyH+e_5=e zqbQ>)M||x~-1VD%JEJ`{V;7s9N~}_=T~dl`&iIlYileTgZ0N~)&q1KnF);$C0cvs5 z7KG$SKCKLg=V&!zo$01}{+jXLHr^da575EhsAHQtnG-R$ykZm2*y5Pycj3IKU}Do& z*^M3*xv7xGvr7hz+S5&70h8-MZ4A`ILp~FI?t0fd!Qt_J zYqIwHu-}e@g7+D$t~0xEaT} z#9?6>`--+NqC!63qw#ln%u&KBK}e8pP-*uCt5Ux z`YNpFpvfQ^MC(F;JcM7_Yc@VuFJc6)SdL=ndWvK<6Urg@P48t2GyeL>DZ*P?lqDp4 zPjtqV`W0yHEJl(*{3Sb7>F9>fWM6RsM37eWrTryjxlEZRjy4glcaELfHCvM=`%r&U z*PT;{<>_QcNs|*%+20oh->~%bNkz)2a$TT8bwTO7J6_$3TYIl$!K3xW%>(lYzw@dD zNDB8ZnV{i4&%RZk!(*|(I>-d{?4PElx0T@tc{PbE=Mf;&e3SXN68Z@z`a%5xbViCL z|I`ltt;ln6t!zrTH?@bXi3S)w*=w_UkXQ}?o&}J>rR4OEe0%fq>NFg3K7t*kJ6Rh| zf0mkd<88m6Vzzt@B4vjLb~+Ldj7cx|qL*z+ zZ4!zX*tNexr$b!6Ma6Fb7CTS&Ii|dXDDwH0T*Red41w#OO7bcf z#4hUcR@&p};9G z9F=fIadY9~YI*GD@0gL&k z6;7Mouu&98>NwY;2>p=NdXX{Qx;p)`% zJ|YeIDSj*Uc}56`ANL8>%6AzyVq+ULxBZmeYMjKJARZJz2EJ{%8*Vdik(43FRw7^1 z%ozM|Zv+D9XUAGL7J!fttT$7c4Pe0D0bpsrGfS4&rliz*qvWob(}-?fE+SBtc&rHq zD}S4PI>~}bz7@K5+-=4%%_fZ+M`zE zw2|0Em3<~gop+sMQAx=$T{VdUOndnRaRCH8J9Zq_2N-ZuTuKRbkB>jAk6b z^93nkxF&Hkg`g3iScaMB_6i0D4u6!_RWxXKqCLQDGJO2WGWai#;WQ6Y_G(T@WMt+<+@IOj%gDS(n&cD_ zU&YY~#(<<&>$i|k)PDRjGPy3G$0K-dPIBp#DcAfms<}VadVb0*N+gz~U}qBEm_ES6 z{`?d2_;GT_^-~GU%$RgG>+Zg^W=-}qicvXYYL zi(63O9p#@T4Shr|)VmTO7^MSj@sj2nb_Y38{X_;+;PS$a1AJxmFWYr!b@eE!e z9~%6?6o~95U9cZ@P2Vp^+oA$C;lhBW*FV}ZE3KLIQ0aFvvWuRg&4yg()E3;&Tsag3 ze9jWaPJd4{{Cr88=|Sdy_BVjB`z$n#bB_YA%H!&p<$EU#1Qf92*1iV6p9AqfWg&C_ zrAj)8MPo{-X+M|q#;#hQ5?^(%pZZh>!Og`ENRYD(YetJ7Cr$o@Hed@XCrF(%Bwn zY`HDTzw+N(Xg;JWCfUneUh`jtHW{B7-N3m@l^#!MOim zm?kX)U1VsQ67M|it1v45Pytrip{(GqYzCicZBu@m`r>Q~ju-{xJ@`%wpN}2gyVP`i2mW6Vx z3M=<^H1m;q2rct}?ybdr^;ZZeZ#@h{s9UWEA9fnaWnX-7qK2;*`0p}rTm7D#-h8Zm zZ|k6|Ti5@kfEXdCHYNKFumA^aj)*#<|Npic$(kmvo%b9zEH21=!jug5P6gHZv>L6k8{rH|X6w!$5p=``l&d zp}+(4@<(sJN>elyadBq0HRiXCYkf&kxe>C6cX&m~fdeL2&&(5;g(cby9%H^&X{&2# ziEH7BXKZ$O?zpc^HxN46iowKMMID=4R12detqD^!Jqt= z((84bwG^jwJjN(vc)2+KAnAIAL#v>$DM!ES3uiRHOJ@?+GPW7${;2Oz`n+S+=cV_7 z4C1#nAbr_k*9po9faT!b3vrwWtQP(_QXocffDlcCa=$l>X)}>co0S@w@~L&8WFs0D z9?epYBR)$YpYkG^&3T9-ngJ6J#BT=YtQ{|_JZ?T%>|V82DnfRiMe=nVDzYmITx5+_ zVOge7X_);IP`FDX9INe!)md~he44A1qyMGDX2-v858Ei#_{E!O2ZCaLU+Ny6rZ!=A zY(r^mVJ8299l$$hT&4W=eR6_}%m$+7b0{yK#Sa3i9`a1J7$&ht%pOwWB87-&SX2#z zf@4uZpKLxq=A^{a{$A^Z99A#PIw{rq&TGIMKdoKm$*@@QoT_)FYQkpuhbmocgf5}I zHKk)BNnF0aj5-+I{|uCawh9=l1V3?2&~+#y@C){LCr7crrJyh6N90aEnA zgD<0v$|AVt(rm>ICw7AP&k}VC6Rt9Aygh>%FNXRgdzd%Jf=!GTe9}>d z_3*rlu+r{jK2{xFlnqB)=3Cqhnx-jwzRs0_SKFp4n>vdq8Cn&Y&y-PMaKi6{BsL|b&~W86!6=THfD{?u1T`mn7J83_ zM)t6^+14Dv>1Wni@mt~Y+VW26Sh_m-I_yTK7nJE6s(6c*^$(+x`D>g3+4oh8Kw~I-ESvyEPDSjGq08oncX$XA zgMej>$8b;YyFQtFv0wv8^nt`)0F_9C)MSuD7M*HUP=QffkylwLPeFi?ZWArJgOa=& zCqJB zDLX}3SjD1!-3Q0kFo5cX$v9L*#d^F$5R%rocW?#2a*&TQF_Sw-ZEPM37~OyS60e>E zO5^&T{0=BEB}M!=eLwmjUu$mst}gz@x_RRV8clmOgAff#>=}tt8vShvFrLFVH5NWq z(ZCy!+KwaixXD}_9a9mGFG7DN9olOQt&ccd^d($a`Hy2x+>9vP@UO%X;#!bjIKMRi zYt(itz%nTNy1-24SFnM@H=H4woEJJ`8HP`?yrhNHA3@(G3i+H?Yh1PYt!97A`?Zjf zG4tZE^E>}j*3rsuk}O6^Y@s1APA@;ObtRDP|=Lt^i(}ETd9=20)dlFu0 zH3Ik)CGy$hX6_rDS~+6f%`hcvfj+9i`?qLy^r-qZc|e-ds5(eMoCEpaJ|-T}Y?ae^ z5+01H_x>eBMF!ZO-!BbE@-fd=Yb}TIb_k$T?<9@$4so8{<&Lmaa>AL(z&O~LhLqw8cz2DrtllX=xj()$@jx8zDg5o3PC(0;NJQM@?+P{o>xdciDS#UD0|A>WU%e*Lz29rm3|Afo)9BZr z;c9l+fza9JVe`IoZQW^?DzN(qeIkVL)8u#&aVzu($WK3uPMUVETf3@@Jdyj6u;(H# zur)?>OB^cw$F0}wxu*_vIeG7a~bMn4d?gn-WUm!j=+Z<4P( zynjqC^u9q@t2^I42u*h_Hp+MDcq?l$>_dt8r=1fjWUy@^QNFL(1DZ2$F}bdv-Zy^GbH7O= z0ZlW=5x(BZuBPq|gGz>K zTGF}bOFD&svpj*vA%_=1ctIO@-OIi#@4ctU;j2Oqj*U_pC7!g|VE*xMpA)uQB+EQ*R5vKTe)O;n zQ-P7_fKn)R9i7(#2Nw)-U{TiC-I!{;*_wb%4ExO;mO|gMS@Tvc6JTHxTjVH#_RC4p zvUvRK;QQy_x{ieDDlP^Y@uw33)9Fa(>`Psf<4zX|U*UF0^gp&6uR?FOau@Yu#7h+BLyM-uIZFq5*X5VfK^e73j$EauC> zA>K>>&QAUe$S8~J29<{HLgIE>F!x;LHv4;jc1dWp$jMKYUG)(vXu@mS>Vp!ZALaQ~ zlgOvLe(3~MvYLm?cm#L3J%TE{crrbV1y32@lzW_CG3dutxSwA+3=^(NfYtDY+P_oc za~ARIWumKVCf5g^XQ(_I?H5wHGv!i5*FEr^pE|8x55^wicc0d}zl|jjyB_pVZ@unZ zwDaIXmV#lta;J(}r|<~v@oV!>Hv*8I`5Qy8G7aOmBu1(;Q*YFosuL@y;?qa0m26qZ zPnzu03EX;EV?TW8aF2ZFc>4I+2eam7B3?%*-C@--#G*pfy)P)tBtbMKP3cdFl@U1aKM0|U9!()^L%szJT3^OZcBYAENs3QOQquCzS5w;BO_LqX z69D73!&=|>dZmi_23f@*KKKuY|1g(j~1*ce4-e{1~&9J)#bRDu)aZFe#JVbc8Wv{y4PWf3>ra2P7n@vDUbp=(xTefhxjfAJ zcY=y#u)e-Ni`-UyJS`k~L%j06?6@Z&#{ZT$?`2UtbF+7|Wt+4~>3-@0p8nleUJogc z*C{UkwPn1r%j=Yg!onwIOuvY-$3G_Cl%}a0TC=zsmKHvB%S=hZ?VkB9(KdX3>{YH_ z?y;gm5I14nEn!L7$R=C0p=j9C@nb~BKC?uPkJ*;a$NSjytyleY!A#AYlSNPGXr-{A z0m`2Zzs-O*(kW$V=%XtLY#CIJ?x(i_4YPrf)%S;pojd4X1vK7}VsD{?hiz9oNA$|= zTe{EQJ*G3!=Q>&Q_LVFIJ;a=JeteX(sse_tAE;;3b0B$z06De& zLpg(PG}Be`OjdiC>I`UC8j`q{%11KGqcN}-$M)mthw>2!vG68*Bv{Idj%2$hXr)q- zT1|9?D-$i%6)?B2x?8qt{5`p2a0NHnHq+ynlOWSg=R2`DCM5rO9CjRkzs5boG1Dmh zK}IGzyj?y~DpALlMo5)uRrG;~BYQ*pLhLMHowMwwhHy;N7)|FQk%|V8uaT{@-_Vlw zQ(JboK$&0q%tdUS^I8F4+t+oF&5H}eN#^_wlyy|hLEH^7YeO3|iRv&Eqw1d$etr?m zrHP7Q6ig;S>lEs6{ZKnr%EeLlZdx5-be2KlUn#MfKZ;~yPqDJMAfHRnM(3+T$BQ5b zh8-5}ofL&nVX?}lKaefq3BR}No0Q3Oi=;QFoYT>XH` z$G3lpa-vMmFhzL^UDDpUg+&|FT1yVITkn==o}Pz6`i9mI-)yA%smSoxNRAu{B%c<) z*d`#@R$l9`!`(Z-nBCof_W6?TwcP8mNX_RzXfLAJxV3IPCGz08CPi8m@1XOrxZ#@C zb(1r4aovilZAU#(teSUkKrmeKhq;`Zxt$IpHjrAA#Nb(LK@ph0bKsYyD~7Qv3DC?} zHj5ur$|**_y) zLJ~wzf>wvZ!l>;SkpkMc%-%r2i1PQ$D_eodc%`z^3T6X7v>-!c%>7GJT)aJuS_yju zE?Q+)R^zm+YW?QjGy${cAhDN=<#^&(!{Fu0BauyFR{i-jl{<4-#@fK%!o(A+Hl>S; z0`xWf>`$7k)rf-tBYEG#G*?1o-dSW-ta4Vc3+|gCi~uNHm@=A=5pmF z=?x}T3VGAgc@{|!rBa~Fck)@3&X&e>t>tuih@yw_ahv-DD_7l<%A8k8NidCYPU7td z&81gOv=?Q|@|X&a>H0nu6*a>y0aZ8Kw?;FXLYBtoLN4)mf8RwZZ+2m84>t!g>Dl&` ze97I}%&`4aQ6g8#MLs$ocUEaqdkJ1{PXR4q#SUY&EuHs5fE$Dy0t!ZDf&say{p`;o zC3!Qy&9jG7DsI+wi`%?@0eX_b&b}d&ttY1x#qW^6Sc=)VB8u6K&coWu4lggnx0u~V zmwl4ZEb55QU5vqN_cbTdhX1bm$E%8jg-|zWQZP*6Qf<+9(%-FU5v^!-+EGFtpl92m%psSx9{u@$n>aTaqHbDSp0GN^-vv{fn_Lnb=%|BC@x8w_V08p!O^Np)e>-~3xnijWF;a5aKJ6QG2V0npv-|91ZjMzEZ|tWzL0V{Q(! z?zZhhXmSr;=g(eis(DFr38BER>hzlLDqS^$4|Cn_TPXs@;>|{Rj7~73Iag~um8pUE zLCjd0iFyvUZ~g0^In~$)M6qsw`WfRTmmdRGkTuQbW!E7@?1sj8S-eLfu7_)n0#^eznEy zw!|bE+D7v#SE2+c^d-q7I{(B6(~XfmS(1+ZEpd=u>*hZgl`W_@^b1>S`X?gY{%=7Y zMQy{E>k?y=+#9K*uw~ziz8UoN%ece6dGp2r{Zq_gE{+M)d({IkGQEJ`;rW;&#PFe@ zikb`2&D;6?v8dhO^cE_?RpDo$(gFYC!8B2zR1|3lEN zjc%r&8DX|JVxpF?J6kJ*4U9;zlYB;`;E;y`9R^!CUv-J)U*4=nZn3c`VL7^V5v)*R zPn2Hk;!@Z|w11iYcsu11{4lpgV&%}Qoi1fPaae>5l30ueFoz(C4uYQ6fxKyeM)5oE z(zQcrHBe=Q@IFGD|2DE74>Wh_)qO2+K>4xU=PI2_K$NjWmv!n|0w?`X8Dq2Bc7q*X zK+SnDrl^}Ho3ce4*ElJ;mg|G)ExslRmE~W~kVJoWbDjJC?VyQQ!Xt}J?X7V{OSMUr zYGF4HHcWvtq*KQ?%yc_U4QVxB|aCjHJx9~Re1zmczr8D3}J zb}?8|8ha-Ai}(o0jk?=7&55e4hWl81p&KeFyRxUTtLwqp*YSg1ZwC~-iyGik_36XE zvz+I@dx%FhIluQ)(Tz6aOukaE(L}>ETY7?BJ7ohAmWQxA-{oqQM-!w!;C$UanAO8* ze7jiUnBM@F#X}@TmR$SmUsmx+E$)(I`6ZvkBz^SrENO$Y419JLLb;Xyws&^*DJ~*A z(vWPd*)2oo#}tbGPV8Y4mI=q82cK2mJ@MsJ-v9Yyd{2bdov{ha;G3{0UqCE_wB3Y< z=5K;A9m01-Bfg*h=KCB$bH(%L~hhOEBakJFwIln#{F0 z8QwT}p3=Xix6>kdu3EsW`s7O{%F|>ie|2_e^tEGT2e;H{>4lliXUeZCU!eJVOQN4I z#3B_L&o1~T;C5$dK}Jf|Js}j&8-Jc%6j3VwK$6{`(O~_XvVet0_&=fY4*i??OC)-_ z2M+F9*sq4fN)dcS*x|BD)W)vSoRMX>Naeu=6ZRGE8C@|w5R>rtpWjCm3z9BMy8@~h z9}m%WN9S5zCfh~ISvB9ktpx} z(A+bo$-A~0bv%(=lxV2fv~@Z!;V|>N_xF&v3bvBF?Y>-st6KW9zXt6MxvwVM-lMbJ?$Cv#mhLR06@d_ncgm178!Cq zh92(3Ed%wID}4J_f!t-ZC*$Ixr8)aivNosew^8#dlAKBi|8}n@;ICj~XTd!?X~6BC z;_Y69+|78=Q_bux(Zxcay5@D$hKBt?JfaEkhEyI+%{%pGj|&hs1-4b_s}LS0VmA41 z&`hHBsB$^$H%$^-t6lk@dUjy9`13aWfV5plw_}YMomdh zHJX?vJ8KPDT6J?nkc2&KoUGxH{*$Y&9<%kFU^(|I(f^_8tE1ZJpRW^Ki@UoND~004 z-K8zX-Q7LG-JwW}ySuwXp?GnpxVtBBp5J-D=WPDo>}O|YXYSm&lQucE8jR#vB04*+ z+78^rM-ih%A;1~8M1>p2LkS+;P_4#c93d|;Wz77V|B|0snxZH8_f+%Xn&@mGdmYut z!-FS0-D|z0?(-*3_)U0^AjBn9z~%gnDjMUZtB}kas8^k-1Lcvgb-?~9ph|phZyqZ{>V zTYm=67kBEK*cFNd*H2CR&eTU7R&QP{jD4w&t8x9MU1k(@hch}-oTBTLng%#dI(1{M zQEL_X9~U5QgXVy7L_wSN+8lx%q+R60GN+4^07 zX!xxXqP@;%6->b~N#n?g(D<*Reb{?%roakYM&n ze*cdDl*(mE)TpOr#DG7SXt3JRu=tqiqq1M8T3ZXcxsFGKInX$bj2eiGAjgd0ET*HFgF0+!KD5k%l`x?k4lsBJ>t4Q~E;**o{M$8%yJI(vMDk54z3gQ_J4*uRB zt(yhqQ%2lbHAkAOZ*qKD-H}VB2Mr+tYUAru zw9q%NfB6u}cQ4`OgLGjq_`%3rc^l)%u*Ve(zEdBcgWAw-ykR$#nzItKa@>eo&a8_Q z4wW_IB@iu%+%+GM+TAtiJ^IA8dn0R(ru#r9mGnJlmXL@XYU#=E8$BYku6FLvJ2oMbh0a+fhYsGG{Ozt3}*+fwdyi=MGnT>ZPyB(?(xx8Fb^pzo+KCD zLBQaMgznoV^yioz5uzu<`ccsh%aoQ&Ow`7N`@np=Be$pv;lj)2=<3b4l*m&nb;JUO zAyL#AOqAlEMs3c_Of*T9bb?6A7$|aJIO}4pEiDAshiZZ=!xp<*?U+h7IC^&a#>RoR zi5we{$Ga))f7WnDSA>I;G$ z=KsA-;EzL3zT#(3Dxr<+M+xB^ojBN3h!f>qhf09T+~zOn=d@>J@>?wa2&|=OSq%7= zeNKlV(KPX_#l{g;%8kxHqo@LXU3zo_sYp>F2-R6m)QK!;3gBPbCPtqeG*j@g<>h%z z34Tv*4!x2TaiWJbnvo=2Q5zu&IRUmvwx$B!GD@m}N1JUAb(%e3SX<3xiyMaNKYOMj z11L05XH9lkJjvN*A>JQz64Da_uz%iMTnGi`NZ#-I-~XztVR<2lf@shZ+0KFVe$+RL z0v$IdV|Qy_6sf66Gqr6ZfhhEBMTo3E`3cM;p`W z`j(%~HWP1rr{F;$?r47YWGFU20Y(vJZz4eqkUI~1x#Q4uFB|UQrujv^toj_%vrTkg zi~`_G7Y^)X^hohDA#c3`Ak-UHV4gVg2Py%WT7^-{*BguLPQakWWw+};j{dY{e8#dP zWZO(lM{A>81M_yggi2vsFWqs8O14V_wudwGtvh@2(NDl$hN!`wNdo8sJK7QLNc8|u z*I(!oH=nw~3AC+O6*eW7ZhZI)x&SI$+LF{3NWT6hh+c<*^^(?>F~wV<&LQA|JNR*!RFZ}O%; zD?p~)hYvO*aJmF0RB08r9pTN6mD&7a4YfMfB5+Wit6OPbX6$R2rvlk`RoQTyR7AP6 z4JgD&5STbu`R#V;Z5?R90=`#Hmz9GsLX+P7!>HfM` zB8-QLRv5wb5sCWXyuQsmzgmjxCzgf=ss&6F^)xkyNvO3d(iI;p7gZLxGir% z0QX-M>pOqGPLWwj_QHw}*#phl1QWOF#;CE9O5MDXPJ10HNS! z^Hem))30iQ8@>fr9hXy`&z9d^GBv$jHKJDB`y|WV4|IQ{;=1d9P8IgS`l8owDEjT8 zgU5*%(&e9av^ll-8q9DUa3`s-_>)Gc7rOD}E2O9d{M#Bri^4JXHg7k|V?xF6H#r&!h$ zG3(DHHP&E9jo)Lv#LyBwVZ9SLHRRTZGTZKvwSDdWtI;zA$aMq9)`30eHaNIga`!3= z?F6XFEOA6i=qsJA4V)w2xC!MD{^G#{%Of%cjq2KFmDK4_eyF+%3VFB(Hec9X*UX~_ z*xclGN4@KH%P?L2E=AAX@8$OMny^MH&|If z^Q+rcI_-q)&s*3)YO9~A35?_JsFdu{5E^|@mMz)A*b)-7|3S%lu8{CIe;E37I#OMx zI!%|PG`IQpQE~Z6v0xmglwf}Ma(aT?ndOdM8;AGX=Bc5+mp?-8C<89Hu#}kv2?bXf z69G_G{6x>S&L>712;Lj;fnan8w)xnL*6~tfoBX+;M5ILM2416;G~zq0C;~13-Uzn_ zl^-OWvcs-_=cGBTEz*|qu+M#HAWW-yQmnpA6N0uzyf*Mc#jPfL^!(X)ar5hE?`G{W zgkeFhFNV$=1)H`sWH1hOG#?7{axF|iZeip;bV2OqRsbi9O3F%}d2|e|Vu9KF_!?|r zsV4O!f=3$7;MXc~hU33=?T#(JNjd;ZpipgnxX|RLy+Lftae1t&egP&+?4tCf=(ht+ zB5~|lbRP`K|E#TTzGpC?d7tV&Qs0!S;>J>8TlFf|ughD=AB)!e$bJ}MusR%^Tb5Lw zREQdB3dbm~AYn2VO{dXa?J4}dQ@ebvYZ)w`wR({_lZqIZc6GXz?@_4%ZI_?yd=~p2%TPdEzrp78Et2t91r)oY2HAY#l4)$bdzQzi)q3wwgk#b zn2ZAp=`$1PBdw8gpUh0lfZQ#l@?RFMz~!;f>h~@11}<5o0X6b2+k&x6`}T%a_>lG9 zhEm8zjmXXNH}F`^#>-f&NHL14PE@9>Sp?H9GEayrKqJMa)%@$q>lEmzij{c*>e6J9OI9!XP4@ZMIXYWk^y6` zFe$n9(`O}E1=(nDW`5!=bl)9#+d+ampD;}sk9d;XVyL7wf{k?d(p*x8JH2z7>B+td zmu(8}I&nFdNW&q~5#?wQG-6l3`BDYa8#9#Sj988iBfpjTaeL7C)*uKim09d@|4{=I zvHFAnjM@XZHyW{h2(Fz9=sfrZGQj|#9`OeXi{_@2HXoy<{W9%n(;<_6)a?xPPg%v@ z!0L<`gU>++)M9lK%|WQVdbRoQpYEP8r-x{ZdPo=;{(QV^C}9_ipm$4zCJaRZm-QKwEaywCjOflwd1 zyen_^$t1%;w14cMzgU{Wr;!kE(SjnEqMylI_y0rV?sr9WZ#>^a#94NG_&b|jx?z9i z!~+fgxWl?!@%)dQh!6dCLSxC(3aDJcrIJ1w|8L|MBs092l>J2MabRlK?=>sSyq##R zp=b^+6n?kv>(4~|j*X(d#Ux`n?@4{8Ox(ag`?3utykj4ZT>4X#J0lk?Cy|mao=)(_ zQl3!wm4Zv2sjylnw^W^V{Ao<*!_@3;k4x&d9<~$Bep=v71{NIF+senBEI^GtD~Zz_ zAQyQpeg@i7XUYz05i(ki*f6wTHuM&BGWwj90PARQdYr(pT;wZC-x+Y=`#W@A=J_}7 zAEJ&-th|6;ArMS7$(%9~m!At8d)X4+maY;ll69AUo1Y|^o+VQUD{v4MA+-YDePE{| zW4C9kK@Pk(wjLe{--Xuc0UJd4{No8)D^wPjol@oJ?jhOXM2;Q-Z@aZuf3G;(^YwxX zmbJz66O%hllhqLkq>3KA!dFt%nq^Aw_#mZ3#eYqNT9kcpm&VQU_4TtvF~+uPUa3qyB@$}|RM7DRiiO(6t0hY=TGcf=9g zFAAjIs<-f^6=<;b^`=4Eq+!RZRs|>PI)&`}(lsOQbdSlv%oRgUwiL*{e%Yo$r=^4_ zE>79pldBH!E755=5;+R9P3Q^f4;x7VYWt78k0hHvTVyK5%GT2?gaJ|^`;wBHP^uEV zxH-IGZF8`S*c=|C(l0f&*xj_}yybupj$NsuTpBZ1if6Y1TB%vLm!KxJ0E82~%OOMG z{RYRkZqSYq39Wff~QO)L1xkXMH=n zpG#B@J(owb&j0c`-X|nIEFMKTt*1*WyuJIxohJ9^Uhzp!Lm-9>>}jHS_zgBGTw#d- zz&5glV8N%I{OVB=A*_;mT*%)tKguSv2g$4EFs>$ih5ywVr?yYcIuNPnf5OpcO(pW7CmbVCw*&xg-f2eLSY7)y3HWyVDPWqiB-lQqka30uxO-~a`S5~z8 zErTg&X$MKJ;L>tzFFf|ngp?u{u#DAuem9t96vyPDP&IG2pOZN$tb*6sPeDnM&eorbEBj? zU@@Q7g6?jjiLl)FL(mVYF~ww($4hND0N)evyK>hx)@Njiqai4l=4>=h4?ythIRQ*! z;)B0~eq!tQ-3aA`ejkgFuySG{WMDbr7+r)8(j_&_wS=~6L8IcLn$Kh@zd&k#(Qh?i z5jP9ZkD9>q``5deNMZyLSYK3rQyVOw$t|y$#KWMh865-v(mZK)=pMbXYOmbv<3280 zvw&;AO;08S8%Ac#>A{g*FMI1c_`Et|1rwg?Adjufu-(YG5v|CcOg)bHN*oBcN|e## ze^f^m&wskw4mIG(r^1L}V5F8pF)D9!JljirN{)`7>+)Vbvu3K;Vv+F?ix@-1D#$y* zPv?@?7{)6h<#)ym)_}DQ^Z-@Pz9$rG)%;iYlRfKx{14(Nfx6@I-f_>%VvR z4l0t5mZr=;e=!v+?Ek&j{_Ym$hd2Rw*rme82TtMPoK=1Atyhe_ zl1OJT_S7<&zk-83V^#g=41 zf0iFA(vTwYQid6l?iPKMeEQIYsuHd>2E( z=>J^cHR|j*=u=v=uM|T%X|_XiD`v;YMcsqXv^7L z698P2O?@UPKSrr|0u2Jexo^^^#Q{opc7j#X;Z+2Y4rPxP1yKEkp7gCL=8fH4QIq+P zbvXtyZhu;jnKK?1Hho7ztBai@=Xj5y3RUf^*%{h{3>O9XG1E z-=K}JQP*h@5mk6*by<$*c$nkfE~Ebk)xGnfyWhnLcG@b1y389^qJEX;FLLm5`=qq@ z3()F%MlChT7QA2e)|EnzpxrVZlH%;xFE6;yPvM$E?wTaHY$P9j@9(YW@-<^H>*8a6 zuQD;<5%&jnYqL8lK;|7_Z5JrkvSsAVk?Z~<8A^>AskZ=SrcA|!q8(7B%!19z9o#c; zTPz(^tkd~^7O4(7>oqF+8GNrjHLxj=F)5Ju`c+KF@z1o18fAQarv>Au8=osQ7C zLaO&gQ+j#fScITQo{k$FjFZ=@pgSED>%vXX z8&3Rz@g8b7;n!|$r~DjVD;@$&*s-zQoYcM_8UA?njM@?XDK*itwUP$XxX$mHc7JZb z&4zXA41^1*?jnOmdEu&bZ#HdAO<{VnXDPeiepk)LprRbfeySnAeOSKuu7-oifa;8y zIi(j+Zf*PF2Zk5lSNj%^e19Uv|7iMOi=B=-^^PE+dw*~r*c+2+gM%(76&K{>OOICm`-ZBvu4XXw3Tu$eI%z}7oY zG2{+zCLU#<@13;G3N6oq2W_PX#%uubUkw8`6JNijl3KK zR39)+Q$GuFHbe)!K7Uk|LE{5&gzf=i+S{IWGKtK^-PV=6_SPu>tia{)#>KiV0Ou(Z z=HJBiOGH1|sLNjE_iH8<4oQMDa>@Sps?_nv)b;zb zn^IYH>efnrq+|QMMzhakho|Q)xv0OQ<#(p#lGF_4ePQQeF4j*|Vi8gBz%G&M_!`(S zipj6IDqHF(n@nUjh0K#wrH(FgloSu`4bPt{Z0(HTWQIV+yA`<#91YQiV^&>su&2=& zxCN@Z`Sb^V>lo^_xoKB~I!*fDbL9|B;~WyO(QH#_CrLz)b12d}9+8(#c|yL_TexZ# zXq6P$@mMwKE>5&uXM!N0`;Er2M1~Grp~ZDmV8Zut-*u5f=HD_4qK;-a==5ao%u{Yt z?LYP?8UCeZ_?Y-BAoV?1d;RS=xI@+p0Zzc402UjaMT z$t|Xb#0m3vhyeOJHJ0;PM6@okGJRbmTV3Mj+8-k9PDX$0oWF~=WJ@+0**s2_$)MpL zrd21JO7$#0{zCtj3w{rIdGF{6!pa4zf%Z@Uz%5m$Dp1eJDl>XO2Yhf(5$y&u5mBsn z!o}%4B*euYbcE}@y}vQRkcEnBP zq$?Z2?g5or=>bXAsUiat;k3Ycb}?Gcw*dsk&=`$MtvE*gdWp&F(P*S{F&~$kisajlVG|n$b#2a3?)e^gSNFTrW*u@(G7@>+-8QauM@9;cOO_ z2qM-$#S$T8>GZio1IcxF`vg!r0ZE9s%xq?19cGa)ZjoQ=#W*wy6B0g4u)KOpE6Lg< z$_Q z{=uO)^-Ao?NyDM;xj=dTJ>}RsIV`>iV0Sa^PJIlB0}*|`(e%uU_RkT0_}ns{gUR!b zqJ1zW$SJAMW_u<6OI+wg0&SoPa16m%pOm_g{bkOA2*r=H1P2sMS|;)hPPPZy0tk3} z0X@&{TtJUhnO1LHH30(P9^hlmb`(zc9K4_5&A9dOOQH2XYJ9}Y&{V;FF9)j8_6rpL z#4yafy`Qy1vYJqiIh1}c11NHKp^m-PLQ6HU-(tI&xrDX+=rll&HSp1t{f;77z}4mO z{dtzFfh@5MfTX~1&^Phk?|t^@KHgcU+oZ9-?#*0qUvNL_Ca~8-N@Q|WDk$`Kof4sT z8F^~ubS9x4Tcs0=BCe#G;*9XQrW9!Err(!D@UXt)I`Kj|`Q5ARMF{jG7&H`#+jjs5 zX6S`d#wDpih%2D%Hmcq=S5!SFaz8#iQ#@?+yziG!s33oj1>nw*)PMt`($3_a`IAM; zux_-Ryh?(Zc0chvrlI2FbZJNpgRnFQ5QlR%tV$+;aDGNro=b~lft1>alq({ePPFl2 zSNCUZ6P+8!xL!)e%i0t$!03Uh>2a?0R zTXItaFP8DP8>IhwQBs}Uif#ZOADpgxLBQM|B!ITp{MF)P-wL$);_W688^OJ}P^gDC zEM|)e7X`Q98_GIB``si}u&GC@I3a;r?%+)m$|2-H!;u4pe1E-;6X z+6MJadZ}~WdfYBU9$rSt1#hO_wZ?J*F6!!E&|o?cbLfJgXAxg+Q=fYGqL^zHCa6gkaloHG{~fFwgL z2Bwy$O)YzXq-oPD{$mZ#Z~V3wr3JnB2_+W~dYozzo4jOO!@D=N(AMVC)o!jeTi>KB z*o0;vUtl4#sG}4s$km>#P}h_<`&l+m?%e@WUye*Rbviw626dXik0acQ#{TBA>2$&> z-da2I611Dk;uh4_1rkr>k^Yx2z+SYt&_k?EGys?3O=0`an`!{YHCYTY4TzCS<=O`* zRed4)MSyS&cib&fx?YTyTaLNro{4q}WJO>Vzd{YBI|XeLMr8RKW?wT~VBcQN0|}@? zPT%~Sx$KN`jkO0tpxy<;6YI9#g*$TiF)1PRh|=9&$@C!yj?^`)Vi9wzrW>~pCJ-#I z=>lgAh(Fh3F_|p<08%CbBgd*!1+ch1>(&Fq8V*YRjtCF0*b!Y(ac~7ObDNnq%7t zJ$U$_EdCzKBBQ0ot`MwLM6esNli7m8+?b3kMK7!+`kZ zAvIqtJIX4uY$KV=2@tJ#HMiyK90APRXpV$)#}G(WbB1`l$qm}L!96+tV+9CzYT?f5 z7cF*q-z8n67n-eF#ZAeq9P*aMbS-;Lu&4i+azP~AhDGx*BIWX=;8^er6F7eCVx}7b z#d(bPcO|N<2ZVA$6Yoi#GifH8Y=ylJuU;%0AyZ+Pjeo7a7c@DL>pINnoB@Eg+O|d+ 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 B@FV~L diff --git a/team_b/yappy/ios/.gitignore b/team_b/yappy/ios/.gitignore deleted file mode 100644 index 7a7f9873..00000000 --- a/team_b/yappy/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/team_b/yappy/ios/Flutter/AppFrameworkInfo.plist b/team_b/yappy/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 7c569640..00000000 --- a/team_b/yappy/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 12.0 - - diff --git a/team_b/yappy/ios/Flutter/Debug.xcconfig b/team_b/yappy/ios/Flutter/Debug.xcconfig deleted file mode 100644 index 592ceee8..00000000 --- a/team_b/yappy/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/team_b/yappy/ios/Flutter/Release.xcconfig b/team_b/yappy/ios/Flutter/Release.xcconfig deleted file mode 100644 index 592ceee8..00000000 --- a/team_b/yappy/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/team_b/yappy/ios/Runner.xcodeproj/project.pbxproj b/team_b/yappy/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 92da6d9b..00000000 --- a/team_b/yappy/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,616 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/team_b/yappy/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/team_b/yappy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/team_b/yappy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 8e3ca5df..00000000 --- a/team_b/yappy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/ios/Runner.xcworkspace/contents.xcworkspacedata b/team_b/yappy/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16..00000000 --- a/team_b/yappy/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/team_b/yappy/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/team_b/yappy/ios/Runner/AppDelegate.swift b/team_b/yappy/ios/Runner/AppDelegate.swift deleted file mode 100644 index 62666446..00000000 --- a/team_b/yappy/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d0d98aa1..00000000 --- a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1 +0,0 @@ -{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index 1973bf0c8ee3a9d7e5394f6e92cead136beb2f07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 230178 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/macos/Runner/Configs/AppInfo.xcconfig b/team_b/yappy/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 7ca93a44..00000000 --- a/team_b/yappy/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = yappy - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved. diff --git a/team_b/yappy/macos/Runner/Configs/Debug.xcconfig b/team_b/yappy/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd94..00000000 --- a/team_b/yappy/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/team_b/yappy/macos/Runner/Configs/Release.xcconfig b/team_b/yappy/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f495..00000000 --- a/team_b/yappy/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/team_b/yappy/macos/Runner/Configs/Warnings.xcconfig b/team_b/yappy/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf47..00000000 --- a/team_b/yappy/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/team_b/yappy/macos/Runner/DebugProfile.entitlements b/team_b/yappy/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index dddb8a30..00000000 --- a/team_b/yappy/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - - diff --git a/team_b/yappy/macos/Runner/Info.plist b/team_b/yappy/macos/Runner/Info.plist deleted file mode 100644 index 4789daa6..00000000 --- a/team_b/yappy/macos/Runner/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/team_b/yappy/macos/Runner/MainFlutterWindow.swift b/team_b/yappy/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb2..00000000 --- a/team_b/yappy/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/team_b/yappy/macos/Runner/Release.entitlements b/team_b/yappy/macos/Runner/Release.entitlements deleted file mode 100644 index 852fa1a4..00000000 --- a/team_b/yappy/macos/Runner/Release.entitlements +++ /dev/null @@ -1,8 +0,0 @@ - - - - - com.apple.security.app-sandbox - - - diff --git a/team_b/yappy/macos/RunnerTests/RunnerTests.swift b/team_b/yappy/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1f..00000000 --- a/team_b/yappy/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/team_b/yappy/pubspec.yaml b/team_b/yappy/pubspec.yaml deleted file mode 100644 index 4d1359e0..00000000 --- a/team_b/yappy/pubspec.yaml +++ /dev/null @@ -1,112 +0,0 @@ -name: yappy -description: "Yappy! is an application that allows you to store transcripts in different industry contexts." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+1 - -environment: - sdk: ^3.6.2 - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - - intl: ^0.17.0 - audio_waveforms: ^1.2.0 - cupertino_icons: ^1.0.8 - flutter_launcher_icons: ^0.14.3 - sqflite: ^2.4.1 - path: ^1.9.0 - path_provider: ^2.1.5 - envied: ^1.1.1 - sherpa_onnx: ^1.10.46 - record: ^5.2.1 - connectivity_plus: ^6.1.3 - shared_preferences: ^2.5.2 - share_plus: ^10.1.4 # Allows sharing with the phones default apps. - http: ^1.3.0 # For network requests - permission_handler: ^11.4.0 # For storage permissions - archive: ^4.0.4 # For BZ2 decompression - file_picker: ^9.0.2 - flutter_audio_waveforms: ^1.2.1+8 - dart_openai: ^5.1.0 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^5.0.0 - envied_generator: ^1.1.1 - build_runner: ^2.4.15 - mockito: ^5.0.16 - -flutter_icons: - android: true # For Android app icon - ios: true # For iOS app icon (optional, but recommended) - image_path: "assets/icon/app_icon.png" # Path to your PNG icon - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - assets: - - assets/icon/app_icon.png - - assets/yappy_database.db - - assets/models_config.json - - assets/ - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package diff --git a/team_b/yappy/test/audiowave_widget_test.dart b/team_b/yappy/test/audiowave_widget_test.dart deleted file mode 100644 index 86cfba10..00000000 --- a/team_b/yappy/test/audiowave_widget_test.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/services/speech_state.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - testWidgets('AudiowaveWidget displays correctly', - (WidgetTester tester) async { - // Mock SpeechState - final mockSpeechState = SpeechState(); - mockSpeechState.audioSamplesNotifier.value = - List.generate(100, (index) => (index % 2 == 0) ? 1000 : -1000); - - // Build the AudiowaveWidget widget. - await tester.pumpWidget(MaterialApp( - home: Scaffold( - body: AudiowaveWidget(speechState: mockSpeechState), - ), - )); - - // Allow the widget to fully build. - await tester.pumpAndSettle(); - - // Verify that the AudiowaveWidget is displayed. - expect(find.byType(AudiowaveWidget), findsOneWidget); - - // Verify that the CustomPaint widget is present. - expect(find.byType(CustomPaint), findsNWidgets(2)); - }); - - testWidgets('AudiowaveWidget updates with new audio samples', - (WidgetTester tester) async { - // Mock SpeechState - final mockSpeechState = SpeechState(); - mockSpeechState.audioSamplesNotifier.value = - List.generate(100, (index) => (index % 2 == 0) ? 1000 : -1000); - - // Build the AudiowaveWidget widget. - await tester.pumpWidget(MaterialApp( - home: Scaffold( - body: AudiowaveWidget(speechState: mockSpeechState), - ), - )); - - // Allow the widget to fully build. - await tester.pumpAndSettle(); - - // Update the audio samples. - mockSpeechState.audioSamplesNotifier.value = - List.generate(100, (index) => (index % 2 == 0) ? 2000 : -2000); - await tester.pumpAndSettle(); - - // Verify that the CustomPaint widget is updated. - expect(find.byType(CustomPaint), findsNWidgets(2)); - }); -} diff --git a/team_b/yappy/test/contact_page_test.dart b/team_b/yappy/test/contact_page_test.dart deleted file mode 100644 index c82f1c83..00000000 --- a/team_b/yappy/test/contact_page_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/contact_page.dart'; -import 'package:yappy/tool_bar.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('ContactPage should have a ToolBar and HamburgerDrawer', - (WidgetTester tester) async { - // Build the widget - await tester.pumpWidget(MaterialApp(home: ContactPage())); - - // Verify that ToolBar is in place - expect(find.byType(ToolBar), findsOneWidget, - reason: 'ToolBar should be visible'); - - // Find the Scaffold widget and trigger openDrawer() on its context - final scaffoldFinder = find.byType(Scaffold); - - // Use the `tester` to access the Scaffold and open the drawer directly - final scaffoldState = tester.state(scaffoldFinder); - scaffoldState.openDrawer(); // This explicitly opens the drawer - - await tester.pumpAndSettle(); // Wait for the drawer to open - - // Verify that the HamburgerDrawer is visible after opening - expect(find.byType(HamburgerDrawer), findsOneWidget, - reason: 'HamburgerDrawer should be available'); - }); - - testWidgets('Tapping the menu button should open the drawer', - (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: ContactPage())); - - // Drawer should not be visible initially - expect(find.byType(Drawer), findsNothing); - - // Tap the menu button (leading icon in AppBar) - await tester.tap(find.byIcon(Icons.menu)); - await tester.pumpAndSettle(); // Wait for animations - - // Drawer should be visible now - expect(find.byType(Drawer), findsOneWidget); - }); -} diff --git a/team_b/yappy/test/database_helper.mocks.dart b/team_b/yappy/test/database_helper.mocks.dart deleted file mode 100644 index 768fd8e1..00000000 --- a/team_b/yappy/test/database_helper.mocks.dart +++ /dev/null @@ -1,514 +0,0 @@ -// Mocks generated by Mockito 5.4.5 from annotations -// in yappy/test/database_helper.mocks.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; - -import 'package:mockito/mockito.dart' as _i1; -import 'package:sqflite/sqflite.dart' as _i2; -import 'package:yappy/services/database_helper.dart' as _i3; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class - -class _FakeDatabase_0 extends _i1.SmartFake implements _i2.Database { - _FakeDatabase_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -/// A class which mocks [DatabaseHelper]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockDatabaseHelper extends _i1.Mock implements _i3.DatabaseHelper { - MockDatabaseHelper() { - _i1.throwOnMissingStub(this); - } - - @override - _i4.Future<_i2.Database> get database => - (super.noSuchMethod( - Invocation.getter(#database), - returnValue: _i4.Future<_i2.Database>.value( - _FakeDatabase_0(this, Invocation.getter(#database)), - ), - ) - as _i4.Future<_i2.Database>); - - @override - _i4.Future>> getUsers() => - (super.noSuchMethod( - Invocation.method(#getUsers, []), - returnValue: _i4.Future>>.value( - >[], - ), - ) - as _i4.Future>>); - - @override - _i4.Future insertUser(Map? user) => - (super.noSuchMethod( - Invocation.method(#insertUser, [user]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateUser(Map? user) => - (super.noSuchMethod( - Invocation.method(#updateUser, [user]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteUser(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteUser, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertVehicle(Map? vehicle) => - (super.noSuchMethod( - Invocation.method(#insertVehicle, [vehicle]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateVehicle(Map? vehicle) => - (super.noSuchMethod( - Invocation.method(#updateVehicle, [vehicle]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteVehicle(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteVehicle, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertVehicleMaintenance(Map? maintenance) => - (super.noSuchMethod( - Invocation.method(#insertVehicleMaintenance, [maintenance]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateVehicleMaintenance(Map? maintenance) => - (super.noSuchMethod( - Invocation.method(#updateVehicleMaintenance, [maintenance]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteVehicleMaintenance(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteVehicleMaintenance, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertTranscript(Map? transcript) => - (super.noSuchMethod( - Invocation.method(#insertTranscript, [transcript]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateTranscript(Map? transcript) => - (super.noSuchMethod( - Invocation.method(#updateTranscript, [transcript]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteTranscript(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteTranscript, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future>> getAllTranscripts() => - (super.noSuchMethod( - Invocation.method(#getAllTranscripts, []), - returnValue: _i4.Future>>.value( - >[], - ), - ) - as _i4.Future>>); - - @override - _i4.Future?> getTranscriptById(int? transcriptId) => - (super.noSuchMethod( - Invocation.method(#getTranscriptById, [transcriptId]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future insertOrder(Map? order) => - (super.noSuchMethod( - Invocation.method(#insertOrder, [order]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateOrder(Map? order) => - (super.noSuchMethod( - Invocation.method(#updateOrder, [order]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteOrder(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteOrder, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertOrderItem(Map? orderItem) => - (super.noSuchMethod( - Invocation.method(#insertOrderItem, [orderItem]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateOrderItem(Map? orderItem) => - (super.noSuchMethod( - Invocation.method(#updateOrderItem, [orderItem]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteOrderItem(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteOrderItem, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future>> getMenuItems() => - (super.noSuchMethod( - Invocation.method(#getMenuItems, []), - returnValue: _i4.Future>>.value( - >[], - ), - ) - as _i4.Future>>); - - @override - _i4.Future insertMenuItem(Map? menuItem) => - (super.noSuchMethod( - Invocation.method(#insertMenuItem, [menuItem]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateMenuItem(Map? menuItem) => - (super.noSuchMethod( - Invocation.method(#updateMenuItem, [menuItem]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteMenuItem(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteMenuItem, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertSpecialRequest(Map? specialRequest) => - (super.noSuchMethod( - Invocation.method(#insertSpecialRequest, [specialRequest]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateSpecialRequest(Map? specialRequest) => - (super.noSuchMethod( - Invocation.method(#updateSpecialRequest, [specialRequest]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteSpecialRequest(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteSpecialRequest, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future>> getDoctorVisits() => - (super.noSuchMethod( - Invocation.method(#getDoctorVisits, []), - returnValue: _i4.Future>>.value( - >[], - ), - ) - as _i4.Future>>); - - @override - _i4.Future insertDoctorVisit(Map? doctorVisit) => - (super.noSuchMethod( - Invocation.method(#insertDoctorVisit, [doctorVisit]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateDoctorVisit(Map? doctorVisit) => - (super.noSuchMethod( - Invocation.method(#updateDoctorVisit, [doctorVisit]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deleteDoctorVisit(int? id) => - (super.noSuchMethod( - Invocation.method(#deleteDoctorVisit, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future insertPatient(Map? patient) => - (super.noSuchMethod( - Invocation.method(#insertPatient, [patient]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updatePatient(Map? patient) => - (super.noSuchMethod( - Invocation.method(#updatePatient, [patient]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future deletePatient(int? id) => - (super.noSuchMethod( - Invocation.method(#deletePatient, [id]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future?> getDoctorVisitById(int? visitId) => - (super.noSuchMethod( - Invocation.method(#getDoctorVisitById, [visitId]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future>> getDoctorVisitsByPatientId( - int? patientId, - ) => - (super.noSuchMethod( - Invocation.method(#getDoctorVisitsByPatientId, [patientId]), - returnValue: _i4.Future>>.value( - >[], - ), - ) - as _i4.Future>>); - - @override - _i4.Future?> getVehicleMaintenanceById( - int? maintenanceId, - ) => - (super.noSuchMethod( - Invocation.method(#getVehicleMaintenanceById, [maintenanceId]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future?> getVehicleById(int? vehicleId) => - (super.noSuchMethod( - Invocation.method(#getVehicleById, [vehicleId]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future> getVehicleIdsByUserId(int? userId) => - (super.noSuchMethod( - Invocation.method(#getVehicleIdsByUserId, [userId]), - returnValue: _i4.Future>.value([]), - ) - as _i4.Future>); - - @override - _i4.Future> getTranscriptIdsByUserId(int? userId) => - (super.noSuchMethod( - Invocation.method(#getTranscriptIdsByUserId, [userId]), - returnValue: _i4.Future>.value([]), - ) - as _i4.Future>); - - @override - _i4.Future> getMaintenanceIdsByUserId(int? userId) => - (super.noSuchMethod( - Invocation.method(#getMaintenanceIdsByUserId, [userId]), - returnValue: _i4.Future>.value([]), - ) - as _i4.Future>); - - @override - _i4.Future> getItemIdsByOrderId(int? orderId) => - (super.noSuchMethod( - Invocation.method(#getItemIdsByOrderId, [orderId]), - returnValue: _i4.Future>.value([]), - ) - as _i4.Future>); - - @override - dynamic saveTranscript({ - required int? userId, - required int? transcriptId, - required String? text, - required String? industry, - }) => super.noSuchMethod( - Invocation.method(#saveTranscript, [], { - #userId: userId, - #transcriptId: transcriptId, - #text: text, - #industry: industry, - }), - ); - - @override - dynamic saveTranscriptAiResponse({ - required int? userId, - required int? transcriptId, - required String? text, - required String? aiResponse, - required String? industry, - }) => super.noSuchMethod( - Invocation.method(#saveTranscriptAiResponse, [], { - #userId: userId, - #transcriptId: transcriptId, - #text: text, - #aiResponse: aiResponse, - #industry: industry, - }), - ); - - @override - _i4.Future> searchTranscripts(String? query, String? industry) => - (super.noSuchMethod( - Invocation.method(#searchTranscripts, [query, industry]), - returnValue: _i4.Future>.value([]), - ) - as _i4.Future>); - - @override - _i4.Future?> getTranscriptDetails(String? entry) => - (super.noSuchMethod( - Invocation.method(#getTranscriptDetails, [entry]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future insertDocument( - int? transcriptId, - String? fileName, - List? fileBytes, - ) => - (super.noSuchMethod( - Invocation.method(#insertDocument, [ - transcriptId, - fileName, - fileBytes, - ]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future?> getTranscriptTextDataAndIndustryById( - int? transcriptId, - ) => - (super.noSuchMethod( - Invocation.method(#getTranscriptTextDataAndIndustryById, [ - transcriptId, - ]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future?> getDocumentAndIndustryById( - int? transcriptId, - ) => - (super.noSuchMethod( - Invocation.method(#getDocumentAndIndustryById, [transcriptId]), - returnValue: _i4.Future?>.value(), - ) - as _i4.Future?>); - - @override - _i4.Future insertAiResponse(int? transcriptId, String? aiResponse) => - (super.noSuchMethod( - Invocation.method(#insertAiResponse, [transcriptId, aiResponse]), - returnValue: _i4.Future.value(0), - ) - as _i4.Future); - - @override - _i4.Future updateTranscriptDocument( - int? transcriptId, - List? documentBytes, - ) => - (super.noSuchMethod( - Invocation.method(#updateTranscriptDocument, [ - transcriptId, - documentBytes, - ]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); -} diff --git a/team_b/yappy/test/database_helper_test.dart b/team_b/yappy/test/database_helper_test.dart deleted file mode 100644 index c1530336..00000000 --- a/team_b/yappy/test/database_helper_test.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; -import 'database_helper.mocks.dart'; - -void main() { - late MockDatabaseHelper mockDataHelper; - - setUp(() { - mockDataHelper = MockDatabaseHelper(); - }); - - group('DatabaseHelper Tests', () { - test('should get transcript text data and industry by ID', () async { - int transcriptId = 1; - Map mockTranscriptData = { - 'transcript_text_data': 'Sample text', - 'industry': 'Sample industry', - }; - - when(mockDataHelper.getTranscriptTextDataAndIndustryById(transcriptId)) - .thenAnswer((_) async => mockTranscriptData); - - final transcriptData = await mockDataHelper.getTranscriptTextDataAndIndustryById(transcriptId); - expect(transcriptData, isNotNull); - expect(transcriptData!['transcript_text_data'], 'Sample text'); - expect(transcriptData['industry'], 'Sample industry'); - }); - - test('should update transcript document', () async { - int transcriptId = 1; - List documentBytes = [1, 2, 3, 4, 5]; - - when(mockDataHelper.updateTranscriptDocument(transcriptId, documentBytes)) - .thenAnswer((_) async => true); - - final result = await mockDataHelper.updateTranscriptDocument(transcriptId, documentBytes); - expect(result, true); - }); - - test('should get transcript by ID', () async { - int transcriptId = 1; - Map mockTranscript = { - 'transcript_id': transcriptId, - 'transcript_text_data': 'Sample text', - 'industry': 'Sample industry', - }; - - when(mockDataHelper.getTranscriptById(transcriptId)) - .thenAnswer((_) async => mockTranscript); - - final transcript = await mockDataHelper.getTranscriptById(transcriptId); - expect(transcript, isNotNull); - expect(transcript!['transcript_id'], transcriptId); - }); - - test('should insert AI response', () async { - int transcriptId = 1; - String aiResponse = 'This is an AI response'; - - when(mockDataHelper.insertAiResponse(transcriptId, aiResponse)) - .thenAnswer((_) async => 1); - - final result = await mockDataHelper.insertAiResponse(transcriptId, aiResponse); - expect(result, 1); - }); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/file_handler_test.dart b/team_b/yappy/test/file_handler_test.dart deleted file mode 100644 index f2a7d42e..00000000 --- a/team_b/yappy/test/file_handler_test.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; -import 'package:yappy/services/file_handler.dart'; -import 'dart:io'; -import 'package:flutter/services.dart'; -import 'database_helper.mocks.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - late MockDatabaseHelper mockDbHelper; - late FileHandler fileHandler; - const MethodChannel pathProviderChannel = MethodChannel('plugins.flutter.io/path_provider'); - // I have to cache the temp directory path as multiple calls - // to getApplicationDocumentsDirectory() return different paths - late String tempDirectoryPath; - - setUpAll(() async { - // Register the path_provider plugin - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - pathProviderChannel, - (MethodCall methodCall) async { - if (methodCall.method == 'getApplicationDocumentsDirectory') { - final directory = Directory.systemTemp.createTempSync(); - tempDirectoryPath = directory.path; - return tempDirectoryPath; - } - return null; - } - ); - - // Initialize the database - mockDbHelper = MockDatabaseHelper(); - fileHandler = FileHandler(); - }); - - group('FileHandler', () { - setUp(() { - mockDbHelper = MockDatabaseHelper(); - fileHandler = FileHandler(); - }); - - test('should save transcript text data to local storage', () async { - int transcriptId = 1; // Assuming transcriptId 1 exists in the database with test data - Map mockTranscriptData = { - 'transcript_text_data': 'Sample text', - 'industry': 'Sample industry', - }; - - when(mockDbHelper.getTranscriptTextDataAndIndustryById(transcriptId)) - .thenAnswer((_) async => mockTranscriptData); - - await fileHandler.saveTranscriptTextToLocal(mockDbHelper, transcriptId); - final directory = tempDirectoryPath; - final fileName = 'transcript_text_${transcriptId}_Sample industry.txt'; - final file = File('$directory/$fileName'); - - expect(await file.exists(), isTrue); - }); - - test('should move file from local storage to database', () async { - int transcriptId = 1; // Assuming transcriptId 1 exists in the database with test data - final fileName = 'transcript_text_${transcriptId}_Vehicle Maintenance.txt'; - final directory = await fileHandler.localStoragePath; - final file = File('$directory/$fileName'); - - // Setup: Create the file in local storage - await file.writeAsString('Test content for transcript text'); - - if (await file.exists()) { - final fileBytes = await file.readAsBytes(); - when(mockDbHelper.updateTranscriptDocument(transcriptId, fileBytes)) - .thenAnswer((_) async => true); - when(mockDbHelper.getTranscriptById(transcriptId)) - .thenAnswer((_) async => { - 'transcript_id': transcriptId, - 'transcript_document': fileBytes, - }); - - await mockDbHelper.updateTranscriptDocument(transcriptId, fileBytes); - - final transcript = await mockDbHelper.getTranscriptById(transcriptId); - expect(transcript, isNotNull); - expect(transcript!['transcript_document'], fileBytes); - } else { - fail('File not found in local storage: $fileName'); - } - }); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/help_test.dart b/team_b/yappy/test/help_test.dart deleted file mode 100644 index 58e3907b..00000000 --- a/team_b/yappy/test/help_test.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/help.dart'; -import 'package:yappy/tutorial_page.dart'; - -void main() { - group('HelpApp Widget Tests', () { - testWidgets('HelpApp renders HelpPage as the home screen', - (WidgetTester tester) async { - await tester.pumpWidget(const HelpApp()); - - expect(find.byType(HelpPage), findsOneWidget); - }); - }); - - group('HelpPage Widget Tests', () { - testWidgets('HelpPage has the correct background color', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - final scaffold = tester.widget(find.byType(Scaffold)); - expect(scaffold.backgroundColor, const Color.fromARGB(255, 0, 0, 0)); - }); - - testWidgets('HelpPage displays the "Lets Yap about Yappy" title', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - expect(find.text('Lets Yap about Yappy'), findsOneWidget); - }); - - testWidgets('HelpPage displays the welcome message', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - expect( - find.text( - 'Welcome to Yappy! If this is your first time and need help with using Yappy, please select the button below.', - ), - findsOneWidget, - ); - }); - - testWidgets( - 'HelpPage displays "It\'s my first time" button and navigates to TutorialPage', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - expect(find.text('It\'s my first time'), findsOneWidget); - - await tester.tap(find.text('It\'s my first time')); - await tester.pumpAndSettle(); - - expect(find.byType(TutorialPage), findsOneWidget); - }); - - testWidgets( - 'HelpPage displays "Report a problem" button and shows alert dialog', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - expect(find.text('Report a problem'), findsOneWidget); - - await tester.tap(find.text('Report a problem')); - await tester.pump(); - - expect(find.text('Report a Problem'), findsOneWidget); - expect(find.text('Please call: +1-800-123-4567'), findsOneWidget); - }); - - testWidgets( - 'HelpPage displays "Feedback for the Help Center" button and shows alert dialog', - (WidgetTester tester) async { - await tester.pumpWidget( - const MaterialApp( - home: HelpPage(), - ), - ); - - expect(find.text('Feedback for the Help Center'), findsOneWidget); - - await tester.tap(find.text('Feedback for the Help Center')); - await tester.pump(); - - expect(find.text('Feedback for the Help Center'), findsNWidgets(2)); - }); - }); -} diff --git a/team_b/yappy/test/home_page_test.dart b/team_b/yappy/test/home_page_test.dart deleted file mode 100644 index 2d7fe19a..00000000 --- a/team_b/yappy/test/home_page_test.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/home_page.dart'; -import 'package:yappy/tutorial_page.dart'; - -import 'package:shared_preferences/shared_preferences.dart'; - -void main() { - group('HomePage Tests', () { - testWidgets('displays all buttons on the HomePage', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: HomePage())); - - // Assert - expect(find.text('Restaurant'), findsOneWidget); - expect(find.text('Vehicle Maintenance'), findsOneWidget); - expect(find.text('Medical Doctor'), findsOneWidget); - expect(find.text('Medical Patient'), findsOneWidget); - expect(find.text('Help'), findsOneWidget); - expect(find.text('Contact'), findsOneWidget); - expect(find.text('Settings'), findsOneWidget); - }); - - testWidgets('navigates to TutorialPage on first-time user dialog "Yes"', - (WidgetTester tester) async { - // Arrange - SharedPreferences.setMockInitialValues({'isFirstTime': true}); - await tester.pumpWidget(MaterialApp(home: HomePage())); - - // Act - await tester.tap(find.text('Yes')); - await tester.pumpAndSettle(); - - // Assert - expect(find.byType(TutorialPage), findsOneWidget); - }); - - testWidgets( - 'does not show first-time user dialog if "isFirstTime" is false', - (WidgetTester tester) async { - // Arrange - SharedPreferences.setMockInitialValues({'isFirstTime': false}); - await tester.pumpWidget(MaterialApp(home: HomePage())); - - // Assert - expect(find.text('Welcome!'), findsNothing); - }); - }); -} diff --git a/team_b/yappy/test/login_page_test.dart b/team_b/yappy/test/login_page_test.dart deleted file mode 100644 index 7b52fde1..00000000 --- a/team_b/yappy/test/login_page_test.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/login_page.dart'; -import 'package:yappy/sign_up_page.dart'; - -void main() { - group('LoginPage Tests', () { - testWidgets('renders all widgets properly', (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: LoginPage())); - - // Assert - expect(find.byType(CircleAvatar), findsOneWidget); - expect(find.text('Login'), findsOneWidget); - expect(find.text('Submit'), findsOneWidget); - expect(find.text('Sign-up'), findsOneWidget); - expect(find.text('Terms and Conditions'), findsOneWidget); - }); - - testWidgets('navigates to SignUpPage when "Sign-up" button is pressed', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: LoginPage())); - - // Act - await tester.tap(find.text('Sign-up')); - await tester.pumpAndSettle(); - - // Assert - expect(find.byType(SignUpPage), findsOneWidget); - }); - - testWidgets('ensures TextFields update with input', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: LoginPage())); - - // Act - await tester.enterText( - find.widgetWithText(TextField, 'Username'), 'testuser'); - await tester.enterText( - find.widgetWithText(TextField, 'Password'), 'password123'); - - // Assert - final usernameField = find.widgetWithText(TextField, 'Username'); - final passwordField = find.widgetWithText(TextField, 'Password'); - - expect((tester.widget(usernameField) as TextField).controller?.text, - 'testuser'); - expect((tester.widget(passwordField) as TextField).controller?.text, - 'password123'); - }); - }); -} diff --git a/team_b/yappy/test/main_test.dart b/team_b/yappy/test/main_test.dart deleted file mode 100644 index b4329ed9..00000000 --- a/team_b/yappy/test/main_test.dart +++ /dev/null @@ -1,77 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:yappy/main.dart'; -import 'package:yappy/home_page.dart'; - -void main() { - group('Main Tests', () { - testWidgets('renders MyApp and HomePage correctly', - (WidgetTester tester) async { - // Arrange - SharedPreferences.setMockInitialValues({}); // Mock shared preferences - await tester.pumpWidget(const MyApp()); - - // Assert - expect(find.byType(MyApp), findsOneWidget); - expect(find.byType(HomePage), findsOneWidget); - }); - - testWidgets('displays API key alert dialog when API key is empty', - (WidgetTester tester) async { - // Arrange - SharedPreferences.setMockInitialValues({'openai_api_key': ''}); - final navigatorKey = GlobalKey(); - - await tester.pumpWidget( - MaterialApp( - navigatorKey: navigatorKey, - home: Builder(builder: (context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( - context: navigatorKey.currentContext!, - builder: (BuildContext context) { - return AlertDialog( - title: Text('OpenAI API Key Required'), - content: Text( - 'Please add a valid OpenAI API key via the Settings menu.'), - actions: [ - TextButton( - child: Text('OK'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - }); - return Container(); - }), - ), - ); - - // Act - await tester.pumpAndSettle(); - - // Assert - expect(find.text('OpenAI API Key Required'), findsOneWidget); - expect( - find.text('Please add a valid OpenAI API key via the Settings menu.'), - findsOneWidget); - }); - - test('checks API key is saved in shared preferences', () async { - // Arrange - SharedPreferences.setMockInitialValues({}); - final preferences = await SharedPreferences.getInstance(); - - // Act - preferences.setString('openai_api_key', 'test_api_key'); - - // Assert - expect(preferences.getString('openai_api_key'), 'test_api_key'); - }); - }); -} diff --git a/team_b/yappy/test/mechanic_test.dart b/team_b/yappy/test/mechanic_test.dart deleted file mode 100644 index 03f424d4..00000000 --- a/team_b/yappy/test/mechanic_test.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/mechanic.dart'; -import 'package:yappy/search_bar_widget.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/transcription_box.dart'; - -void main() { - testWidgets('MechanicalAidApp should have a MechanicalAidPage', (WidgetTester tester) async { - await tester.pumpWidget(const MechanicalAidApp()); - - expect(find.byType(MechanicalAidPage), findsOneWidget); - }); - - testWidgets('MechanicalAidPage should have a ToolBar', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MechanicalAidPage())); - - expect(find.byType(ToolBar), findsOneWidget); - }); - - testWidgets('MechanicalAidPage should have a SearchBarWidget and IndustryMenu', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MechanicalAidPage())); - - expect(find.byType(SearchBarWidget), findsOneWidget); - expect(find.byType(IndustryMenu), findsOneWidget); - }); - - testWidgets('MechanicalAidPage should have AudiowaveWidget and TranscriptionBox', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MechanicalAidPage())); - - expect(find.byType(AudiowaveWidget), findsOneWidget); - expect(find.byType(TranscriptionBox), findsOneWidget); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/medical_doctor.dart b/team_b/yappy/test/medical_doctor.dart deleted file mode 100644 index 2ddf87cf..00000000 --- a/team_b/yappy/test/medical_doctor.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/medical_doctor.dart'; -import 'package:yappy/search_bar_widget.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/transcription_box.dart'; - -void main() { - testWidgets('MedicalDoctorApp should have a MedicalDoctorPage', (WidgetTester tester) async { - await tester.pumpWidget(const MedicalDoctorApp()); - - expect(find.byType(MedicalDoctorPage), findsOneWidget); - }); - - testWidgets('MedicalDoctorPage should have a ToolBar', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalDoctorPage())); - - expect(find.byType(ToolBar), findsOneWidget); - }); - - testWidgets('MedicalDoctorPage should have a SearchBarWidget and IndustryMenu', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalDoctorPage())); - - expect(find.byType(SearchBarWidget), findsOneWidget); - expect(find.byType(IndustryMenu), findsOneWidget); - }); - - testWidgets('MedicalDoctorPage should have AudiowaveWidget and TranscriptionBox', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalDoctorPage())); - - expect(find.byType(AudiowaveWidget), findsOneWidget); - expect(find.byType(TranscriptionBox), findsOneWidget); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/medical_doctor_test.dart b/team_b/yappy/test/medical_doctor_test.dart deleted file mode 100644 index 53eef6c8..00000000 --- a/team_b/yappy/test/medical_doctor_test.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/medical_doctor.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/transcription_box.dart'; -import 'package:yappy/audiowave_widget.dart'; - -void main() { - group('MedicalDoctorPage Tests', () { - testWidgets('renders MedicalDoctorApp and MedicalDoctorPage correctly', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(const MedicalDoctorApp()); - - // Assert - expect(find.byType(MedicalDoctorApp), findsOneWidget); - expect(find.byType(MedicalDoctorPage), findsOneWidget); - }); - - testWidgets('renders IndustryMenu with correct title and icon', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: MedicalDoctorPage())); - - // Act - await tester.pumpAndSettle(); - - // Assert - expect(find.byType(IndustryMenu), findsOneWidget); - expect( - find.widgetWithText(IndustryMenu, 'Medical Doctor'), findsOneWidget); - expect(find.byIcon(Icons.medical_services), findsOneWidget); - }); - - testWidgets('renders AudiowaveWidget and TranscriptionBox', - (WidgetTester tester) async { - // Arrange - await tester.pumpWidget(MaterialApp(home: MedicalDoctorPage())); - - // Act - await tester.pumpAndSettle(); - - // Assert - expect(find.byType(AudiowaveWidget), findsOneWidget); - expect(find.byType(TranscriptionBox), findsOneWidget); - }); - }); -} diff --git a/team_b/yappy/test/medical_patient_test.dart b/team_b/yappy/test/medical_patient_test.dart deleted file mode 100644 index 24d32b77..00000000 --- a/team_b/yappy/test/medical_patient_test.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/medical_patient.dart'; -import 'package:yappy/search_bar_widget.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/transcription_box.dart'; - -void main() { - testWidgets('MedicalPatientApp should have a MedicalPatientPage', (WidgetTester tester) async { - await tester.pumpWidget(const MedicalPatientApp()); - - expect(find.byType(MedicalPatientPage), findsOneWidget); - }); - - testWidgets('MedicalPatientPage should have a ToolBar', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalPatientPage())); - - expect(find.byType(ToolBar), findsOneWidget); - }); - - testWidgets('MedicalPatientPage should have a SearchBarWidget and IndustryMenu', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalPatientPage())); - - expect(find.byType(SearchBarWidget), findsOneWidget); - expect(find.byType(IndustryMenu), findsOneWidget); - }); - - testWidgets('MedicalPatientPage should have AudiowaveWidget and TranscriptionBox', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: MedicalPatientPage())); - - expect(find.byType(AudiowaveWidget), findsOneWidget); - expect(find.byType(TranscriptionBox), findsOneWidget); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/restaurant_test.dart b/team_b/yappy/test/restaurant_test.dart deleted file mode 100644 index c5a1b527..00000000 --- a/team_b/yappy/test/restaurant_test.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/restaurant.dart'; -import 'package:yappy/search_bar_widget.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/transcription_box.dart'; - -void main() { - testWidgets('RestaurantApp should have a RestaurantPage', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: RestaurantPage())); - - expect(find.byType(RestaurantPage), findsOneWidget); - }); - - testWidgets('RestaurantPage should have a ToolBar', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: RestaurantPage())); - - expect(find.byType(ToolBar), findsOneWidget); - }); - - testWidgets('RestaurantPage should have a SearchBarWidget and IndustryMenu', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: RestaurantPage())); - - expect(find.byType(SearchBarWidget), findsOneWidget); - expect(find.byType(IndustryMenu), findsOneWidget); - }); - - testWidgets('RestaurantPage should have AudiowaveWidget and TranscriptionBox', (WidgetTester tester) async { - await tester.pumpWidget(MaterialApp(home: RestaurantPage())); - - expect(find.byType(AudiowaveWidget), findsOneWidget); - expect(find.byType(TranscriptionBox), findsOneWidget); - }); -} \ No newline at end of file diff --git a/team_b/yappy/test/sign_up_page_test.dart b/team_b/yappy/test/sign_up_page_test.dart deleted file mode 100644 index ace17bb0..00000000 --- a/team_b/yappy/test/sign_up_page_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/material.dart'; -import 'package:yappy/sign_up_page.dart'; - -void main() { - group('SignUpPage Tests', () { - testWidgets('Should display all required fields', - (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Verify presence of username, password, and re-enter password fields - expect(find.byType(TextField), findsNWidgets(3)); - expect(find.text('Username'), findsOneWidget); - expect(find.text('Password'), findsOneWidget); - expect(find.text('Re-Enter Password'), findsOneWidget); - }); - - testWidgets('Should display Sign-Up button', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Verify presence of Sign-Up button - expect(find.text('Sign-Up'), findsOneWidget); - expect(find.byType(ElevatedButton), findsWidgets); - }); - - testWidgets('Should display disclaimer text', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Verify disclaimer text is present - expect( - find.text( - 'Yappy! Is not responsible for any legal consequences due to the use of this application', - ), - findsOneWidget, - ); - }); - - testWidgets('Should input text into username field', - (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Input text into username field - final usernameField = find.widgetWithText(TextField, 'Username'); - await tester.enterText(usernameField, 'testuser'); - - // Verify text is entered - expect(find.text('testuser'), findsOneWidget); - }); - - testWidgets('Should input text into password field', - (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Input text into password field - final passwordField = find.widgetWithText(TextField, 'Password'); - await tester.enterText(passwordField, 'password123'); - - // Verify text is entered - expect(find.text('password123'), findsOneWidget); - }); - - testWidgets('Should input text into re-enter password field', - (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Input text into re-enter password field - final reenterPasswordField = - find.widgetWithText(TextField, 'Re-Enter Password'); - await tester.enterText(reenterPasswordField, 'password123'); - - // Verify text is entered - expect(find.text('password123'), findsOneWidget); - }); - - testWidgets('Submit button is functional', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: SignUpPage())); - - // Find and tap the Submit button - final submitButton = find.widgetWithText(ElevatedButton, 'Submit'); - await tester.tap(submitButton); - - // Verify button press - expect(find.widgetWithText(ElevatedButton, 'Submit'), findsOneWidget); - }); - }); -} diff --git a/team_b/yappy/test/transcription_box_test.dart b/team_b/yappy/test/transcription_box_test.dart deleted file mode 100644 index e655d4de..00000000 --- a/team_b/yappy/test/transcription_box_test.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/material.dart'; -import 'package:yappy/transcription_box.dart'; - -void main() { - group('TranscriptionBox Tests', () { - late TextEditingController textEditingController; - - setUp(() { - textEditingController = TextEditingController(); - }); - - testWidgets('Should display the transcription box', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: TranscriptionBox(controller: textEditingController), - ), - ), - ); - - // Verify the transcription box is displayed - expect(find.byType(TextField), findsOneWidget); - expect(find.text('Transcription will appear here...'), findsOneWidget); - }); - - testWidgets('Should update text in transcription box', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: TranscriptionBox(controller: textEditingController), - ), - ), - ); - - // Set text in the controller - textEditingController.text = 'Sample transcription text'; - await tester.pumpAndSettle(); - - // Verify the text is displayed - expect(find.text('Sample transcription text'), findsOneWidget); - }); - - testWidgets('Should display scroll bar when content overflows', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: TranscriptionBox(controller: textEditingController), - ), - ), - ); - - // Add long text to simulate overflow - textEditingController.text = 'Line 1\n' * 50; - await tester.pumpAndSettle(); - - // Verify scroll bar is visible - expect(find.byType(Scrollbar), findsOneWidget); - }); - }); -} diff --git a/team_b/yappy/test/tutorial_page_test.dart b/team_b/yappy/test/tutorial_page_test.dart deleted file mode 100644 index af142a20..00000000 --- a/team_b/yappy/test/tutorial_page_test.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/material.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/transcription_box.dart'; -import 'package:yappy/tutorial_page.dart'; -import 'package:yappy/home_page.dart'; - -void main() { - group('TutorialPage Tests', () { - testWidgets('Should display ToolBar and Drawer', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: TutorialPage(), - ), - ); - - // Verify ToolBar is displayed - expect(find.byType(ToolBar), findsOneWidget); - - // Verify HamburgerDrawer is present - final hamburgerIcon = find.byIcon(Icons.menu); - await tester.tap(hamburgerIcon); - await tester.pumpAndSettle(); - expect(find.byType(Drawer), findsOneWidget); - }); - - testWidgets('Should show first tutorial popup on load', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: TutorialPage(), - ), - ); - - // Wait for post-frame callback to execute - await tester.pumpAndSettle(); - - // Verify first popup is shown - expect( - find.text( - "The button of the left is the Record button that allows you to record conversations and get a transcript in return."), - findsOneWidget, - ); - }); - - testWidgets('Should navigate through tutorial popups', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: TutorialPage(), - ), - ); - - // Wait for first popup - await tester.pumpAndSettle(); - expect( - find.text( - "The button of the left is the Record button that allows you to record conversations and get a transcript in return."), - findsOneWidget); - - // Tap Next on first popup - await tester.tap(find.text("Next")); - await tester.pumpAndSettle(); - expect( - find.text( - "The second button will show you the days transcripts with broken down into details."), - findsOneWidget); - - // Tap Next on second popup - await tester.tap(find.text("Next")); - await tester.pumpAndSettle(); - expect( - find.text( - "The third button will show you all transcripts and allow you to search, share, upload, download, and delete."), - findsOneWidget); - - // Tap Next on third popup - await tester.tap(find.text("Next")); - await tester.pumpAndSettle(); - expect( - find.text( - "The fourth button will bring you to a chatbot that can search your transcripts to provide you information."), - findsOneWidget); - - // Tap Finish on fourth popup - await tester.tap(find.text("Finish")); - await tester.pumpAndSettle(); - - // Verify navigation to HomePage - expect(find.byType(HomePage), findsOneWidget); - }); - - testWidgets('Should display IndustryMenu and TranscriptionBox', - (WidgetTester tester) async { - await tester.pumpWidget( - MaterialApp( - home: TutorialPage(), - ), - ); - - // Verify IndustryMenu is displayed - expect(find.byType(IndustryMenu), findsOneWidget); - - // Verify TranscriptionBox is displayed - expect(find.byType(TranscriptionBox), findsOneWidget); - }); - }); -} diff --git a/team_b/yappy/web/favicon.png b/team_b/yappy/web/favicon.png deleted file mode 100644 index 8aaa46ac1ae21512746f852a42ba87e4165dfdd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM diff --git a/team_b/yappy/web/icons/Icon-192.png b/team_b/yappy/web/icons/Icon-192.png deleted file mode 100644 index b749bfef07473333cf1dd31e9eed89862a5d52aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5292 zcmZ`-2T+sGz6~)*FVZ`aW+(v>MIm&M-g^@e2u-B-DoB?qO+b1Tq<5uCCv>ESfRum& zp%X;f!~1{tzL__3=gjVJ=j=J>+nMj%ncXj1Q(b|Ckbw{Y0FWpt%4y%$uD=Z*c-x~o zE;IoE;xa#7Ll5nj-e4CuXB&G*IM~D21rCP$*xLXAK8rIMCSHuSu%bL&S3)8YI~vyp@KBu9Ph7R_pvKQ@xv>NQ`dZp(u{Z8K3yOB zn7-AR+d2JkW)KiGx0hosml;+eCXp6+w%@STjFY*CJ?udJ64&{BCbuebcuH;}(($@@ znNlgBA@ZXB)mcl9nbX#F!f_5Z=W>0kh|UVWnf!At4V*LQP%*gPdCXd6P@J4Td;!Ur z<2ZLmwr(NG`u#gDEMP19UcSzRTL@HsK+PnIXbVBT@oHm53DZr?~V(0{rsalAfwgo zEh=GviaqkF;}F_5-yA!1u3!gxaR&Mj)hLuj5Q-N-@Lra{%<4ONja8pycD90&>yMB` zchhd>0CsH`^|&TstH-8+R`CfoWqmTTF_0?zDOY`E`b)cVi!$4xA@oO;SyOjJyP^_j zx^@Gdf+w|FW@DMdOi8=4+LJl$#@R&&=UM`)G!y%6ZzQLoSL%*KE8IO0~&5XYR9 z&N)?goEiWA(YoRfT{06&D6Yuu@Qt&XVbuW@COb;>SP9~aRc+z`m`80pB2o%`#{xD@ zI3RAlukL5L>px6b?QW1Ac_0>ew%NM!XB2(H+1Y3AJC?C?O`GGs`331Nd4ZvG~bMo{lh~GeL zSL|tT*fF-HXxXYtfu5z+T5Mx9OdP7J4g%@oeC2FaWO1D{=NvL|DNZ}GO?O3`+H*SI z=grGv=7dL{+oY0eJFGO!Qe(e2F?CHW(i!!XkGo2tUvsQ)I9ev`H&=;`N%Z{L zO?vV%rDv$y(@1Yj@xfr7Kzr<~0{^T8wM80xf7IGQF_S-2c0)0D6b0~yD7BsCy+(zL z#N~%&e4iAwi4F$&dI7x6cE|B{f@lY5epaDh=2-(4N05VO~A zQT3hanGy_&p+7Fb^I#ewGsjyCEUmSCaP6JDB*=_()FgQ(-pZ28-{qx~2foO4%pM9e z*_63RT8XjgiaWY|*xydf;8MKLd{HnfZ2kM%iq}fstImB-K6A79B~YoPVa@tYN@T_$ zea+9)<%?=Fl!kd(Y!G(-o}ko28hg2!MR-o5BEa_72uj7Mrc&{lRh3u2%Y=Xk9^-qa zBPWaD=2qcuJ&@Tf6ue&)4_V*45=zWk@Z}Q?f5)*z)-+E|-yC4fs5CE6L_PH3=zI8p z*Z3!it{1e5_^(sF*v=0{`U9C741&lub89gdhKp|Y8CeC{_{wYK-LSbp{h)b~9^j!s z7e?Y{Z3pZv0J)(VL=g>l;<}xk=T*O5YR|hg0eg4u98f2IrA-MY+StQIuK-(*J6TRR z|IM(%uI~?`wsfyO6Tgmsy1b3a)j6M&-jgUjVg+mP*oTKdHg?5E`!r`7AE_#?Fc)&a z08KCq>Gc=ne{PCbRvs6gVW|tKdcE1#7C4e`M|j$C5EYZ~Y=jUtc zj`+?p4ba3uy7><7wIokM79jPza``{Lx0)zGWg;FW1^NKY+GpEi=rHJ+fVRGfXO zPHV52k?jxei_!YYAw1HIz}y8ZMwdZqU%ESwMn7~t zdI5%B;U7RF=jzRz^NuY9nM)&<%M>x>0(e$GpU9th%rHiZsIT>_qp%V~ILlyt^V`=d z!1+DX@ah?RnB$X!0xpTA0}lN@9V-ePx>wQ?-xrJr^qDlw?#O(RsXeAvM%}rg0NT#t z!CsT;-vB=B87ShG`GwO;OEbeL;a}LIu=&@9cb~Rsx(ZPNQ!NT7H{@j0e(DiLea>QD zPmpe90gEKHEZ8oQ@6%E7k-Ptn#z)b9NbD@_GTxEhbS+}Bb74WUaRy{w;E|MgDAvHw zL)ycgM7mB?XVh^OzbC?LKFMotw3r@i&VdUV%^Efdib)3@soX%vWCbnOyt@Y4swW925@bt45y0HY3YI~BnnzZYrinFy;L?2D3BAL`UQ zEj))+f>H7~g8*VuWQ83EtGcx`hun$QvuurSMg3l4IP8Fe`#C|N6mbYJ=n;+}EQm;< z!!N=5j1aAr_uEnnzrEV%_E|JpTb#1p1*}5!Ce!R@d$EtMR~%9# zd;h8=QGT)KMW2IKu_fA_>p_und#-;Q)p%%l0XZOXQicfX8M~7?8}@U^ihu;mizj)t zgV7wk%n-UOb z#!P5q?Ex+*Kx@*p`o$q8FWL*E^$&1*!gpv?Za$YO~{BHeGY*5%4HXUKa_A~~^d z=E*gf6&+LFF^`j4$T~dR)%{I)T?>@Ma?D!gi9I^HqvjPc3-v~=qpX1Mne@*rzT&Xw zQ9DXsSV@PqpEJO-g4A&L{F&;K6W60D!_vs?Vx!?w27XbEuJJP&);)^+VF1nHqHBWu z^>kI$M9yfOY8~|hZ9WB!q-9u&mKhEcRjlf2nm_@s;0D#c|@ED7NZE% zzR;>P5B{o4fzlfsn3CkBK&`OSb-YNrqx@N#4CK!>bQ(V(D#9|l!e9(%sz~PYk@8zt zPN9oK78&-IL_F zhsk1$6p;GqFbtB^ZHHP+cjMvA0(LqlskbdYE_rda>gvQLTiqOQ1~*7lg%z*&p`Ry& zRcG^DbbPj_jOKHTr8uk^15Boj6>hA2S-QY(W-6!FIq8h$<>MI>PYYRenQDBamO#Fv zAH5&ImqKBDn0v5kb|8i0wFhUBJTpT!rB-`zK)^SNnRmLraZcPYK7b{I@+}wXVdW-{Ps17qdRA3JatEd?rPV z4@}(DAMf5EqXCr4-B+~H1P#;t@O}B)tIJ(W6$LrK&0plTmnPpb1TKn3?f?Kk``?D+ zQ!MFqOX7JbsXfQrz`-M@hq7xlfNz;_B{^wbpG8des56x(Q)H)5eLeDwCrVR}hzr~= zM{yXR6IM?kXxauLza#@#u?Y|o;904HCqF<8yT~~c-xyRc0-vxofnxG^(x%>bj5r}N zyFT+xnn-?B`ohA>{+ZZQem=*Xpqz{=j8i2TAC#x-m;;mo{{sLB_z(UoAqD=A#*juZ zCv=J~i*O8;F}A^Wf#+zx;~3B{57xtoxC&j^ie^?**T`WT2OPRtC`xj~+3Kprn=rVM zVJ|h5ux%S{dO}!mq93}P+h36mZ5aZg1-?vhL$ke1d52qIiXSE(llCr5i=QUS?LIjc zV$4q=-)aaR4wsrQv}^shL5u%6;`uiSEs<1nG^?$kl$^6DL z43CjY`M*p}ew}}3rXc7Xck@k41jx}c;NgEIhKZ*jsBRZUP-x2cm;F1<5$jefl|ppO zmZd%%?gMJ^g9=RZ^#8Mf5aWNVhjAS^|DQO+q$)oeob_&ZLFL(zur$)); zU19yRm)z<4&4-M}7!9+^Wl}Uk?`S$#V2%pQ*SIH5KI-mn%i;Z7-)m$mN9CnI$G7?# zo`zVrUwoSL&_dJ92YhX5TKqaRkfPgC4=Q&=K+;_aDs&OU0&{WFH}kKX6uNQC6%oUH z2DZa1s3%Vtk|bglbxep-w)PbFG!J17`<$g8lVhqD2w;Z0zGsh-r zxZ13G$G<48leNqR!DCVt9)@}(zMI5w6Wo=N zpP1*3DI;~h2WDWgcKn*f!+ORD)f$DZFwgKBafEZmeXQMAsq9sxP9A)7zOYnkHT9JU zRA`umgmP9d6=PHmFIgx=0$(sjb>+0CHG)K@cPG{IxaJ&Ueo8)0RWgV9+gO7+Bl1(F z7!BslJ2MP*PWJ;x)QXbR$6jEr5q3 z(3}F@YO_P1NyTdEXRLU6fp?9V2-S=E+YaeLL{Y)W%6`k7$(EW8EZSA*(+;e5@jgD^I zaJQ2|oCM1n!A&-8`;#RDcZyk*+RPkn_r8?Ak@agHiSp*qFNX)&i21HE?yuZ;-C<3C zwJGd1lx5UzViP7sZJ&|LqH*mryb}y|%AOw+v)yc`qM)03qyyrqhX?ub`Cjwx2PrR! z)_z>5*!*$x1=Qa-0uE7jy0z`>|Ni#X+uV|%_81F7)b+nf%iz=`fF4g5UfHS_?PHbr zB;0$bK@=di?f`dS(j{l3-tSCfp~zUuva+=EWxJcRfp(<$@vd(GigM&~vaYZ0c#BTs z3ijkxMl=vw5AS&DcXQ%eeKt!uKvh2l3W?&3=dBHU=Gz?O!40S&&~ei2vg**c$o;i89~6DVns zG>9a*`k5)NI9|?W!@9>rzJ;9EJ=YlJTx1r1BA?H`LWijk(rTax9(OAu;q4_wTj-yj z1%W4GW&K4T=uEGb+E!>W0SD_C0RR91 diff --git a/team_b/yappy/web/icons/Icon-512.png b/team_b/yappy/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48dff1169879ba46840804b412fe02fefd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8252 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 diff --git a/team_b/yappy/web/icons/Icon-maskable-192.png b/team_b/yappy/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d76e525556d5d89141648c724331630325d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! diff --git a/team_b/yappy/web/icons/Icon-maskable-512.png b/team_b/yappy/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c56691fbdb0b7efa65097c7cc1edac12a6d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20998 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 MPgg&ebxsLQ025IeI{*Lx diff --git a/team_b/yappy/web/index.html b/team_b/yappy/web/index.html deleted file mode 100644 index 5756468d..00000000 --- a/team_b/yappy/web/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - yappy - - - - - - diff --git a/team_b/yappy/web/manifest.json b/team_b/yappy/web/manifest.json deleted file mode 100644 index d4e0ed7f..00000000 --- a/team_b/yappy/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "yappy", - "short_name": "yappy", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/team_b/yappy/windows/.gitignore b/team_b/yappy/windows/.gitignore deleted file mode 100644 index 4c0ca135..00000000 --- a/team_b/yappy/windows/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Ignore Flutter/Dart build artifacts -# Flutter build directories -**/build/ -**/flutter/GeneratedPluginRegistrant.* -**/flutter/generated_plugin_registrant.* -**/flutter/generated_plugins.cmake - -# Windows, macOS, Linux platform-specific build files -flutter_windows.dll.pdb -flutter_windows.dll -**/*.so -**/*.dylib -**/*.a -*.flutter-plugins -*.flutter-plugins-dependencies - -# Ignore any temporary or log files -*.log -*.tmp -*.swp -*.bak \ No newline at end of file diff --git a/team_b/yappy/windows/CMakeLists.txt b/team_b/yappy/windows/CMakeLists.txt deleted file mode 100644 index d8e98e42..00000000 --- a/team_b/yappy/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(yappy LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "yappy") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/team_b/yappy/windows/flutter/CMakeLists.txt b/team_b/yappy/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f4899..00000000 --- a/team_b/yappy/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) diff --git a/team_b/yappy/windows/runner/CMakeLists.txt b/team_b/yappy/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c0..00000000 --- a/team_b/yappy/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/team_b/yappy/windows/runner/Runner.rc b/team_b/yappy/windows/runner/Runner.rc deleted file mode 100644 index 308bfff0..00000000 --- a/team_b/yappy/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "yappy" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "yappy" "\0" - VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "yappy.exe" "\0" - VALUE "ProductName", "yappy" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/team_b/yappy/windows/runner/flutter_window.cpp b/team_b/yappy/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee303..00000000 --- a/team_b/yappy/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/team_b/yappy/windows/runner/flutter_window.h b/team_b/yappy/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652f..00000000 --- a/team_b/yappy/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/team_b/yappy/windows/runner/main.cpp b/team_b/yappy/windows/runner/main.cpp deleted file mode 100644 index d7fd7ce2..00000000 --- a/team_b/yappy/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"yappy", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/team_b/yappy/windows/runner/resource.h b/team_b/yappy/windows/runner/resource.h deleted file mode 100644 index 66a65d1e..00000000 --- a/team_b/yappy/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/team_b/yappy/windows/runner/resources/app_icon.ico b/team_b/yappy/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20caf6370ebb9253ad831cc31de4a9c965f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33772 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 diff --git a/team_b/yappy/windows/runner/runner.exe.manifest b/team_b/yappy/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e8..00000000 --- a/team_b/yappy/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/team_b/yappy/windows/runner/utils.cpp b/team_b/yappy/windows/runner/utils.cpp deleted file mode 100644 index 3a0b4651..00000000 --- a/team_b/yappy/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/team_b/yappy/windows/runner/utils.h b/team_b/yappy/windows/runner/utils.h deleted file mode 100644 index 3879d547..00000000 --- a/team_b/yappy/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/team_b/yappy/windows/runner/win32_window.cpp b/team_b/yappy/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0f..00000000 --- a/team_b/yappy/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/team_b/yappy/windows/runner/win32_window.h b/team_b/yappy/windows/runner/win32_window.h deleted file mode 100644 index e901dde6..00000000 --- a/team_b/yappy/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_ From 32a455b48074161c6f504998133edffda756ec1d Mon Sep 17 00:00:00 2001 From: Layersuza Date: Sat, 29 Mar 2025 02:09:36 +0200 Subject: [PATCH 07/10] Update generated plugin files --- .../macos/Flutter/GeneratedPluginRegistrant.swift | 4 ++++ .../windows/flutter/generated_plugin_registrant.cc | 6 ++++++ .../windows/flutter/generated_plugins.cmake | 2 ++ 3 files changed, 12 insertions(+) diff --git a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift index cb306519..20fb3502 100644 --- a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,7 +5,9 @@ import FlutterMacOS import Foundation +import cloud_firestore import file_selector_macos +import firebase_auth import firebase_core import firebase_messaging import flutter_local_notifications @@ -23,7 +25,9 @@ import video_player_avfoundation import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) diff --git a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc index b9a92ab2..14cd0546 100644 --- a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc +++ b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc @@ -6,7 +6,9 @@ #include "generated_plugin_registrant.h" +#include #include +#include #include #include #include @@ -16,8 +18,12 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { + CloudFirestorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( diff --git a/STML/stml_application/windows/flutter/generated_plugins.cmake b/STML/stml_application/windows/flutter/generated_plugins.cmake index e59c92e8..03daf122 100644 --- a/STML/stml_application/windows/flutter/generated_plugins.cmake +++ b/STML/stml_application/windows/flutter/generated_plugins.cmake @@ -3,7 +3,9 @@ # list(APPEND FLUTTER_PLUGIN_LIST + cloud_firestore file_selector_windows + firebase_auth firebase_core flutter_secure_storage_windows flutter_tts From a4611054714f508b5b1d0c7741c717390ff8a361 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Sat, 29 Mar 2025 02:19:14 +0200 Subject: [PATCH 08/10] Update .gitignore to exclude team_a and team_b --- .gitignore | Bin 709 -> 852 bytes .../stml_application/android/app/build.gradle | 2 +- .../lib/services/notification_service.dart | 224 ++++++++++-- .../presentation/caregiver-dashboard.dart | 10 +- STML/stml_application/lib/ui/help_screen.dart | 334 ++++++++++++++++-- .../flutter/generated_plugin_registrant.cc | 4 + .../linux/flutter/generated_plugins.cmake | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 6 + STML/stml_application/pubspec.yaml | 8 +- .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + 11 files changed, 539 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index 3a83c2f087b9568780f528dbc06b0f83bb14179a..b00169fdc21667a86d4e5d765a88d7170ab84886 100644 GIT binary patch delta 311 zcmZXNF-`+95Jks9P*_aC1%i+wMT&$igeXHDIyk|~>vf{tIBRQdr=sEnto9DvfFp1N z4nUntka3a;L&W|Gs#ipCQNoae9MXRH}V~k^2%wcd`(##Uf6_FhiSL7EMJ+tL_Rw_5KX}0lRYpTcI=7f z{b+HQ%_bDbB`V|TZ6;!)JQZ-Uv?)f@-Fll=bxRE&qw$tFETM)D43wZC(C$D30{_Pa eG~_#IPi~@1L!@+O0px*4YEZC&g63aRp2!}{gh~eh delta 166 zcmcb@c9eC3EhE=N2X$F4y_CeFlK7JR{2YBQy@JH#?8NlcVy>jp%$yYci5&raTm_{` z#RaL!dO7*Y*<2G}%1`EG^x)!3$xqf#EXdU7njFWd!p^0anpdX9HMxgTpNmTiY@}XR z@#N!-rj!3NdQNs{^3VnfXBEeTNxhWRf?^0OH?e?=OD`>_w4@}pNVg!TG(9t~c=7=z HIYur3NHa8& diff --git a/STML/stml_application/android/app/build.gradle b/STML/stml_application/android/app/build.gradle index a7b7327d..52e942fe 100644 --- a/STML/stml_application/android/app/build.gradle +++ b/STML/stml_application/android/app/build.gradle @@ -9,7 +9,7 @@ plugins { android { namespace = "com.umgc.memoryminder" compileSdk = 35 - ndkVersion = "27.0.12077973" + ndkVersion = "29.0.13113456" compileOptions { coreLibraryDesugaringEnabled true diff --git a/STML/stml_application/lib/services/notification_service.dart b/STML/stml_application/lib/services/notification_service.dart index 616dc6d7..b88ef896 100644 --- a/STML/stml_application/lib/services/notification_service.dart +++ b/STML/stml_application/lib/services/notification_service.dart @@ -1,25 +1,51 @@ +import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:cloud_functions/cloud_functions.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:geocoding/geocoding.dart'; +import 'package:memoryminder/ui/location_history_screen.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; class NotificationService { final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + final FirebaseAnalytics _analytics = FirebaseAnalytics.instance; String? _caregiverToken; + String? _lastRequestId; + + String? get lastRequestId => _lastRequestId; Future initialize() async { - // Récupérer le token FCM de l'appareil actuel + // Get the FCM token for the current device _caregiverToken = await _firebaseMessaging.getToken(); print("Caregiver Token: $_caregiverToken"); - // Écouter les nouveaux tokens (au cas où le token change) + // Log token generation for analytics + await _analytics.logEvent( + name: 'fcm_token_generated', + parameters: { + 'user_type': 'caregiver', + }, + ); + + // Listen for new tokens (in case the token changes) _firebaseMessaging.onTokenRefresh.listen((newToken) { _caregiverToken = newToken; print("New Caregiver Token: $_caregiverToken"); + + // Log token refresh for analytics + _analytics.logEvent( + name: 'fcm_token_refreshed', + parameters: { + 'user_type': 'caregiver', + }, + ); }); - // Configurer les notifications locales + // Configure local notifications const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); final InitializationSettings initializationSettings = @@ -28,44 +54,196 @@ class NotificationService { ); await _flutterLocalNotificationsPlugin.initialize(initializationSettings); - // Écouter les messages entrants + // Listen for incoming messages FirebaseMessaging.onMessage.listen((RemoteMessage message) { - print("Message reçu: ${message.notification?.title}"); + print("Message received: ${message.notification?.title}"); _showNotification(message); + + // Log message received for analytics + _analytics.logEvent( + name: 'notification_received', + parameters: { + 'notification_type': message.data['type'] ?? 'unknown', + 'has_notification': message.notification != null, + }, + ); }); } Future _showNotification(RemoteMessage message) async { const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails( - 'your_channel_id', // ID du canal de notification - 'your_channel_name', // Nom du canal de notification + 'your_channel_id', // Notification channel ID + 'your_channel_name', // Notification channel name importance: Importance.max, priority: Priority.high, ); const NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidPlatformChannelSpecifics); + await _flutterLocalNotificationsPlugin.show( - 0, // ID de la notification - message.notification?.title, // Titre de la notification - message.notification?.body, // Corps de la notification + 0, // Notification ID + message.notification?.title, // Notification title + message.notification?.body, // Notification body platformChannelSpecifics, ); - } - Future sendHelpNotification() async { - if (_caregiverToken == null) { - print("Caregiver token is not available."); - return; - } - - // Envoyer une notification au soignant - await _firebaseMessaging.sendMessage( - to: _caregiverToken!, - data: { - 'type': 'help_request', - 'message': 'The STML user has requested help.', + // Log notification shown for analytics + await _analytics.logEvent( + name: 'notification_displayed', + parameters: { + 'notification_title': message.notification?.title ?? 'No title', }, ); } + + Future sendHelpNotification(LocationEntry? currentLocationEntry) async { + try { + // Start timer for performance tracking + final startTime = DateTime.now(); + + // Prepare location data + Map? locationData; + + if (currentLocationEntry != null) { + try { + // Try to get the current coordinates + Position currentPosition = await Geolocator.getCurrentPosition(); + + // Create the data map with the stored address and current coordinates + locationData = { + 'address': currentLocationEntry.address, + 'latitude': currentPosition.latitude, + 'longitude': currentPosition.longitude, + 'timestamp': currentLocationEntry.startTime.toIso8601String() + }; + + // Log successful location capture + await _analytics.logEvent( + name: 'emergency_location_captured', + parameters: { + 'method': 'geolocator', + 'has_coordinates': true, + }, + ); + } catch (e) { + // Log location error + await _analytics.logEvent( + name: 'emergency_location_error', + parameters: { + 'error_type': 'geolocator_error', + 'error_message': e.toString(), + }, + ); + + // Fallback: try to geocode the address to get coordinates + try { + List locations = + await locationFromAddress(currentLocationEntry.address); + if (locations.isNotEmpty) { + locationData = { + 'address': currentLocationEntry.address, + 'latitude': locations.first.latitude, + 'longitude': locations.first.longitude, + 'timestamp': currentLocationEntry.startTime.toIso8601String() + }; + + // Log successful geocoding + await _analytics.logEvent( + name: 'emergency_location_captured', + parameters: { + 'method': 'geocoding', + 'has_coordinates': true, + }, + ); + } else { + // If geocoding fails, only send the address + locationData = { + 'address': currentLocationEntry.address, + 'timestamp': currentLocationEntry.startTime.toIso8601String() + }; + + // Log geocoding with no results + await _analytics.logEvent( + name: 'emergency_location_captured', + parameters: { + 'method': 'geocoding', + 'has_coordinates': false, + }, + ); + } + } catch (e) { + // Log geocoding error + await _analytics.logEvent( + name: 'emergency_location_error', + parameters: { + 'error_type': 'geocoding_error', + 'error_message': e.toString(), + }, + ); + + // As a last resort, only send the address + locationData = { + 'address': currentLocationEntry.address, + 'timestamp': currentLocationEntry.startTime.toIso8601String() + }; + } + } + } else { + // Log no location available + await _analytics.logEvent( + name: 'emergency_location_missing', + ); + } + + // Call the Cloud Function + final HttpsCallable callable = + FirebaseFunctions.instance.httpsCallable('sendHelpAlert'); + final result = await callable.call({ + 'caregiverToken': _caregiverToken, + 'location': locationData, + 'userId': FirebaseAuth.instance.currentUser?.uid, + 'userName': FirebaseAuth.instance.currentUser?.displayName + }); + + // Save the request ID for later reference + _lastRequestId = result.data['requestId']; + + // Calculate time taken + final endTime = DateTime.now(); + final duration = endTime.difference(startTime).inMilliseconds; + + // Create parameters map without nullable values + final Map analyticsParams = { + 'success': result.data['success'] ?? false, + 'has_location': currentLocationEntry != null, + 'processing_time_ms': duration, + }; + + // Add requestId only if it's not null + if (_lastRequestId != null) { + analyticsParams['request_id'] = _lastRequestId!; + } + + // Log complete event with success/failure + await _analytics.logEvent( + name: 'emergency_alert_sent', + parameters: analyticsParams, + ); + + return result.data['success'] ?? false; + } catch (e) { + print("Error sending notification: $e"); + + // Log error event + await _analytics.logEvent( + name: 'emergency_alert_error', + parameters: { + 'error_message': e.toString(), + }, + ); + + return false; + } + } } diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart index 68c56b4d..5a6dfd6e 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart @@ -10,7 +10,6 @@ import 'package:memoryminder/src/features/caregiver-dashboard/presentation/care_ import 'package:memoryminder/src/features/caregiver-dashboard/service/manage_care_recipient_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_stream_service.dart'; -import 'package:memoryminder/ui/profile_screen.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -35,12 +34,11 @@ class _CaregiverDashboardScreen extends State { } Future _callEmergencyNumber() async { - const phoneNumber = - 'tel:911'; // Remplacez par le numéro d'urgence approprié - if (await canLaunch(phoneNumber)) { - await launch(phoneNumber); + final Uri phoneUri = Uri.parse('tel:911'); + if (await canLaunchUrl(phoneUri)) { + await launchUrl(phoneUri); } else { - throw 'Could not launch $phoneNumber'; + throw 'Could not launch $phoneUri'; } } diff --git a/STML/stml_application/lib/ui/help_screen.dart b/STML/stml_application/lib/ui/help_screen.dart index 1042db10..b32ebae3 100644 --- a/STML/stml_application/lib/ui/help_screen.dart +++ b/STML/stml_application/lib/ui/help_screen.dart @@ -1,37 +1,327 @@ import 'package:flutter/material.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:memoryminder/services/notification_service.dart'; +import 'package:memoryminder/ui/location_history_screen.dart'; +import 'package:memoryminder/src/utils/permission_manager.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; +import 'dart:async'; // For StreamSubscription -class HelpScreen extends StatelessWidget { +class HelpScreen extends StatefulWidget { const HelpScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final notificationService = NotificationService(); + State createState() => _HelpScreenState(); +} + +class _HelpScreenState extends State { + final NotificationService _notificationService = NotificationService(); + bool _isLoading = false; + bool _helpSent = false; + String? _requestId; + String _statusMessage = ''; + StreamSubscription? _statusSubscription; + + @override + void initState() { + super.initState(); + _notificationService.initialize(); + _checkPermissions(); + + // Log screen view for analytics + FirebaseAnalytics.instance.logScreenView( + screenName: 'help_screen', + ); + } + + @override + void dispose() { + _statusSubscription?.cancel(); + super.dispose(); + } + + Future _checkPermissions() async { + // Check general permissions using the existing PermissionManager + await PermissionManager.requestInitialPermissions(); + + // Additionally check location service + await PermissionManager.checkIfLocationServiceIsActive(context); + + // Also request notification permission (not covered in PermissionManager) + await _requestNotificationPermission(); + } + + Future _requestNotificationPermission() async { + NotificationSettings settings = + await FirebaseMessaging.instance.requestPermission( + alert: true, + badge: true, + sound: true, + provisional: false, + ); + + if (settings.authorizationStatus == AuthorizationStatus.denied) { + if (mounted) { + await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text("Notifications Required"), + content: const Text( + "Notifications are essential for caregiver alerts. Please enable them in your device settings."), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text("OK"), + ), + ], + ), + ); + } + return false; + } + + return settings.authorizationStatus == AuthorizationStatus.authorized; + } + + void _subscribeToHelpRequestUpdates(String requestId) { + _statusSubscription?.cancel(); + + _statusSubscription = FirebaseFirestore.instance + .collection('helpRequests') + .doc(requestId) + .snapshots() + .listen((snapshot) { + if (!mounted) return; + + if (snapshot.exists) { + final status = snapshot.data()?['status']; + + setState(() { + if (status == 'responded') { + _statusMessage = 'Your caregiver has confirmed and is on the way!'; + + // Log status update received + FirebaseAnalytics.instance.logEvent( + name: 'help_request_status_updated', + parameters: { + 'request_id': requestId, + 'status': status, + }, + ); + + // Show a prominent notification + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Your caregiver is on the way!'), + backgroundColor: Colors.green, + duration: Duration(seconds: 10), + ), + ); + } else { + _statusMessage = + 'Help request sent. Waiting for caregiver to respond...'; + } + }); + } + }); + } + + Future _sendHelpRequest() async { + // Check permissions before sending alert + bool hasGeneralPermissions = + await PermissionManager.requestInitialPermissions(); + bool hasLocationService = + await PermissionManager.checkIfLocationServiceIsActive(context); + bool hasNotificationPermission = await _requestNotificationPermission(); + + if (!hasGeneralPermissions || + !hasLocationService || + !hasNotificationPermission) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Required permissions are missing'), + backgroundColor: Colors.orange, + ), + ); + return; + } + + setState(() { + _isLoading = true; + _helpSent = false; + _statusMessage = ''; + }); + + try { + // Get the most recent location entry + final locations = await LocationDatabase.instance.readAllLocations(); + final currentLocation = locations.isNotEmpty ? locations.first : null; + + // Send the help notification with location data + final success = + await _notificationService.sendHelpNotification(currentLocation); + // Get the request ID from the notification service + _requestId = _notificationService.lastRequestId; + + if (!mounted) return; + + if (success && _requestId != null) { + setState(() { + _helpSent = true; + _statusMessage = + 'Help request sent. Waiting for caregiver to respond...'; + }); + + // Subscribe to updates on this request + _subscribeToHelpRequestUpdates(_requestId!); + + // Show feedback + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Help request sent successfully to caregiver.'), + backgroundColor: Colors.green, + ), + ); + } else { + // Show failure message + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Failed to send help request. Please try again.'), + backgroundColor: Colors.red, + ), + ); + } + } catch (e) { + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error: ${e.toString()}'), + backgroundColor: Colors.red, + ), + ); + } finally { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } + } + + Widget _buildStatusIndicator() { + if (!_helpSent) return const SizedBox.shrink(); + + return Container( + margin: const EdgeInsets.symmetric(vertical: 20, horizontal: 24), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.blue[50], + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.blue[200]!), + ), + child: Column( + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.blue[100], + shape: BoxShape.circle, + ), + child: const Icon(Icons.info_outline, color: Colors.blue), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + _statusMessage, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + const LinearProgressIndicator(), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Help'), ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'Help is on the way!', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: () async { - await notificationService.sendHelpNotification(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Help request sent to caregiver.')), - ); - }, - child: const Text('Send Help Request'), - ), - ], + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.emergency, + size: 80, + color: Colors.red, + ), + const SizedBox(height: 20), + const Text( + 'Need assistance?', + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 20), + + // Status indicator (shows when help is sent) + _buildStatusIndicator(), + + const SizedBox(height: 20), + _isLoading + ? const Column( + children: [ + CircularProgressIndicator(color: Colors.red), + SizedBox(height: 10), + Text( + 'Sending emergency alert...', + style: TextStyle(color: Colors.red), + ), + ], + ) + : _helpSent + ? ElevatedButton.icon( + icon: const Icon(Icons.refresh), + label: const Text('SEND ANOTHER ALERT'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.orange, + padding: const EdgeInsets.symmetric( + horizontal: 40, vertical: 15), + ), + onPressed: _sendHelpRequest, + ) + : ElevatedButton.icon( + icon: const Icon(Icons.warning_amber_rounded), + label: const Text('SEND EMERGENCY ALERT'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + padding: const EdgeInsets.symmetric( + horizontal: 40, vertical: 15), + ), + onPressed: _sendHelpRequest, + ), + const SizedBox(height: 20), + const Text( + 'This will send your current location to your caregiver', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey), + ), + + if (_helpSent) const SizedBox(height: 40), + ], + ), ), ), ); diff --git a/STML/stml_application/linux/flutter/generated_plugin_registrant.cc b/STML/stml_application/linux/flutter/generated_plugin_registrant.cc index 3ccd5513..ba1e23e1 100644 --- a/STML/stml_application/linux/flutter/generated_plugin_registrant.cc +++ b/STML/stml_application/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) maps_launcher_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "MapsLauncherPlugin"); + maps_launcher_plugin_register_with_registrar(maps_launcher_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/STML/stml_application/linux/flutter/generated_plugins.cmake b/STML/stml_application/linux/flutter/generated_plugins.cmake index 9ce94c49..d8e70d24 100644 --- a/STML/stml_application/linux/flutter/generated_plugins.cmake +++ b/STML/stml_application/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux flutter_secure_storage_linux + maps_launcher url_launcher_linux ) diff --git a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift index 20fb3502..f2302e6c 100644 --- a/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/STML/stml_application/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,9 @@ import FlutterMacOS import Foundation import cloud_firestore +import cloud_functions import file_selector_macos +import firebase_analytics import firebase_auth import firebase_core import firebase_messaging @@ -16,6 +18,7 @@ import flutter_tts import flutter_web_auth import geolocator_apple import local_auth_darwin +import maps_launcher import package_info_plus import path_provider_foundation import speech_to_text @@ -26,7 +29,9 @@ import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) + FLTFirebaseFunctionsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFunctionsPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) @@ -36,6 +41,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterWebAuthPlugin.register(with: registry.registrar(forPlugin: "FlutterWebAuthPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) + MapsLauncherPlugin.register(with: registry.registrar(forPlugin: "MapsLauncherPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SpeechToTextPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextPlugin")) diff --git a/STML/stml_application/pubspec.yaml b/STML/stml_application/pubspec.yaml index 279902fd..618c50ac 100644 --- a/STML/stml_application/pubspec.yaml +++ b/STML/stml_application/pubspec.yaml @@ -42,7 +42,7 @@ dependencies: timeago: ^3.5.0 path_provider: ^2.1.1 video_thumbnail: ^0.5.3 - flutter_dotenv: ^5.1.0 + flutter_dotenv: ^5.2.1 aws_rekognition_api: ^2.0.0 aws_s3_api: ^2.0.0 camera: ^0.11.1 @@ -66,9 +66,13 @@ dependencies: cloud_firestore: ^5.6.5 flutter_local_notifications: ^18.0.1 fitbitter: ^2.0.4 - flutter_secure_storage: ^8.0.0 + flutter_secure_storage: 8.1.0 http: ^0.13.6 fl_chart: ^0.64.0 + cloud_functions: ^5.3.4 + maps_launcher: ^3.0.0+1 + intl: ^0.19.0 + firebase_analytics: ^11.4.4 dev_dependencies: flutter_test: diff --git a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc index 14cd0546..8e6e6414 100644 --- a/STML/stml_application/windows/flutter/generated_plugin_registrant.cc +++ b/STML/stml_application/windows/flutter/generated_plugin_registrant.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("GeolocatorWindows")); LocalAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalAuthPlugin")); + MapsLauncherPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("MapsLauncherPlugin")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/STML/stml_application/windows/flutter/generated_plugins.cmake b/STML/stml_application/windows/flutter/generated_plugins.cmake index 03daf122..348c6bb2 100644 --- a/STML/stml_application/windows/flutter/generated_plugins.cmake +++ b/STML/stml_application/windows/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_tts geolocator_windows local_auth_windows + maps_launcher permission_handler_windows url_launcher_windows ) From 7fb7530f709c78ee004024ed81c8152152dd8d05 Mon Sep 17 00:00:00 2001 From: Layersuza Date: Sat, 29 Mar 2025 02:46:22 +0200 Subject: [PATCH 09/10] Add emergency button feature with caregiver alerts and update Flutter generated files --- .firebaserc | 5 + .../lib/ui/caregiver_alerts_screen.dart | 268 + firebase.json | 18 + functions/.eslintrc.json | 9 + functions/.gitignore | 2 + functions/index.js | 38 + functions/package-lock.json | 7142 +++++++++++++++++ functions/package.json | 27 + 8 files changed, 7509 insertions(+) create mode 100644 .firebaserc create mode 100644 STML/stml_application/lib/ui/caregiver_alerts_screen.dart create mode 100644 firebase.json create mode 100644 functions/.eslintrc.json create mode 100644 functions/.gitignore create mode 100644 functions/index.js create mode 100644 functions/package-lock.json create mode 100644 functions/package.json diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..7dd880b5 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "spring2025-81f5b" + } +} diff --git a/STML/stml_application/lib/ui/caregiver_alerts_screen.dart b/STML/stml_application/lib/ui/caregiver_alerts_screen.dart new file mode 100644 index 00000000..1ed892b9 --- /dev/null +++ b/STML/stml_application/lib/ui/caregiver_alerts_screen.dart @@ -0,0 +1,268 @@ +// caregiver_alerts_screen.dart +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:intl/intl.dart'; +import 'package:maps_launcher/maps_launcher.dart'; +import 'package:firebase_analytics/firebase_analytics.dart'; + +class CaregiverAlertsScreen extends StatefulWidget { + const CaregiverAlertsScreen({Key? key}) : super(key: key); + + @override + State createState() => _CaregiverAlertsScreenState(); +} + +class _CaregiverAlertsScreenState extends State { + bool _isLoading = false; + String? _filterStatus; + + @override + void initState() { + super.initState(); + // Log screen view for analytics + FirebaseAnalytics.instance.logScreenView( + screenName: 'caregiver_alerts_screen', + ); + } + + Future _respondToAlert(String docId, String userId) async { + setState(() { + _isLoading = true; + }); + + try { + // Update status in Firestore + await FirebaseFirestore.instance + .collection('helpRequests') + .doc(docId) + .update({ + 'status': 'responded', + 'responseTime': FieldValue.serverTimestamp(), + }); + + // Log the response for analytics + await FirebaseAnalytics.instance.logEvent( + name: 'emergency_alert_responded', + parameters: { + 'request_id': docId, + 'user_id': userId, + }, + ); + + // Show confirmation + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Response confirmed. The user has been notified.'), + backgroundColor: Colors.green, + ), + ); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error: ${e.toString()}'), + backgroundColor: Colors.red, + ), + ); + } + } finally { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Help Requests'), + actions: [ + PopupMenuButton( + onSelected: (value) { + setState(() { + _filterStatus = value == 'all' ? null : value; + }); + }, + itemBuilder: (BuildContext context) => [ + const PopupMenuItem( + value: null, + child: Text('All Requests'), + ), + const PopupMenuItem( + value: 'sent', + child: Text('Pending Requests'), + ), + const PopupMenuItem( + value: 'responded', + child: Text('Responded Requests'), + ), + ], + icon: const Icon(Icons.filter_list), + ), + ], + ), + body: _isLoading + ? const Center(child: CircularProgressIndicator()) + : StreamBuilder( + stream: _filterStatus == null + ? FirebaseFirestore.instance + .collection('helpRequests') + .orderBy('timestamp', descending: true) + .snapshots() + : FirebaseFirestore.instance + .collection('helpRequests') + .where('status', isEqualTo: _filterStatus) + .orderBy('timestamp', descending: true) + .snapshots(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } + + if (!snapshot.hasData || snapshot.data!.docs.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.notifications_off, + size: 64, color: Colors.grey), + const SizedBox(height: 16), + Text( + _filterStatus == null + ? 'No help requests found' + : 'No $_filterStatus requests found', + style: + const TextStyle(fontSize: 18, color: Colors.grey), + ), + ], + ), + ); + } + + return ListView.builder( + itemCount: snapshot.data!.docs.length, + itemBuilder: (context, index) { + var doc = snapshot.data!.docs[index]; + var data = doc.data() as Map; + var userId = data['userId'] as String? ?? 'unknown'; + var timestamp = data['timestamp'] as Timestamp?; + var location = data['location'] as Map?; + var status = data['status'] as String? ?? 'unknown'; + + return Card( + margin: const EdgeInsets.symmetric( + vertical: 8, horizontal: 16), + elevation: 4, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + leading: CircleAvatar( + backgroundColor: status == 'sent' + ? Colors.red + : Colors.green, + child: Icon( + status == 'sent' + ? Icons.warning + : Icons.check, + color: Colors.white, + ), + ), + title: Text( + 'Help requested by ${data['userName'] ?? 'Unknown'}', + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + subtitle: Text( + timestamp != null + ? DateFormat.yMMMd() + .add_jm() + .format(timestamp.toDate()) + : 'Unknown time', + style: TextStyle( + color: Colors.grey[600], + ), + ), + trailing: status == 'sent' + ? ElevatedButton.icon( + icon: const Icon(Icons.check_circle), + label: const Text('Respond'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + foregroundColor: Colors.white, + ), + onPressed: () => + _respondToAlert(doc.id, userId), + ) + : Chip( + label: const Text('Responded'), + backgroundColor: Colors.green[100], + labelStyle: + TextStyle(color: Colors.green[800]), + ), + ), + if (location != null && location['address'] != null) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Location:', + style: TextStyle( + fontWeight: FontWeight.bold), + ), + Text(location['address']), + ], + ), + ), + ButtonBar( + alignment: MainAxisAlignment.end, + children: [ + if (location != null && + (location['latitude'] != null && + location['longitude'] != null)) + OutlinedButton.icon( + icon: const Icon(Icons.map), + label: const Text('Open Map'), + onPressed: () { + MapsLauncher.launchCoordinates( + location['latitude'], + location['longitude'], + 'Help request location', + ); + }, + ), + if (location != null && + location['address'] != null) + OutlinedButton.icon( + icon: const Icon(Icons.navigation), + label: const Text('Directions'), + onPressed: () { + MapsLauncher.launchQuery( + location['address']); + }, + ), + ], + ), + ], + ), + ), + ); + }, + ); + }, + ), + ); + } +} diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..5f923501 --- /dev/null +++ b/firebase.json @@ -0,0 +1,18 @@ +{ + "functions": [ + { + "source": "functions", + "codebase": "default", + "ignore": [ + "node_modules", + ".git", + "firebase-debug.log", + "firebase-debug.*.log", + "*.local" + ], + "predeploy": [ + "npm --prefix \"$RESOURCE_DIR\" run lint" + ] + } + ] +} diff --git a/functions/.eslintrc.json b/functions/.eslintrc.json new file mode 100644 index 00000000..b84faaa0 --- /dev/null +++ b/functions/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "root": true, + "env": { + "es6": true, + "node": true + }, + "extends": [], + "rules": {} +} \ No newline at end of file diff --git a/functions/.gitignore b/functions/.gitignore new file mode 100644 index 00000000..21ee8d3d --- /dev/null +++ b/functions/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +*.local \ No newline at end of file diff --git a/functions/index.js b/functions/index.js new file mode 100644 index 00000000..bd6d04db --- /dev/null +++ b/functions/index.js @@ -0,0 +1,38 @@ +const functions = require("firebase-functions"); +const admin = require("firebase-admin"); +admin.initializeApp(); + +exports.sendHelpAlert = functions.https.onCall(async (data, context) => { + const {caregiverToken, location, userId, userName} = data; + + if (!caregiverToken) { + return {success: false, error: "Token du caregiver manquant"}; + } + + try { + const latitude = location && location.latitude ? location.latitude.toString() : ""; + const longitude = location && location.longitude ? location.longitude.toString() : ""; + const address = location && location.address ? location.address : ""; + + await admin.messaging().send({ + token: caregiverToken, + notification: { + title: "URGENT: Help Needed!", + body: `${userName || "A user"} needs help immediately!` + }, + data: { + type: "help_request", + userId: userId || "", + latitude: latitude, + longitude: longitude, + address: address, + timestamp: new Date().toISOString() + } + }); + + return {success: true}; + } catch (error) { + console.error("Error sending message:", error); + return {success: false, error: error.message}; + } +}); \ No newline at end of file diff --git a/functions/package-lock.json b/functions/package-lock.json new file mode 100644 index 00000000..684b2b87 --- /dev/null +++ b/functions/package-lock.json @@ -0,0 +1,7142 @@ +{ + "name": "functions", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "functions", + "dependencies": { + "firebase-admin": "^12.6.0", + "firebase-functions": "^6.0.1" + }, + "devDependencies": { + "eslint": "^8.15.0", + "eslint-config-google": "^0.14.0", + "firebase-functions-test": "^3.1.0" + }, + "engines": { + "node": "22" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", + "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", + "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", + "license": "MIT" + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", + "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/app-types": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", + "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", + "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/component": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz", + "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.10.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz", + "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.9", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz", + "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.6.9", + "@firebase/database": "1.0.8", + "@firebase/database-types": "1.0.5", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz", + "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-types": "0.9.2", + "@firebase/util": "1.10.0" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz", + "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.0.tgz", + "integrity": "sha512-88uZ+jLsp1aVMj7gh3EKYH1aulTAMFAp8sH/v5a9w8q8iqSG27RiWLoxSAFr/XocZ9hGiWH1kEnBw+zl3xAgNA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@opentelemetry/api": "^1.3.0", + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.3.3", + "protobufjs": "^7.2.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.1.0.tgz", + "integrity": "sha512-G/FQx5cE/+DqBbOpA5jKsegGwdPniU6PuIEMt+qxWgFxvxuFOzVmp6zYchtYuwAWV5/8Dgs0yAmjvNZv3uXLQg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/storage": { + "version": "7.15.2", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.15.2.tgz", + "integrity": "sha512-+2k+mcQBb9zkaXMllf2wwR/rI07guAx+eZLWsGTDihW2lJRGfiqB7xu1r7/s4uvSP/T+nAumvzT5TTscwHKJ9A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^4.4.1", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.2.tgz", + "integrity": "sha512-nnR5nmL6lxF8YBqb6gWvEgLdLh/Fn+kvAdX5hUOnt48sNSb0riz/93ASd2E5gvanPA41X6Yp25bIfGRp1SMb2g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", + "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/request": { + "version": "2.48.12", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", + "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT", + "optional": true + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001707", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", + "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0", + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "optional": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.126", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.126.tgz", + "integrity": "sha512-AtH1uLcTC72LA4vfYcEJJkrMk/MY/X0ub8Hv7QGAePW2JkeUFHEL/QfS4J77R6M87Sss8O0OcqReSaN1bpyA+Q==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-google": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", + "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT", + "optional": true + }, + "node_modules/farmhash-modern": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz", + "integrity": "sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/firebase-admin": { + "version": "12.7.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.7.0.tgz", + "integrity": "sha512-raFIrOyTqREbyXsNkSHyciQLfv8AUZazehPaQS1lZBSCDYW74FYXU0nQZa3qHI4K+hawohlDbywZ4+qce9YNxA==", + "license": "Apache-2.0", + "dependencies": { + "@fastify/busboy": "^3.0.0", + "@firebase/database-compat": "1.0.8", + "@firebase/database-types": "1.0.5", + "@types/node": "^22.0.1", + "farmhash-modern": "^1.1.0", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.1.0", + "node-forge": "^1.3.1", + "uuid": "^10.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^7.7.0", + "@google-cloud/storage": "^7.7.0" + } + }, + "node_modules/firebase-functions": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.3.2.tgz", + "integrity": "sha512-FC3A1/nhqt1ZzxRnj5HZLScQaozAcFSD/vSR8khqSoFNOfxuXgwJS6ZABTB7+v+iMD5z6Mmxw6OfqITUBuI7OQ==", + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.5", + "@types/express": "^4.17.21", + "cors": "^2.8.5", + "express": "^4.21.0", + "protobufjs": "^7.2.2" + }, + "bin": { + "firebase-functions": "lib/bin/firebase-functions.js" + }, + "engines": { + "node": ">=14.10.0" + }, + "peerDependencies": { + "firebase-admin": "^11.10.0 || ^12.0.0 || ^13.0.0" + } + }, + "node_modules/firebase-functions-test": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/firebase-functions-test/-/firebase-functions-test-3.4.1.tgz", + "integrity": "sha512-qAq0oszrBGdf4bnCF6t4FoSgMsepeIXh0Pi/FhikSE6e+TvKKGpfrfUP/5pFjJZxFcLsweoau88KydCql4xSeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "^4.14.104", + "lodash": "^4.17.5", + "ts-deepmerge": "^2.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", + "firebase-functions": ">=4.9.0", + "jest": ">=28.0.0" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/form-data": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", + "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "license": "MIT", + "optional": true + }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/google-auth-library": { + "version": "9.15.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", + "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz", + "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "^1.10.9", + "@grpc/proto-loader": "^0.7.13", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.7.0", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.2", + "protobufjs": "^7.3.2", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "license": "MIT", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "optional": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-entities": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.3.tgz", + "integrity": "sha512-D3AfvN7SjhTgBSA8L1BN4FpPzuEd06uy4lHwSoRWr0lndi9BKaNzPLKGOWZ2ocSGguozr08TTb2jhCLHaemruw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", + "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==", + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "license": "MIT", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.0.tgz", + "integrity": "sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww==", + "license": "MIT", + "dependencies": { + "@types/express": "^4.17.20", + "@types/jsonwebtoken": "^9.0.4", + "debug": "^4.3.4", + "jose": "^4.15.4", + "limiter": "^1.1.5", + "lru-memoizer": "^2.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "license": "MIT", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-memoizer": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz", + "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==", + "license": "MIT", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "6.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proto3-json-serializer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", + "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT", + "optional": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT", + "optional": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "optional": true + }, + "node_modules/ts-deepmerge": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-2.0.7.tgz", + "integrity": "sha512-3phiGcxPSSR47RBubQxPoZ+pqXsEsozLo4G4AlSrsMKTFg9TA3l+3he5BqpUi9wiuDbaHWXH/amlzQ49uEdXtg==", + "dev": true, + "license": "ISC" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT", + "optional": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/functions/package.json b/functions/package.json new file mode 100644 index 00000000..ded79f2b --- /dev/null +++ b/functions/package.json @@ -0,0 +1,27 @@ +{ + "name": "functions", + "description": "Cloud Functions for Firebase", + "scripts": { + "lint": "exit 0", + "build": "echo No build required", + "serve": "firebase emulators:start --only functions", + "shell": "firebase functions:shell", + "start": "npm run shell", + "deploy": "firebase deploy --only functions", + "logs": "firebase functions:log" +}, + "engines": { + "node": "22" + }, + "main": "index.js", + "dependencies": { + "firebase-admin": "^12.6.0", + "firebase-functions": "^6.0.1" + }, + "devDependencies": { + "eslint": "^8.15.0", + "eslint-config-google": "^0.14.0", + "firebase-functions-test": "^3.1.0" + }, + "private": true +} From 0f8048689fecabc1fbbe0b26214f65d16eb0670c Mon Sep 17 00:00:00 2001 From: Layersuza Date: Sat, 29 Mar 2025 02:47:01 +0200 Subject: [PATCH 10/10] Update .gitignore to exclude team_a and team_b --- .gitignore | Bin 852 -> 888 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index b00169fdc21667a86d4e5d765a88d7170ab84886..a08830584923d8b3c38baa5052bdf2855ddcc1da 100644 GIT binary patch delta 11 Scmcb@_JeIh2=inEW)%P&C delta 7 Ocmeytc7<(22r~c;>H^>Z

    _ATdKu(8ZQBT`}+6J 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�V)9g5jVodE|g*mIlaiC6x7UQGPZ9%yC)HyK?^jc|l(d_9O*j#Y*=ivmttB&Z&vNM)L z^+>&ezLJm$>|>XvcM1DECoH#INPk3b?A-BTDOJ9F;Z4j<2 zn3ak8{8={1{j`_RdW%#@TE)kG6g#B#_deDq6s6ahRv+*||CjE>?P96Pi~9egxWpSu@`qdYN;B%kgs0 zA<_LWhPPJmsx~n){02)B&tdI75r~9qn8pTz zI1MaF#E8jY@`O90Ilpf>Z5$f2=VUkBm(+?>Uj{Je8Y%P{3cfum+|IE8Pu;MgugaUkrpCtW(b%Ii6!Izh~o~JAT{-Mig zD;RMZxeF9|ye9V3Tt^Hy-;sX$BHT(Ar_enhMx{O5Innd#B&cihzf6|WNVMD%WW{TQ zZhB;kIs7)9jo-2al<*tTZZ%Oc`u>W{z##p@CUn|IB+fQidG=OK7+&8aBwf}B7Nct{`hn+Gk8LAK-#_wudR#Mk{ttSsB%m zO@wG2yZFx1C9M+TTxGvyHHT@3lC@wLE{RL%8Mop?osx0i{9lz8FmnQwwj7eX%)+?a zKaIC%93NV>TIPBvZs>s7+Mql$=G2WpxX@v@{`t}K3>_RfQ=?&L3Lp54(`G`W6IFtl zAH+wI+f|_|(Em?;zH{PR@!vK==7c-n$O%shdRF7V@HAQ%qjZnz_Id%d2E&cdb_+?; z2EV5bB_?H-_o#%jl(9Q&_n9714oK~SwRQ2@E(d5R*sj$MDu0+? z-r@ufV`%PJOxHAg%6RVcsQG@@_w&)7x6(mSvUhyF&y%1XMp-I8*G;}WCgwbzpDq%NH3U|l6WvXqBB;h8$jLThVU~gWU%^4 z$~{nA8)r9)3gYrxhl!sv+pccDUKZ#VF_?MCJ)i);l3sP2u%^&f(apL!EXJuN;!&wMeq1(N_q6A1Z_nH9j zo>~4)+=4X;?p~Ye0*5^j_m#6PR?6PF3OHLybCJURSUC-~BLlu0<_J6(5&MP=lo)Se zo>3UY;Lw4WB9v(D?E)v!_>+U_#QG#oHtf-o3b4>xLsLYJ5rRIcUF?7L{jLytjpor@ zmEUhtu}`<#Q;HiFNO?H!bDv;yj>k9wKd8-xR`d{r@)wLa1=&XRhH^ZvmNd;szxzQp z9k2;iqDQl5g>E2v%^s96b5Kq_0PTf{+&xq21k`dXlA=};HyF7!wR_KS%nrwxu(y1; zPP$v>+g7Dp#u+4s@i^*Nuq~Vl6A%o{#vwA^o)T2NVOR=XK9TKG&J8}otgO=kMt zVkhMd@_`-J{FB0jTTDra=lv4NdrFp4*OPh(OsGxx-4ER)c=ydZII;Z?6&~VDg$G*V zqFn$3>|8uA_?+`8+f~Iq4)Ov(w=jurDWZ4%A6gfTbQN4LsM;VbQola|n(e^i4HYZD zedWKF{K`z8^~sttPpQIcF)f{7#k{z#iR@PZK(gRrPj|#Dhr1XADo4Le`>_*sEw1qB z29T9CyGU)wQ;n~#b{B`ffAM6&OXUyiZDp~C+QA$~GuJYVx*B0G!~e@E8?XCa+??i< z52u7K|!@^%b0RiG7Rk2;WUr?g+|XvbvxV4$X!e0F6w3`(kCNxI9YBN= z{I?^K!PA0lW&uLe%PL>JK*I|1Dh`{u8T_iGZdlukd9oL^^Sr>P_HwDW&h^efvuZxb zBq+1O?X8ZuSsA`cJI3RJD&Fvd63ffV6gG?upyrgrE#fEqFZoI$3z}6d+FALn3gYvw zCo=f&Fuds*5e`#Jz|OXL_ytzrVAly^Y1fE*S1@Pc=Yt_R2pdj&A92H2mK1Dc-~BF5 zppc#z{rNsI(o4y<>WDdiK03tqsY-?8C;KLw(!&MD_iQS8inKEa|JZMHF;J_m$;MhJh;xwBbOnY703-`1~8AYbh^#eVfACeGEyNNw{mGulG4XSlb9P{C<$ zh&*QRTViHaO7f=SP zyhkXAWLmm>osTHda>@TdwtGCZ-zIM+;=JENR7twRd(lp@GI+pu7vp<2h4{e>jzHkF z9-oG(fLhvAW$2f~VK*s7pt)KEAvu@mh>^{OZEfD9CwTsb(69iC_r!;*8x4izK%dC5amhF_8#CJWkRFeBO(%>J)^@0t7ctZeUff%}I`rxhU4`XF_{jsvu z;S)0z{$T{E!#J!d$)aG|2<+H2#pn8qe0%rnb|D*8)(ym;_QcuA^|8OjVRhW;TvZX( z>`)e@NN*Zu=qzXdjyW69xl|M~eQzhC^PjPhf3<$^d-iO;N#@lS5Pwf9L4~{bE%r{o zJj)?K=Cj=zfOEVQ5Jf~BV8bP?=mK!DZgOP}2-c4RCT9-y&$rDXX1Yi%A^18cVI?S^mfJ*IP8>u3}=QT^e51M>||yM0`)Jr4UP30yiG@ko5;#K|FxQ#Rd1_6i#p z=&zodRnx~F?&Oz8-tEO|J#Ipt6gSYY-QX$~&ZWC3DyGPT-#;3>IE3$Tdw?nFqMTn}Fd{CjQ1kS6P>N`O3w=OuKgImWxZB&GIOJGNAy=6OuG* zX8hT4%qk!EfmNGNcS1B3N(f;yYOk$SOj12}2xAcY35B~M>rJgR@p_URU_lVHpXoi3 z>WNX+a-Bf3FSLg3Z&_v;vHf@qap|eI5HIqsL z_O$bqGmFl|MaS$#N66eEA2GlJ-nmYps*UoHG}Ok0R>R6aiEI2y+P;q0w=cha7*lU5 zg^QfN<@`|C4Lx58Qf1-_W!9ICEO29HxDQj@nM8X>7f&6%i_+o$-2|_hA7&0Bt{(=; zEr^&^Jo@w6CR-2iGu~0t{13{)0!-Oea(En&3@Z63?auD^H_zQ_W_{4hUwnHj=#FpMDXG*5YW^#mnCb zgLC)DEoZ53ZB{1bm&~@UM?Fgvv>+`?54O*z)na-0Y4H14-~a%)NyLulG_@hN)VZVy5L2AuodXA!WEoViPK!UwUX$l z5cLA4pndyU_;EXe*5TUi*wwc}a;>FlQdW!Dq5oacq_albFJ5Wft@nq}e~4Q7{(T|v zKinIm6(=INPN|3w-64t27mF;_-NQLX;m?1B!8>>>Oepy45}^@`V7@{SyW+T{Pf(|s zAQ1%!zp|=dDO|a2Wy+;hF<`;{$d~B#HGQx`oBz9G5wma0{SyfGtL3&9V+gwQKBI$R zG5F%n#pOd0!WWXC{_bG6SXiM9WMPE5D2F*riY>-{kaRq` zV|M56GnNOQ!s#)h(`9-79bKJHy-_$0?RAGIiDH<3)_c}#)Wf)_5H^Zym5?8QKQ>Wz z`i@`fx=?LJ)3Y`Zh>E0oCaZ>WTS>>$^SDB@MU+m?7;GzybUw3yt`->!{O=CXMF$5$Xz1%E|0_>b$Pa) zx|@{_+YT!uC7D>O41&`H$8EiV4>9z;r2hwUN}K{ZAQc6oB5L&($3zRf>ek(Tn6+Kn z{2vDH3z4SR>-rjukAQHA6P4o8?01n;IDJAI^KhND2ggsWpAnAG;|bWJ(^2+)0VX5I zJ{&+pkD3dB;V=UX@do?_E+H-45N2t)mivSgA_c98oB1laOFGUCve^R zv`uo|zS2MCr3alg@C%vFB0IAXC%wc(>bq&1r^4XUY)J9)LRJS#W2A2M#h%q1ojhev z4)-z|2%bQA42BlB3nIM*z5t&eb5^&GR-FmXsU+Bx5rsd-ko&BBt^Dc+&D>sX6lTwq zY1uBN0=8IItX@@+r1Bvvi1eQPArD~C+K$RgTF{UF^kZdlCa(9WX#!l*2KUc2C;;{= z#Pcb{dL{T6lhSpTGROR?L)OFVScM^KR#J)Fakb+dAmEYepA8mNB#7KtHpj;PkE64G zXzKmj_}NBxcL_+Uq@=nbsUR(&)INlCNhu&3-6aU9AT5oc0wT(WG)RhwfOL1~*m=(P z`Cx{ zN}hGc)zZRfo|$WUXLQ}?g&QBxr`+aE5u>2cLf$Z_jhT7p7FyuNX@`0s1K+NC@$PGL zU_kZ<)*RTbr2VMZ7)-#s)PxaV0WOoaVvd*rw0J0$2$@VZlRq>b}`jQnI^S{5G#t+M6~S0w#o7DBSgB4Gtyi&DOvAvghg2OveGk+)6pg@YAUJ z3)S~mveKVwHAA(8YZbis4>-s5p9Jb-ozSrHo)JhgjHxZe*zHch9!m##uX$yjV^S-8 zql@bC!0b%j#%2;`)0<`MWGCtHGlA_D(WB{(Tlb_hQK*Q3{BHo4XIY9mS=5AG*`M)4 zAF9^r^6jm7Uhkyn5rmSrnFTVhN`mAE#fN#F`+W!ra3@_niMT;J40e|cL_1dAZuI<3 zF!<-WRbvTr0zxKkApljc9!TpM@Kpm}o>LV+IcxZ-Ehg;Vcvcz$PeP9UpsxDWSYBap zgid7(e~-G5ikx4OpRXjMAHDy2^>SXla+s(HyvE73G6E_v=McDRewseXP>U!T>X%a6 z%(C;s4p)^E|LFIV8@za~TIueW91mDIZY~)Jd+L4gaY`YN5`{(pS=M6*ZQca6n29B$ z5)_3Rb&+591$#1VwtYJsfhuh4ppu(V1(bjc^n0cv+`@5*UOzIxDYZwGKs3E|Z)$dB zWpDJ;>zRncZh2nd-v59J@d)3BSUm$-zUQN!V^2x+65G~3zJ2yu?9WVO6~=fu5CQ;}?yI&TDTrxv zU@RTX?Qk+q92bJ@Fok>n7IUW!?xU*Bz$85exH^Dg#v!q%K;%ao zTCK~`SoP2cjM^`Yf7i;@p#%cBpUjrrsCg^&-;Lr+qXp22?~YNI2Nh5;WO5Icr5`50 zu?@3Lxf{o5j3I}orM>mmso%R}M8vUBRqQ@Wna$2WL zO~vo~r$T$c96*nxY9?3|cwo3cSP?GQimY6~gCRjti_zfyf%o;TJXaV^evpX16co*% z_|053tZ#?Ogd|Ny7`IJrMvNcHxF4jfe&(E`fVHRfyAy@wCQ3ZD-@ByJuZxerx_fEc z87S5^lKHti;`*)qoldLdbBN6L`sF#!YVMw&6yxy(?G7WPxs)O$$A4KCa`hkwo?ma7 zr32&1cN5P64-T%e_mAp$ixp7votgKFW32o#rxShyWO2!WLcJM-A-%IklC<-P#&m}4 zUz;sD*3v6pjf)hs22_+20MjFwS&6lw!!HgVcI8Wep$@U|+Xz#wMqLcEx^)obVfgc5C3Vo=X%6l&sL_r_CP^spMiCI}M z2nO0d*W0;OS5m?05FHglvp!vzy`v(Q1VT-QJ&{=V5^|PfT#B2&4D1s#j?>p4XFFV< zsuea;59aIgVQG^_H{req!pD2!!(r5YTEw2yL89R=wbXZTdoza^wKU>L`V}O#ub2#6 z*p2$EB6dD4#PhD?oE4MbpRhW<`-F}RFtF+;H1cEF@B>Cr`W&>q%C$`Sa~gPwVx6ok zGpLRKgx6GjM4KT%a4Os6uOOay@)d$Lvdk$2c2WR#tKyS#pl!z_>1}whJkdlo2)87Q z4d3FK@v(y)jxW4%C78Rzdn^Xbf5dkN$@V#l?0l{y!yChf)E}6{)W7HMBazmBFr_B~ zGyUfOvp#Ypu;6UDT4#Qxog{ycK6}lKeQ5W5!=hn;3Q$Ns$GNHQ0QvDSQ*p?ln;6tg zp`zI(POj|7k^aW-Z&I4cK@r)J?|>5o7L4nvo{9- zU(d_5t}SSD>(hd0L-8GW>gLY}G{#pk&l3@7Ydy;BOa^{-@cUsAe}(LoOO`}$vDV&S zzz}7vXarCW8t$k3#H_j9igcyV+27#@O7p_})wX`tK8w>?Zaq9Pdj4}bMGV|h*Eqq% z+{NsaedFgO@){BOQqquZ1iXt$yQG(p>F0b*AaD7G`hNj$AGQqt7N z!s|a3&L8J%&*FIi2ZD*peYmELQ<5Hwsv(+gG?` z!DY9z)0DSU zKBqX))zhp_XFAgijF1n-*b)9mFzP){usqHE8!RjDW(!NOV5xo({_-y4fn0k=1 zbg3e`@04qXKDF$;uW@E>bclSyQ~RQ(?Mpnfk^Cv`v037J%ts6q?&KN7D0MouR`d}= ztqZamb=j~g!v3jgzc1?AdU6p8LPnc~t`q*m+_8yW6(}MQiPs?CZ$=VAPnVm$dLq=w z_edL041*tcJdnPr?`VH}?KL2~2X9Z4j5Xz)>j0Vr^8Y~bo*eG?P>y}D20IcN)I8ul z?{f1(vRCQ7_3m=NB})l3+w~TSZ*0^`Ivq|KD0weYjsHRvJs@AULa zpIN@nZC9G#8H}Q|!?estIuBWtT7fnB`zfD6sO-I1;UT3*9|rc*89%II#`+<3Ot9JF zJ{O6+DkmV}D=73OFhdZ0vkFQ#+#N>x!IjRz>|xM))HYKHBpowdPldF%j9L!8NYQ{# zzQ8vyA3Xnnu{rv$K7a~PlVe0k{I{FH(CN8Te*7`s<8F{;{%D`Wee+j~)e33%t4%8W zX|VssTY-LAU=!OPXLQe&85R5xVCA3?p|CIc4bbtmW^U9xWRdwjJz#Ac*CVLJ42-Vu za_WZPKy7sDRRd1I?@xhC2<~jW%#fc>V4(8OzujvSEv!&GE+2r77ME^ikZXNoR&rb4 z^5p1le7TIo8TUIT&mRtY0_ARIMQ;Qj-cY%XD&`WYu1jQ%AAAt4NBtsjuH0f|qu({f z`kSKT&$G271I=b;%IFZ*=vVgbOo_=bX_c*4jK8jR4%h>`5VrK;cS2=p@7(^NU+SO4!q6<2KxbloiEpodmT*AU4ZK`jzhr+Xn470wLt>gZf|6x3XGV zIjVqJ4q&1bo;tiUAou?9GYM~|HN|^Pt<2e?jtdw&_vN=C=#1iou4aMnbA!JRpD*%{ z_(mq2@4Wf)El-XRG0v|Hh_PbjVPgA(5241JpP4EoNKJVjxkM5xe%s_vFkMXcl@A>bsagkzg;wsaqksNmkTMrBqF>sCy4}NX;@~(y?j^0u;*? zFr|f=+KK6sf``2%Wn~ue;-bKdg?d>2f0FMhQH=Cdc}eY5|^2k~H=FJ0yo& z)09_Fc+4S>`lUCiyl9=}JWhOdEn3%HRWZc!@5Lz5i3WJ4dli;M9a+_QzT#Q0D9p+g(OT9;7|28}qHyspec6W@(qua)9$ucXk@U7Ro7t;~(V zz8BH^p|@s`_WJx7KK)i2q2kl$9sk0b)oG_qE-fVNOpot;j~4{Pi2Ni#d5TjsrnM~3 z?aq>!6}L@C2g*8Z70jce!6wW?FKZb2X9Etvb{B0XX%7**xOCET9+o%^ztAULmjC^k z3yXIJ7VAVFODux+EZ(T=Sfj>wvhF4@_#RH0qN+^ks<6mH-m8V4ZSJLre-g1Gy6@dn zMltW;04uC&F6ALy;rN%EF0_s7K6PAuFd*&u{z)>W{)|r?RFV#*{ zDi3FF-SD8uvnii8BnLQpadpI`RIth|C;CX=al6>+FoNYM;o;Gx6 zyD*j$O1Y01TbC}YOb5LF(x*S4Ywq4Hy%W0*T=sTFi8x{=5O6eJloOrZG1VN(@l0J{wV@?V;qsA#^ANACyJ$bC0gcX zq=wUy7;Jz+ICKH0zTS(iZ*x0EAj2LeG8X4gcT3=39*r+{Vt#V>`CFGyroovG&e z)LW|ltm)jaUXm}j$G&9u`1ii3kdKZ(%CH*6u@7GAW?s;{phPmx4C5b(VHSR`yP{_Pw(s4Fe$N^w$gUY7Y1kI|1mrQZFPWLjA73Bb@P z=RWLl+l(wg=7hFzmEi=R0? zjmR(P<^7@`B^cfc6S#fgbY~ygFaDKezzIHDx_TR{dKsSokt`nM%K=E|kj3CdBtHv~ z=*dvhjq#hg{yAmBLBca8REuO+u#5&9uNZM{UXJuN-58C1g0bH_dV5-31cwog^bPXW zdf*LAJomAfW`^?#kUq_#vyg5_EO@y0-Y_{nbN<4lI){hksumyv+vH}=21b(JSMANx zM3WW0a<(WN;O4?p)j|h#iD&1WeeV{U#7V=N22EnI@^VfpZe1#e!#0KyH1x1vNeYtP&*M0nDS_R3_5gUwrnHP& zp$%0m@7^7B7v3(G2zet5qsxu1us%38bY*^75){?)t_*yOCeW)a65D(coIu(>QtC+g z-pR_vL+g92q(5&aY*;-Dnu46n=5s(97r@FLe(mH$SXk#V#`%D}%SWD0b~;IV9}R8Kng60mGl{uhAa-t*H~rqS&7Tq!2v{m zlqt4Ga{=SU3(yz3<)zW?3O?STs9l10X&o-uh+Xf5Zrs#C8NWW4Gf7qXh8BOr{ujzPU7M%XXzK% z^O}9STaa;3KmCh`FPYVLO3TmmbwVtrS@bpwq$r|?^?C!3 zRRDWx8laLCO&*j=?qMYXNHu4O!oRiXpgUZ$<)RmMmW9Abd7}6Wnfr|OicuvJb0(Io zcrIEhTFT#er=+{CG86z4b-p?qHo>J5i(<%Z(E=SIlk={7UCr~Z!9tsyx2 zH+NrG0B(LM;%ztH2tAzWHsn+*LCF^Wh$4>~XS6-3cqyBq$@ zucjb(E;8@$PSW=eT)c^o+wMmgaTs%rO=pQ+e!7(DA+m?Qd418&RDfJIbrVp;`3%VY zKGSJYBsPs8eM#_6TM-7(Q^oYgkxC?FP(XC9c*3nUX`epHO>qQ*Hq?*R{eBW4WHk@J=EC-;X_w4n{`N%o zluhW_>1E8^!Ug>@^sDqb<)Xt5QX=wI0EvbO#uOrD}}VY&xUYfJ7PQ{I-eu zvD1`$-dEo^zF0J^O8ES0&pBA*?^Q-rUQrF|DxM3>tZ`2QJC!1EpMJ7IGpRn{P5yy@ z0uopJoB9ZQ7ku$T)MoUPGr6f?BV#WkE%Ws`*p(#IWe8;KeEXwv6J09Zp_{U-^tE{3 zU1X@N{4Sich*v*N2&)Wx{|lD<3wU-jTgi}pNGOz4>+(@h)a?(vdYd^Z1C(f5O2?^3 zH=}dSnQ^laGv~XVjL@hbO&Hp5}CpFn&89UvG-@yxJ(cGCvIwwJqIxDw|7_vZ;(P6$L|j@5*O^Ag>~cc zRvTL9PdwXM6(gU}VWsY|VlSaVvJ*$#$dmdw*QW%CU7s-GBHym@BOsJarUF(4LPxRfMTDq@?T}qPS*p4;^bf~d>4i>%dxh;qPHaWuO zlkeWHU?huUSzCPF`c3y*fW`pdX1JVL-wdG7cK-Fs`v+N$T}St+Ec0&RAr2<^VTahJl zF8SH~m93bMe$tzlFAwnPrjD_v2Tc@dVCK{MN26o>Zt9MV+){-W#+FFhgoPC+ueAxC z=LR+c2K&C-_YJqbKYH}8RUMAoXxZkLbOXoS6a!{o4-ACk_EP6R3!$Q493KYt7;6;U zbz(M1Z<;L3WF92&09!@uKyfUR(8*1_u|H$?4pN3oHmrP98j_g2f5z<8(h>EkQ6YJ^ z)to2nm*7HIQsVyLkCo!Hd0I>x4JgAwRB-&Mf7|ROWeK>-*6;61m+~K*>gkOz)$bm* zMZwp<-cVd$VV}6hXc2o3zK&bQeAU7eUeZ9#roufl0u=zgHwt4@wvzEh^YDKJ z8|k?lU#@TuKa)Z6wgWD9jxh3naYpsC*9^&`+;7Qj(|!Ao^#f4XlQ&JTXPh;yS|%(- z?HnmvCb3=g+N>!AKy+k+pUC#wY6GKn8<}m-bDyo|hD|*eYGNH+y;Um?b2YVNP~b&- zCu7?w8P0o22YNIXZR3RZQTRocddT zDk8SmiOH=vL4&9>zC$VE1Q8s&@B`dLYxh%K<1K0Bu%pc8J zsVnhXm40^Ck51(P11C*w`fV&D+GHUrvtwt~e}ytQ&cs)pn(jU5Cq{!(m+X5}Nc?B* z0(|Id2f7|s>o==Z_#gRWZk4AbyWJyx_wg{fA0+8k#)mUpM$v*p`M;9W#>TdS4+N(D zciPSAciNjFzDsjV;JnMp0Jmp5JpVvVc|5&2J0zqwYi7^HcimI#!>hbzimx8pT)cpT zH2pt;Xltp?R^@ni4{xLAbB@5^w+J|9#0@v^cDN5x9CN#!0*`xzY7p6n`6_U z{aB-M>5ZyRO;J*|QZ*S=Q8+V-d;vo)zrxn?X;{sJyiwsP;?bDhdlvL_a0B&W-eUI@ z>2>=x8)}VxwybbJTb~>MO7@qbc>Y7KM9d_4er6M&ReQi@?%osf=VPmD{H>=LD45}| zfm9oH8FI3mKSvHvr0u5QpjC$3kpnBF8GV8Shs?6OiLo?dBM-=-4~I+ojdgI`@Or=o zaQZmpXqQ#5M&W{41qjd?^n9^(WGr&*)_G<65!I5ixaZTYUTEl6YJ1dJ#PO9}hmlkJ zDV_2a8E?F+9<@x(8&V}0i3)54?hwG~@?@vxbDIm{R&OY-osD?eF z*A9{woog2AHIn4a7p#Qus!$m z{Onx#{1nN@|KBu@vlZVMO_b9DapNnkt0EWHUUv^|O}24AJl`lGk|%#vFDSg&$rze= z7_cbuWujBdOniqwkr#&>6USvD@Mb}L(p|75%-KDP1J)q5)U7}-`ZvBp<13ygqenko z0ILNqD?4!T(M($EnPtzNldG`X)OcAySP8Z{x~8?MU98cD*AL?ZG{6$FbBuJ$a!R!p zQIc-KLVfnj&2$B<0ZnSn^OnEGdXyrQaPx)ut=ma}(M9L0 zQ{S}UI4#w_erY726}P^8%x)1R;Ut!s z0BM*1)a6(7vAHRSF;7F=d0bdI2}uTVhE)}S!2=y$RzkahVpe&q`OoJ{>vwIlDGhyi z9qwp#{z-~p7TKp=@hv1Ctl|O&;ry5M`arfj5vc@Jap}bpxtA)+u}k?5!X(Zb6FPc} zL+OH*Tesrm_c6H*qE6=v)w^cLh(CEUcW!*N-Ud#^1A*=YRang`0FXgm&7r)s?cEt2 z(b@YK5Gd+OWK7=PdP7alU*}?u&$(QtUp&-iJGBDxRj}?I&b~Pw5&&BVg9YXv?L*f1 zN2DYVu<`MID3PP#g$lrKq>h0HzMY%NlzpA4qi2)9{8c)DRty-}Rr3Jc(74aZq`M>E zV_!6~OR3tCe)(qjffid|lq-k!J1Xwy$bkzB=&ZpXMUk7jI~{s>o<_*T9Q_TQ_txKzO$vgUIl%qu-f-((6CjD8UrJ1`jS&C*LIbKKi3_1-oo44 z45#Q1i2s!MIk^?!DM8GG-`x}i@G8e*11c&CSTAlBA9&(O) z&P|D>1G&=pP0{F{`MU3~Q3x@FL*E3XiAi$AEz{z&;J2?6FML_AOG@0JgGk6)Wca~V z;8|0qb;uSAcJSw~y?YdKxk%808vU3Xo8F*VHV7pFu*53d)Kc5{X}iHEac_dR-* zRT2ZA=~Vgdteqs?>=uWo%s;=7n%Dhxc1*IRg|>u=;wc6mGm&fT0l1Vq^Mf>)8_R!; zJu%EHC(KKjnBP(X@&)$L^|vW4VwEVXK)9N4Sh`*G8QCcqb=LH*g$m*d#K*fVZV4q3 zsCOtRFvmA&#Fd3Jaw>=yQV-<~{OQNG`kTcnoC`w*J&12t8m zfi!R<#ZnsR{bG>fl9?y68!V5fFxg{j?eFUBwb8$z$4}FWe`opMJO$71%x0 zH_8<>HXVFiXY^^tJ*n1o3K-$`Dp&W^7ZNa~%^$BZ9a#0ue~en$-_$nO8j1(ECcm#X z^O3@WS;#kYr3JM7*KX2^v{IrET3moQsy)-&SSXZvQ^ILB%&7D+zZ$fxRRwg)b6p#7 zLcc*aO)zB9_N*J@dLFZd^U=F=S>h%2L%Z49vd)?Hz2D~oJioF})%=}Ug9hPmjlSZ- zi>6#bJJL_x)9SLx@Vvm-?#WgJH_>@0aC&!;7YISB=+RR|<0@aOnPQ~2Mb#^f;@Va{ zy0y)$m|PlF0~y|N5yFpz?QEX6*($Lm`_FD`U%OCbK;*|z<}^>AYOmum?oDI9E=>qY zY?H;v12(h>>?j?QoDtg2OPd#|eABPurNjj|yog96*n0~^I_?%|>I1rgZYX-ZGAu}* z7+mG0+q*oHUVQ*7zxT8H{7dB*He(b2ipy8VT1{HOL)uiG4bS|4mPNts6)*%HU9i}J z7TImivtVSGb4?(P@Bpw(!BG||@QVJB(T44xqu+Kir%wj%LDMAUB3TNMaMa;~87UtSoa!c%u<${&C{LignVBAb8E+b9D!tGA%!+465nf`C6jAUx&- z?0-Oxm;X_2r)ZZ;$RqIC4(d9SUrOe}6pX}vgMzd6^pE!y|OmSTMN5*bc2Ps!vVXWh|2N$4GbTuB^8?7u)7!{TSs#E zq|G6*a|Q=#BQPx}FhY$QC5@mL{PvPFjpGtxgcne|0Mp{wa+qmR?&>7|iI^inckSWD z%;&$D!(TR9jz;1;-_!I}znB!?XPYW|M~RnI#3H&%QY}i;oZ?auSUnc?83wuIi>Z--BEO((&hHl$=CbIYR4e!`M?rQzL=6qpVXwug^!O?oiw;!4{fxn)nBm}679JdoM2YkAGX+@-6S_QA`1ivxh@OeRcL{C@S$aKAj@3! z7QIPxU?p8pmECAv>B&f!f8qRZR~(YDWa!Cx7)_c{jf#Frsh}v9@7o?^_`E%hrntw; z32MEk!>(Cv#WzOjS_k87a+bc|Ahu_>@r2Ft6j^yX9XC&~-*+yLk{weT>84n1FH8L~ zgXZdAjRa%&4bq5r;!h#gTP(po=`r1dxC*au9bkH=7q)z$B5EU+^>8(l=eBT0~&oE z>%}j|@md8q4Jvpc#u`U7;=ZB)l#rb2VC+s6g?VC2;IC*Zh>-J2oAxJ}uhKlmbwioZ zT;g^|@GwYlyENt-BhPcSyV8-bw2u!lU5kS2;PlCZ#zY0BV<^{Qjd;+BD+V2&@&2Z>>fW2y)qXcog~&zCA|*~CJX4&?#8X2jslZ(O zZ9(zAfvEuwi3SB3v#q-ivnI!sS?;|V8!Pi?EO$M_@#CqGJ{am53MAQQ{#2f^#PjJ8ViR% z-REqF_(D6;XKwdl0Q+>TGDt>$%B(tD>M_Zu`!S{=F?a^-n;-p@{&qg`@EWPay%_h< z3lyRnbAe44y0!XE2+adgAFlx%V-s)w7&m=Xyko<~M3Y(Z$=tLm>RVoWo*tva591|M zAc8DYz7rR4BxQA|{kAhJ<*BdJ=OmjcFFhKfjNG=>A~K1%;sT^GqdMYui1ma2meZ_Q zUlZ$QZTVXJe^1Wvy&rAr6E~Z)e0P`0s+uaJwP}vN1bAz9h$fW&O#SjA}ZfgqJ8_p9V_c89O%1ce5o(aJT*Bk68pLPLhAOi6*MG#Dc zp`i8N;F=3j_H86hV#Q15*`b4q*r@*Vt{y1!;aGqN$T!7>DN9t zJAiOXj5zD#k2-}kJIT9NLddMnNJpsDC*koxtA?H{N_{42!?pZ=l!BC#PtZ% zV*lX&(FPYYG@4Cwk)_=LGoBVjnCGq#eBU@nh98f}Z~@%Moe!tPXBJX#L|mb#^1jSVgCe+wn@os>MS6W&wbTz zD1dHxkE3(`yZYVa;YSLAVuVgWS9oK=*NE>n5w6w}_tc}2a>S&2Jb>VRuRZe=?!9To zd_!!i$;G2d!{qrLOu~oq>aybM)8I2BbzJ>pQ;*lIr6hNsZ6eFAq*;2%-#F**R1My{ zH9Lxnbs7X#Wls1_o@Vb!K@jO4cVhMMlB7g@emBUT6MFZ-EjMZ;hCrOTz2k>aoN2IKZTlNxL-R&Xhl59%4q$2Rr>7es53o@ z35T$R>~2!ZewPu5=V5q1^q)hvj|ev5xU=(};;D4FWYgp3Yle-~%2R2~`NwK_zjfnT zRZ6dn7)RE6PM44-6w_nVPOO^eUm*qm;!h`2B2OYtyKypUYfKH<+d{ez{u=<+bajlI zV}*z>FK;kKUNa_Y%Cl3?e2CfbD7T9cv)+zcNGxZ;+6^JfK&e^a8K=#+ePnFo%Uyow z_E|L5h+uj*jzt-PdfzLr&4Y)JP8<4=iJgOqD$mjov(Qf95OcYZcNl(D747B%8H0mR z$2u=gNjU-Ag^L<8e#vb%j{N(az_e(xzxURH$I#=$rz}a{Du5Io@ILB_yHACL@30$2Bd7bJ(jk$5 zGGx)R+d`_xZP<<@bfm*h(r?jun$ zU>FP@eY!_CDK;^vEK8a0+TV@g1s+<_ag~ECm!c5xD*FU!6CC5Y2Aqc5F!TYZUZ=!= zuTDw}=R>?VUO$BCXu_RqmG3r5gowqbQ3A(>pFU_yDk+5T&2Z7O!nhJsB*5C+M9QUH zCRSE~&fA}cY;ki2`q!8*v*i%boEpBY7eXb}T(CKlgAkDUdo^X0ZTZna zK-jdwf1&9gFxPXceqz{X)4-AOTXzDkmiOy?GnW`mrHBrl&>!hW_WS;!4cx7*v~lLY ztHapH6q;-NXUM8qOomZHqJcF1aB!6`alR{OZ`GF={O)1~p^A?uNfs;tSCqjP#Q`ni zAN8$3R!MC8E>4;ZZ@@v=-n*!rpP&Qa&(&gKyU1N(0+i2gX6jDkvY_WqP*xQoUm__n7NK`O zY#Oh2KG5ZMRdI!eJGE0B@k5Sc#DiV$exdUPtdu72Djjy;#wC2mNn;j|2J%s{!J zkhleD4kaU$__%Ahu4mfDHw|`_{NR4a?NsigCDxmgp3Fy1hb>^Y{-s)qbp$xX-J^UY z!+%*k@aw6BXEch+&AV%MNTPCR8Ekrftc+h-rU{Yx8{_zOBIIqtUIST*NnlQs>hRPH zzcb!zOVN7Dmd1f5y+HO;>Q_@Hw|+>;se{<&(n34m?D@aN(Jir^0>$T2;pezgqWxc7 z-AM&_W8W(ZJm$D`Dgg@#7)EihD;QsK>tK!{> z>$-_mO#9tPDDpE6^MU9^mIa4g07^}(n3N{4NDjQ3d1_crhWbmHy8UNg2!cFI9BNSE zC%u93r&!F{LSDZj?lJ&UfMP<`j@mE+h*{=$*?cFu*1j_m68fznTCQ`!YsSD-z6o{Z z-Uo}g9J2MreSA zCk3K!9Dr-33oW9XTD*3$*P5nE4g#psQ7qfdvNHZO!TkH@5z+Y1U3R_Ih93etHrklX zANK6>*D)pBTvy+Q@&v(0e~}`D((+MB#bd|1NyiJkm%!RZ$lQdZWKH#xrOU?RpyWde=QK)zerOCLVu+1O1_IF{^kN>1g|K@RS|Dq{Om!Y=1BRyFGPzhvk@< zl8cAxj{!5l+wTm#t_-i`LP>HLWUv(Z{A*i-r5;4j8+FphIr=|0x8ilPcvf0(E_dMB zL*Mf#OGTZY{^io<(}RoG3)RPC3y%j}w)C_<-0#G!NhJJuc&|F`kI!$rV+~ExDR zc>n*T_mKj9m!eNLo{lw#9?<|lQg$#y0q6g41mfA-ofePb)fGA*nEDz1axxJyJN2e7 zX5AjTt2(q7biGb>G8Wu6Z0@s0Z=AVD!;Ftjr9vemKaiqtFQX54Alz>fhJkc+l|q`T z9cT)ZN~2^*w^$L(JGy7?W0^Avm+}Xd1HO}=ktWa|CLQ)r+n%od&Z+`9ty|lg6?RCn z9T^;K|D6VTh1@c(yFvFCeB3P2^0BjhumJJvR7#1?1dxFz9Ei^mU$79ue z@U_a0QuNw~_FGA*W~@a4xSQUU0Rb14fjyI_T0veNT82-gJAq#_B*RFE7k{4^)eU|+ z{fN;LMa2?ROpjBHK)DKxX2)eX*-5bcF-GfRYyfk4dWpjkwl1OK1+}VezXQD!=&+dl zJS%b^39Ne}6_AYJM>Q|2`4zD#KwZ9vdg%)ROZoGsmg8{MMY!ef|8 z*}so=lKD z3(cOEOHyR>^S>9Cst}euJoE?iA+q6VxP-(Qpm}-8&55ZD0^I9Y*!LSVs`gE=guMf7pd-f+un(2 zIww(xTx^!(d3Dk)xg+b{*!+f#JqU*t`|R_r)dPs4IK0zWyw!V$!1h^2`)VRh#o~w@{7E*j5>VN^^@??}vxM@3Rk7=DIL(r* zV^_g6USgZKD?s>>cUIIA?OX25CuIeGd9Yq+qrq+6gZqAya3UrBw;QPmMyw;3F1gL& zajT#e0$s!kx*898_>`{9Ow`=YJYRUY?MelNR|@aTQsQRsZR`n~*%@|hr8a!Cw^}I~ zlo9airevt@9a*>H0&ZFL1CFq2=6r5TTh@HHAT%(3A2xRC<*>j6I9wwaD;mLuQ5p(? ztX^c)+(#W&lqM%B=IfubRle2lTU z@Pc3GL)lIk5&V|YM|@<2=i4XxOA}d_Pb51@Qk&$^>C=!nx}JaLZF@HlfUA`V#Cb-| zg_@9KDXUibkmsxhOu1!Xa^9AA5Nk5lfAqaq%+2}hUaT%Iymv&4c(Z}dST*MYY1({F zRu1BIXPA5;FC2ka1~LqL2YAWxC5Xsw+$^tC61Bnt$vqS98)3~jO4F)H>MpW@Ey?-< z8yd^t?NME8A0{?Mhlc!Xp(=YlRs)4SY_w^Zll!0Wk-TrQv3bJ`8Qx38W1W-0Xynfe zr)y`8>=D~nvI}1M0vwre!yG!^;2?NStnMAUG5xg1h{ms7`di@9NsQ)3rhR*lHnAiF z#Q$NL;^Sz(d@>G4plZ|iB#Z77G>({jUXPv8+QJ4B0S}K^UsZSEjD|x`w;xpy)@MhI z6%Da9BJ_b?u(1cVjQm0Y->)!o*xmPCd>0)81qbj#aOW zP2z%CcoP==Q|f_?OgpG0@BHqJg`p(@u`-JMVrU+xN_B;4aOZRrRJpXPW^)2QmUKa% zjo~l97CWvN-3gSiAvJUBUYY{eeh*@pX)sLZ>OOWHDbCV_twkD)`Su_u(H0%Fo!5E= z%?ZEF1qNJ0Eb!{@Atm;aj?*|I_eLF;$vkULuIda3OClJEoohpogW3OS1ab73V6Zg= zDvJI5j*9*OL@Pt+5p51)W_GBd24$WvlEHT7`yOVehS0wWj(Th_t2WTYu>s!`17}WS zYWx8mA4T{;uUvTQ-J+94xpzu$T7C>R zHsC}Hw1_hlY`JCV{L&OVT9VK%cxo}J0E;2<-zdPHujYik92h8h`UV)NO`TCcFoisAvuGO@0=eQUg35hFMUTmpDHiQj_4r{;;!Qs@>aW{I4nl% zZCnx|1xoSZvt9&!!Oi!V?Afa1faHafFZgI0!*)ilS1DNiJmQ)d-{P0pQM`|&%>H50 z^vN^vnGID{z6t9Z0tjA7$h|-L_WJGKh9`!W?}o6Zl>0fU9J62EIsbSv0J?lBcJsYw zFzN0*Z@O{x)$;ad!Mq5kp#x8-Q)`+SA>;}OKxXRwa)7rM9xj4+=F)?83lXnwg^kp> zZ||E;DLcqp&M+W}Z;u*Yh^l9p$N48kI=ZzGk7}-0*>TeSvnXw$KZ<}~@|!Rk5mE}l zF+7IPwmqxW2t*<-`42#$bL3Y>;R+&qIY_#IDQCQvASIfj!b`qXX<3MXI%LQAjL=)_%asL%!?y8F;E7eIlp*n284KgfeazZV$CD)KK zc$71bEI@%D8VBQ5JF#@wyj0jOy#w&glnj5X8=@7+5y4g-KvC*#t;AS-WOd!Upwis- z4hnilc0X@8$I0&Ksy07#%AVTI$h_8h$WJHTdx)vwVkrcLiHhMyc@m&@ zC%8Lb1_l8Q*dk(cSp= zn>=KYYM&bp1jPF3KN{3<$v6f;C#3=U&y5gezn|c8=6B?tkw=}1ZRKdg{rf4wFJE1F zDn>k-lp{;It9)bd)IBjF7OXMl_%)WpK-L-6HW7SoW+N`Pb$(4HqM zY@n4II%jmP<5z!4qVAXD@y|s??*yk-SQKFddN7vp(3!u9dr>q|h|5^knG+9cB75>B zjgyyqphJO-z80j(j`S(HtN#|k`2-#D5(TbsQI05G1|l1JHyuoJ#ZR7F%KsMrsNBA< zZ=Uoj)PMfqSH-$ldq~w`!yAuW;hB=O4>C!D?$#~MtKOjhEUt(Pcm>Kx<@vjmb?00< zt$uhP$0bih?dFWmUVOM2ALVg}UvZA3^n-~PI!^tAHf4ABCS4-dN<57OZRx*;NxQSX z6nW?DKdwv-4oDea7C*)K@v<$L7rh9xd4?Q{NkC`)H9sPX1pz!4x}4V%d7_kWE3x6H zu$pEnM5&aQD_gHRQzNS#LYZHgrm~ff=ck>bXZ8<_?(4p+sBiqKqR=tk5uk}K^zFRq zb{0mHKkj_$(TZBzc20L&FO^$2?$AfRh1^n8TjUHmpYxQ}-2s%eY8AGe_g<0)#<1ux z%z*hk6TGj>^u0UOk5%L}p@cWsf-Au6M*70+#lMEe|8N1+kY*H zS>qN;RAQQDx$TkG^Gr@FaIkYzj*M)spkj0eI!Ux@9lnXy5&oGF8mTdqL=ZEM71djp zmi5=q2krM$nBCYnyaKk^iBb%~wV5K!%<+R~_$kMcpRx%^&SC?t(ghg9r5{^B`Qm*T zC5cypu)<@H>lPnrIDDBq7S(dPRrq}$kcl^y^U16A>Iq(J@$P_(_ z4yPeOjP8<6-B0#8WRsG3H)$9Ip`Q z&*6R%km>+la=^QBCH=f@PXSKv&a4tD`m+;(e@C%vmaU$sTB+hIuS7Xu-fsD zJ<%oAQXRBZ@ZEd-Fr736VnFxPn6noHnlgP^R2x#o0xP)ghR<5Fn0>fj2oLbE?K~bE z_7HBB^qf-aY59Q?C)&DMtzI);mH?mj(5h@Hfx2fRgp>tVXxDn}N)INX9SKbEN* zK_n7J{!`#0I-#q?ipi6`T3n-nMV}T%4aHr0Rl{*qia1aF4cTvFRl>)r>oaeP;#nS? z2+3(Zy~oSpUa}sxm^;}C4_L?p?M!hSKsk849KGw6-1e44<%_S%7To)U-Q z?%q!(nZ)xxNa$E#EPP>iz=N`??(S>z7J%C(A)^NJ+bYOwl6wc!oa3p~sB?+uz6E!6 ziXR*|tyZ#JPrrr5V~C=FRjeAY81rF#|7@Yb+PV*qB+H8NBd0i{^o72aJ)@NOl0_bC zyl2(+-p>~a&lxI|yk~teUpa3N=EI4+Q&P7X_8HH)W)opl>qucEW_d}XqJkuA z`U;Ggsb$msiOhTE7f%TN)Hw0g?Z=I;Jr97+ysEi0 zAdyO0133U02E^8;4Qh(9wBBfT-Z)S?)=81Clqu~z7sKmMI-7~m!b|Ue<=kKur{xLZ zQ-D{qTuCt)dHn`*0B^<#D-H{J%o@&r{6!^qbo_t2l=fq1wxqW6nlDa*;7+|hV)K=I zqO6THnz#I9s9RxXwD3QjF_a#rQ^iQ`6Q(bQq6#Ez5j@@@S(>kd8uQ|!`u^D7m?et{ zGBu|wJ6(wEtn@pdM}2N^IVLg5aT#m-TM#M+w0n`dA5k3oI zU(mq!{UADWL6N*Y*6J3@hot?F5>#9vp>+C^}xdu1k)~vJ~@8#W=Oc(FLZcm zcn6lEedFp@?oE4y-i$avVbN!R?!U6)Px=IC5a(~uoJFH=kzMy7rl@(l)8&F=E3_`C1Q!lPtpK51#pY3<72pwLn9 zs=|Bg$*&dMes_fc`trssTj|V+W)=0Fnu(8h9Pct)^nEia@neEL?S>mWLx5(wOfcS{ zmeb$dog+VCDuQ`&(2u_)ZBHIers*us5gq>B44Pd*PCbOx8}l8|o8!3Wg~2@ciRS~c zdw_a2M~c|T^9>3tZ>re~u+Bo+@X?X;;M_JQBTN+(sadu%A7i(3f7gBfs1>GX87|(t zQ2Q-mAXf`}>vHNt>*c^HHGLM04bSVA3iGeGSpQYFctV5x+p5jYU{SQNTNvla^5-@Q zcRybJGX#tF|0T)qM?^AU&bbZ#MP&Ef0agozg#(R>38qakUa(+BQoUj*qQME4iVZ+z z=2+rg4&XGvi1~o^YX97Oe^7jH`zWJmy?rm}m9alaVoOywklIZYBjzi-N_r@gc?Q#? zHw(gXnnU!n0+Am4KsIejC|n4GPSB5`mxMk1HO!|PI%0D&GS39xuO{4 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 OBfBEOt8uK1sAy=yN)=1;tyc@(maj@FS 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index a4e21a909dbf6ed2b6972e2f6103b21e0c86759b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1678 zcmV;9266d`P)EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}000D`NkladFNW|I+=nCAwrz7KZ~ex5Z6@%VfIxpbQuqfzlRe%gYr@ zE$uyLxwpfN&F%bgALrcjx!>R8d>Q^@*h(xp8(%D|x0l%})6A(>0fJC4G%@D#I`3X~ zeLZ@|GyJrD?4J`kC6?UAqqWBiD)aUTkyuw?%E-<)p<-YRj{U0^9QYNLwWIzZ7rVJ+V z3!>v(K$d}2nu?0F3KSUgpqKQjxW_z-v9K369y$?-O+)#sM8S3)dg+{}&o?k~b9hh% z*1cDMoKu#{Wq~*+$kp0WYp#Y~N?Mj*gJeKq%32f{9r(`Qh2HQ0;sTH;G3-9laO(8# zlQqmzY|XK6bnJ=!r7T0rK;5cc&{6FZkPu3UB#~4lEW%J@-i{ex2%}LiWDuANtvho! z>mg~7tOAVdKwZNkM;)(D2??!h(NkGzyM*s!t;F(D(cFpd7u zAg=pwVyA7p`lY&$D?LP%ToM+V3QeS~F{vR3qjTWkYJN;fnV@ls`?Dh$ne_rn6f_P9 z4r}u2rE*~+G6Sv@3e{IJJ0U-%O@on%r94U5a z34DT<)Nm9H?{0ZZy$dM)8b_PA8=w?|NC2o9zUt~=6E64gc<)$;xzyeu2;hs& zz#I0%kz!4pTe93d6lGC4hVvs=Fe(Q@C<7%DW*+#v#(IWa>PfkJ?BcvL}C^d-&Rk zO9!?dYHZD5E7;`;C;CDUz$F*o)?Xz}$7 z^!=}6k2~)VUZ^`-W2snIl=u8I^;so(<-Msx7G*6uADImP=Dt1Jb*J6iGvHb>i@%RQ Y0VzBHdcZk9m;e9(07*qoM6N<$f)mdVhyVZp diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 75d60ebbb855fbc31bf650e8f28a40c8b1854df8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3723 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 879605792903523957fe22173b56afe7e7cfe64a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6295 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 A#sB~S diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index f8bb596f0a8cb140dc4dfa63a02195dcf245c61e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6021 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 461ceda0ff912909baee3edf5b9749fcad92c01e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10398 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c5855fcceaf38a73a7748130af7af41f80194d83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9314 zcmV-oB%RxdP)EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}001I&NkldNX+zfS699Dh4=gF>qf%=qLyEoi}Hn~9sq8DH~@&+PYQqpfLKpsZ>055yYden zs?nr>#7#wqh=Qqk!m{fY73Gv>FDaW}vb4OabUvlZbO5=aBmfXE00(6k5F|knCBO)P zehM`9H1!>At!dleS>Lty(5AYEw!`hoWL*Bj=kkRC=*#kA-pbi|i?69#IdyUQ<+)`! z=L4vul)4y1lu}URY?^X4aRP8sAON5QKvluiJQP&s0oNkF>U&pq^tTOsIM5#4y63gM z?;Y51sCl?&B(;;zrG4%ImMti8Tz1dOmGdu}eY-!`e>H$i9Wb*|J7feF5J|c-tQa$J zD|1S-DsxIR*UUJ(GJ4~~U#dQ_yYZ>_e!uB&wOi^VpWp00M*z>bVt)2j4_vlp>XP!i z0lENypwHTd-59weX?mNCFd65#C8v1F?DJ+^Jo~&EO~XCIFTMYVEq~nn%#J2Gar#yK zv;#PAF=FUoL*? z^6`3aCeuzEfNsAFw>@_Axl6A*<8c5>D5YdVSTvhw)mDX!2h?XaX8~WX z|G}?5cFPUt-n#suKi~J_n|;mwr^S<>766ysuqgM&pI!fx%!0sOl!DO^yNub*9sjD2 zo~g5-o$@(beYQF?DwkBg^5d-!ZG8KYjSp^ncE^!eIR2SB{Y(H#P7(j~*v(7MTD|mn zfXuUlph**#G)>ktPC`?#OsJ1a;OHm_>+z+(WSCJ2V4rkkD( zrSvW3wnkIbQRGcsQt{kF?|%F2XYYOC2S=-qe=2YNsQ{e1w8DA++Hd^M>2uz#P&O8A zz|;bU1sPpkO{pS=iqmm)SJvrETJR|Q*V3!KrN@-=GZlRtgn)oZ{+z)5-+JlZxv%}~ z&D%CVy{-GykoXh;7R@Sj-S^_%PdRb>~{ zEps$n8|7?S|7gsBYPOIP%Wr8hw1{;&qHQb`yV1l%$Q%%{+)rHvZ4|7B#kW3s^IMWb zysr9%os$M}(g4mpXS(yAKi~Nj15Y1`DuC4DQO${1aZTk5+_o9`=njV190$89jcGLc zHZilXC1O95*k}>4%PJ)n;T1TP3dPbJe|_WnL|ndn_shF`CWFhQ04$nWDBb(qKmX3@ zb!uu$ERG>n)$G>Y0FtVpP%6MGQ>G21j0jq!LQG{prhO%{%~nvuvI2HA#|{59+==#) zny?d8-SqD_{&}Ql_$zf=j)XrmfQ%sD{p_6&IJ~aAb*)TQ7OK+|6(TNP)cnCD${xJo4zI!uF|l}i_M1$orU8VA4(ZA@zrFSGXYPFFo~C_G6UKih z1@NX{tzMEpHUB4uXt9;E=_EA()UmSB6gCN}tu-Z(*#w9JN5X|nF@R!E5lVbhQ0OUy z*O9>ibr1r9suQD{zUm7XM-(wRhQU}6?V(Pzhr7_97(_&fK_LqF-+I$!kgGDaNHNua zH>KAAS<`-Bj{lCEAGzh@|Gf6GKgK5@+YIQD^1eJQQZ!a@Y81|E?q^2KZ{ z&R>L?8PnhqeA*PKEdt@nG;T8CN#iAZ8{04}&}zI(}+mOjoB12#{n;iXC;)rf{^ zpP0z8e*}g7CP1JPX8I~{e!+5NN!bvIN*4(KTNr!eaj0BcU~S-QE=<);6bN~^r086f zg{EL<&mQ#4Bj8Z!mPUZV1Gokg!RV6cN^G%**_HYKw*0H-zPkPCEsc``aMcf1eT`Bq z(Lpo$m-&SnybqQbSoN|DJV|z8Va8l6FIbF#;OFDvYDz3>XhC88h~(tW=u4v}?7ItY z%=OPehQo)g?H{2n*#nu#kT~BXhF6AV-Po0aPBJaSA%p~0+v~A*&$XvXvQ8B}iXrZNSbymd6-jTWD>np#%@hTj*`Rc)bqKvD>*vgY8-yhZQ`PHhk-m!Mw^Z0dcj_aZ=nD<2n3S&sE>A0ViV zfC{RUP^fA5bk3+ckg*)d<@c;P`?m9cv+c?EoAhHg05AW}RTnChF0{s+w&V)6s+hmA?#LmXy{kHq}`-A!B#eCh2u``}k?SGy_wFfO1bME+{$|@3(J52&15a zxv)eN82uK6THzy_=ca+BH!Z)b`sqzS(l@9K06ke=Oj|zV4yyYos?rRFS|!LrQH-P~ z9zM3Uj_a`j;Oq-#=ehjOt96MP<9%&Xr`|%*NVT9ySeUf{Wu7TUErvA( zH9l~u!M^T_h>@sEdw#kc0Xg{+F`%4O!qUPjG(=j_A$M7nAXPh{!A=dQqRpth^6VMs z9NSvA8CC!nu3EfO0W!_FRu9RjMvASec&$@K;UQO{n2R%V=5w#7GC&JywT>qh4#UPO z#u@xRgxVt$t%LMbM_(vmQWDN`K{=uaXXVbr+Z}yKh)E~{fk3R0pQ+BOYOD5A%Wn$v zu3B{M`@i{{2_UOgDV|q)xe@b&T5Om;S*sLM&3RBbsfc-5^N{JtR3||v*e$e3wMw-p zl1c&*CBpl12_7C7Gbji(BNd{Nbw#@`i!S0c!J`ki=!QfDh}0_aWPHH6Et4=SqY~vp zJsRaMExBuQSv?}r=W2ddTTVsZB}MZ}gs$3lg#(ydnJ;9P##h7nvt0!ZeBv$2Veo_ijW;jQdp< zp0#zhqCM1(Tjs7to+FF73JcpD+lV$UW@suhOOV|eK$p@7DyAkni7gEVjT34P$DKd3 z_)GvQfLX=aOF*eR6*yQuuWm$*eO|x=7v^M7heRf~Gr$K=DT0X*)*so3wsA zrb7}%Gz~ZNEXsSWTj2A1kuBsvR$_1v4~~vBU`zK-BnZVc-!xPPD$x_}#?hhUs0*FI z_O=gk&D2ZbfF(;bJ=kpkq3*(h`uoDxA{*SC!{q9NP@DhRl|;v$@1yn^5PNU#oTYhOi> z4B^Gvbs#MLPt|;L0y3f`h8e!;xMRT@p4ho#!Nsoj% zj*84F_$YV)?2DR-BV5G|Vx4CE?5M-%TH?zOs7_?c{L%&15(|E!qNkjwB?h+ae^8*< zHwA9uK1F^4MLnb^OFLK$3)kUO91DmVIhT(U4A<7~Wh@(H!k8*D@ zC#(JO0SqOE)mU4w<{Hgdd>}l4IE_IPBqWqL+K1IFi%WFE>vZdQPrQWGRLu<0i)=9q z!%8;<{W@aK*P2Ttx_MIrlR~H0<(CR(7P%-Txq6yRPfb}#L24}vn~p>UT zIWfh8eHtZUtZ#V_n_9LZK@y0QB#(Z&N4wAw>c+G{h3Q64B8~db8BQ-~h-%Z*MJ&aM zq-@};3XWV!tv?pMFqBYNV!^hS)cQLGT*L*pC|N?G6!}lH6iF!9*HeSn>)*hLIHChwG)Fy&v6q35jraN_k2we5dg_$63<7%GZlYI5) zdIW{Ac^Wacy$j z9>F<<%gprr$r{naUv0;R62pNK-H8}m5qiw7Hc9)O1mU#b$ikSpKOI}emeNluGT;9= zdB#QUVJJR|`o0rTw6YAUNi9#k69+DzdNJRc{J8TIY;E3-?nECL>;y_ysmKH9CYeM-mTT)Jf2!dvNEwW@VYm(MP zF_X>!OtAPIpiU5sVccdIXQk6XBAMhR7epkJO4J7<0~kpRf;v=D(lfyf$dDYuJ9Qu6 zhB?>b?2@HeRImVDqaEl844LQp`cfJQN_qjc0{`o zQQ~lES@H1}RgbR1kx?xlWY2qAwZw2Dc6&C;R5(U~5%nP!s~a~di>XHHgjpR)RE}XZ z89|m9&^%VU$X6dNlcgk*G>N35fC!el6+!iQ2Zs-%b!R&k7cRuo(lb!#D?nMGjPt`J zr3fdYINW;z)s1^lH*^HDOID|Wu)TAD|^^mdVs-%Supnmlb`HAWGduTq-7N?CNY+CVZkF5oJ)T0uWRg(6$&^ z#1j+;vAKH(wsq`6h7>@+>4QiKB1#fN@i0QlAgDwkxOJnYa1U%muG(LP{vx;p$4R{~ z;p!)&do&0l30#UTy!oWq$3`N(Qg>Y&)22p%ROv+5^uRi3reNxHkWrHMa4)K|XY;U% zNy0Fx3G%6(^RKE{4-6!5R+@!qs*-7Q#Sm7;q5Nn`nP@MW(i^j8A>xfzSx&3PYWP z^?{-+TLG>uabS35-SMkY0jrD((=dGexxn;Ns1L$L9Jplqd8q5HN3YVu(@yFML`}kK z#7frEW~sd?JfSK=;niu1R%d70WiHhUMOEHHoRL3=lW>J6y~b|}Pi%A}BF5EZa7sZY zTTR2dlT;@{T7%6!5k8By{SEu)UbV;+FDn2RduTgOD7vG)=!phV>Gh32N(#*$Nto`R zhFceY1Y z2aDp`6Or~+NXG@W7Exk6EGzRCt4W14&9o^3rz^{f7J)7zc;UcWbj5mkDHZx6*!X)oLRgKH!fU- zDeeLl2m(tbfBJv{W;*kSw%~cw;~5`*S(89od*!1VV-&J2)3a* zT#fHv@*SLAu*AHbmf)xzXuyGn8Vq4bl?=9_<;ueq^De^5X)BSzYH+BY*BeLrG+WNH z;s?6x5F`2iY z&+Ju!Hyf4SG8`L-!SD8C@w78=@$~ah?w`VU1PzNziD4d6urrbcgNYD!b{&M`QpaSM zJH1?4ztCE9!&}R-_x2w%0E~yC2sZa^^%rEWv7KfUL#u<)O2U{o7G%^69L4P(%8n%kg4Xx|_V?H0{DLKLumUoR@t!cmV|BEQ!HXVb1WLJQ z*C&z6K&UoBMu&JF(lGY+F{Vcix;NwJ^h5_y-EjcKC7O>}kg*mkofxqTT6fjI6W0oi z3;^pl>~A{%yVqAsF6k108mePBW@6v5BiaTy>pf0oeAImqGXmu(a~B!rVlsS`7@iND zH0!`pOSZ+TKE(J3wvvpA>I=eynAdL`o&?M)g~6c$7u_(W|uT`Wm9nk8#dQ` zpnov{9PSL#_Prhi=tZo18 z-`*}?F{crr(~JqF?8@tpOIag4rh1Abqc+rlir&LmURcGq7f(LLaVBlyqttpl&FAs^ zp?Zdq4}meBeci{fwPQc1AG~f*oeMFA&9+)rw_>FBWirkx=jO zOaA=85A0Tjrevrs;zG1Yf^9ttGCu4+h?$w?D0b(b8hGj1&$!oy?hjzAQNvGCCBoBrTqswYa3 z^!VX*)xR7#-f25L2EctUY-wC^->N^lGTh%&4D+PfK*N#fchR2;(kvdO@Jdd&MNewC zUs%%>pKoAMpf1>gm+LlS$Q$EDRNT{()P>cl4>7_xd-Ne79*(Ww`NUhhQtvkgKqVn# z)309skE?$DwJ))E44A`8ajR7KiRO+SvzM8ohlBVVND9tKBmdgtVoaThm(*LndVYx%C&(`67)O6S5@L(f` zNd!W+gKvxS#I4Qpq_TT5=6<%h0m+6B4t%fn)$RS`jbp;Pw2z)#f28t)s&5r9p7tET ziZS(BSyWM5MHc**yGoGj%+q$<6h29|>a3ddXs`|MAKQgv@lHr?C-yYd!%rQU8Ysey ztO^uo<|EtVhf|Q?6dY=~rlrhQ_3#RR)O92gLHEc28vELCWbg#~l`v!%f#?$D zxVJuLX(O<1Pte#%?CGr!zqoE9j80nE_r^D#SbO`1htKxr`0iJki$yH7 zA{J)*oQi}6S<~PoPJRaSfDt)?WBpC|u`!+Q$Z>h&hVTC2`y-tL6Y}lgtw{ zQJztZC{@rK4&qSPQS9%nN1r?d>UDr*S?o8_AM~SO+rHExsBc$993x5`T^Q!6dtTwD z#o^pCIVE0xLCvSjwTauGle2|m#7sIE&m$W@n)c3!w$y76ZvNSGw>EF9NpJX01whtX zKROcG@#q`3o%g*juLn^dLR5FwWFxVeQGItC+DE$(cEsTDN)QDHWFw9hY`)H> zJ^b;1^Br%xThWv2R0DoouT9isK(@n=!K7NWPHaxXI8i&-4xptC)U4fnNA0WI2PT8f zq~F@{@l)@1hx>=Gz5Lg=zr`MAS3wjxknH^jwV_tjB%Aq*J83o`5-0b}R&TI8Yc9^r zoQ0=a-bR8ZG0$Iti*gs^56y3?$pgg#u7%vf)=L`fEE@TZvTLxeyBf#B9b?a@=E{xJ zSI?ofn^$lC>0kCu7MD|cZ%pmF>JHH%U4O~X|7kry7E+=R-NvwI&zK?73zDpp(;s~} z9`3}Ki_XW{S@W@D@DMJ|I};tTJ`Nsp8XkumaYaTKvU~_izS zi89p2x~uu*`SBK}LmEAS75Qdn$N_BVohZxaDWh-FoQ7 zO_Q>Drv*UP8a_A>e(9!P-E;Nt?%A6=v*b4*B!gH~m+JIdd!*i)e)wp(9@Blr*cAMP zd&XR6ChA685mw^b1`?w|3i=Ym7@=zFT+v=9(482@kQ~M=!Hw;~TAY!eE0VcwQM^W`m{KFruPR99Pf}{`pPf=YsG_K{&?Xn zD<2mf;yGjT9BKAv&;FlD*NimcIFl+uFpvykp09%c#%y7sGmA^$OkXjkxN{I!k{C#g za7jLwIikQUv_yN+6(7W|p`%!lH5VH@H*tWEjdt+kdb0)^mhUYs+dg@4^H2W#TB!50 zy~*-3zrivQj$!M=fBm?2UG+t)p8VDWf#RHh184xYw+5M`XUB$<5xm>KkKdmC^tZl` zaedxdsPs(1_Q6{1B@hHfu3YpdM(}LsCM1+3zjnT_948{(Sl_=7lt}y`pN4QZPDJ{7 zMJkg%i4_*fQRAf;dLuw29*RD-#%oR>8Z+k&;&Fc)y!(mQ_OeAkUG22K#Wxv^ zB9e9a@W=0_vH9*rJxz9d}1sQv)ihU*Z>BTVdLD897AigUweCl zS~%nuTqd<> znMnY~n4&|WSL$Ei@%!3WwjK%|Z$It8>FslUlQ{!&_Y-e4?tkXpA5K{|>*pnB&RQ}3 zie;;^Dhn@VuO#G~_~V8b=|V8T9;+CfFF}EpaPQ!brY)bm-Lj+RgVySrpmq1`^J-tn zyY!jOY1vj2ZP`|{Y3HNsHs#GN7p7gZxIAY@$+Geb7M|<$d6#O1O@(@n$%3m9saf8j z%=ik^+XKhn-Mw?Lxx2b?^ZsK4$J^yZ=<^57+WsN`H;2Bu7NxJQg}pk2{dv`!mx;W2 z6>g{3?f2$q=4lCBzxJMdqW!NhSY{*`8xHqGf+HhC&E1iq=I+l;H7DEtKNk=f^f*O2 QApigX07*qoM6N<$g5{6xZ~y=R diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 51a766bef120f6674c37a8156bb9088fb7bc2921..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15766 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png deleted file mode 100644 index c8d64e0b131a2e627017ad25202ac794c8e664df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4969 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png deleted file mode 100644 index 9261c29a1c19d56cce5e173d6ce2b7b6a58aa838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14682 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 897aca8ee2774923309096845ccf4cefd196d9a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26482 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png deleted file mode 100644 index 257944e567798b8385066e0f3e3cda0af4dfbaa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8069 zcmV;0A9~=4P)EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}0014BNklF%Tbodbs&cQ@^<*;rrSd7?9sPRU>UxW86_3MTrb zMcbR^*lD-UXlnfJiA*2FiborU^^fFZ&}=WqeKmzJiJQ*A-06f2eX^g}nS9 zZflDSME+d8zGmHlKh$h(+IKqgb;;Kf#uKLzGB|D z=lts9|Jd-O+Ry6xE>e_X?JEIfciFJ)*(Fs={`RIf1WBCDv_vBXe;itz-l4id z%{)Q{D9WRJ9_D+faV5n?;6+Ejh5+T)E~{F1<-#l1y!qtY&mY}-y#G?i6`HF z?1pV?c0In~CmZ*~!|{uf^`Zg#&M)p?Fn8s3?^B>eRwY$TOC6Q=of^z2LJ*5asb1dF zG%gy>Jy2{Gn%?lzp;& zvWaIbfKfo!-Ic( z`hSnDd93~Q2VQ?izCgNiL4a;}c;1AWcUQenDYA!oa7s)w&TU8cR{TYVAv`4}ucnX$ zfe29+Arb)+ksuHiEJ~50GSd7f1(_r{DEx3@x1*3I&8zsu zoj+XO@X3$=SbNC;F;~9w$18qCA(XHi%a+;K%taYMnhjny4-%>%1WB4!gpmcl#B?CqCXi#Fwz5m)Q|3DFJdHxw2(5{v(~4g zr5d9v@s*-|N~k3uO(+LURm_~5o>;uL?P$jh2R^RuxoCh`5cu6UzVib?6mJ{Ksmg?z zJd!HZuyjisKPAW%vN6d!2^EYnTiEbptm_7z}DIsPPADYX_%87!(Q3Q0#%Ky4=b@Rb9e;sHJ40DL*1?cu? zmd+@eJnl!#Yf@^}7S27YN$KGZJ4T64(lYZNl)?)Srh2c$wA`zZCuKwAP9Ii=P+8RK zpOh~|{+^kk1gG5%Uv4h0%9(~U;TALmkD)c$%8XDmIP3M=xH;Dm#Z0NLWcX=;lyAw4)xTaD;+T9dPLzLqC!TDz*PXX z+>c>5VdjLF7d*0X*Y3A=o*ENC_rLPM4~Qtvl1(Gm-8NOZ2!bBpXt52`7#R|>h!=|r zuScbK5^S(RPzOpio-hkOLL-C>`NDdMsM@bfbmE%KDJXM~$DTkn8U~s;sdKJTou}qV zHFKt_*Hd^&w@Ke^&o6(u?oWsB4RsAz+}bdJ=07xloUhFH937HEP#!iDBj}^12wKh5 ziEKlWSb)Xj7NW#ipaNrP$xzc8JzyNY>GvRpL1jrRgTH@w^QZs`l7L&DyyaO+k)z$zk`$oak(11D>J*bXB!=ZxJtkJInEkJt zUis73zP6yQMHYZ&-hEwuPI2CMIa3UYiZ%6AB4V|+qoF4g6iE44T)YtZwp<8ARD(CF zgJU)O%MTFO0uWr2HyxpL2>XIHkVR?%fvAx-cOa^Hu~&n-$PJ7B_SS`e{Fe{6j|k8$ zPu}_v(;hAE(p|WETqkG^DD?{uoVc-QE{bgVYR5zC&8GK5`DKKrncgri8Us{LV#gfc zweZJ#a5CDg^NP*b&#eUlv(*z@QPkNtk=s7qsXi+`IwViY9er>^g~DV za&-8aBQ_QaOwF2rqkY9V5pPzsNT5UdPz!5R>5nhU5sJbo#VaxjGJhWG8lW7Y{7HpU zMnUFXM%rMSEou<5W_VN$xUO)NVscgm&vS-Wx-3Nqt*oKOO9>iBTu$)h)FHUIiVKvQ zN)tqlwJ6dwjaWL)-#bJHBqBnjMm(jE>}U8)uq+%?mo)_nzrQX$ufirvp!REc5cer6>VbSpoA*lHEAq zR}yj(b%A@GB^>j-9I8ZOJ1_H=xSPfz~|5gOrIM^imG*V%@a z{uVrR%{P%}^C@)!DxzuNG~PM77TxK79yYLhboF&Pa6bX}knl5E2jo>B-ybF1?-f2a+;sUUKlxmY>nZusoE zNYfP3sW`sy@5Z5?Bd84=QTroEL*`CkS;eiW%Dq~NmPH%Z9DNrjdrl)(o`6Ggj%jin zf(^x<0(3@tm`d?VC$R*t21uriq`Y9tc$Z{z*(E^|%ZJr`RDWt@?L>F&9>I+qdoIW@ zrWuk|n)pYS(>y$K5I3BXi(kn~7#Yq?ejOXMOk_RrWkVKa8#3%!dM|EU1_ZF8nhbr> z;5_M^rtuO)jQ5VmfzUCfenQQfV+GUTBkFc#d5WaUo2GeXkQ|~qTiI-4927xEOetj$ z`0Uwm3pOX9}_OeWHc(J1z}??--l z4kzh7tzRNRk|@d?$20k{HU>nArvONakZp{hWd$7FYV?p%@ooY;Mx>0Q>_Q0?d8|fj z>@%RISjAkZF^;?KE{L2s$#BgXHZ%oT=BSCoj&PzEA2zPTw&pzurNiizLrStsWj&|T z0+f^}V|(X5GzL!cF?FSTdAwq?Igp@f*aQmEoGy$q26otMce1h@WTf;Owz;CIW&2u` z&Hjjz=#v1F!8R{hiP>7|*D`ljb7nX2+B_!nGNEs3`n@R7o#@2}4Id(q>;@48L}&tM zlWl5DqAe^6YF|c*!r~oPe{PrkYPnRYQdav9AzR469TiLArcT|ljFj1EtRe|^xM4>h z;%YQa^gfTK?XKL*ccEJu^4r&_JkcuZGodJaL-qH0q z5j&@atV*R%FP+HhccS8Q)#=bu0zIPBl$j7DkjCbY-NL`?(>BsD5Kp{e!(vBoh}5e+W+#WE^gxC*Nl~ZRIy%AQ?u2%5VyHWZFGQ z$`lRVjaYy5b3}wFBPAtOkQFmz(YZg?J<2XMW1`scq?|-F6}OgeOeqmHEqCbj0)&|c zG1riykR|n~4x+gZ1itN*a*%?_ey$xh&Ksl5n2H-)F-`NCqkJO))ch$Wq;asX22FcU zqB5rflkzGtKEnsQU_(c;2d#Y_Xy`hIv*B|{yOf1OR(s+*6xH!Cr{NJ@7mVc@u?OP= zh?0~ljsnJrq^>(Q|^S5xOJ@`&7JnA!Z;i01hp$fO7&or zm=-UGk#uWEU2}-@&OlfHq3kl>Loj9V&|@HCDsw1}4YaA}H0JoOfmaxL^;%H>O0Z*o z@f-}s2l4*VbqLWYly#9bWYK|H#WOM9S%{9PAK~aA(l$ZZ-(MRE3@F6h zR(ob=>74SkuHE{T#E4B`z6(KXJb;#P8>VJdm{J7mBxr-N$u=x0zXkc;e5`Bu1Wo;C zxa;o?_h5hHK0LkX`&d3{iBa)mmL~weul)p#txZUg6z8A}(Suti-hgFOmLXTlQnW$9 z$f~1SWQ@kKx1$cS&B&Ov_|~FyI+rTi)!!P}o{A@xn)Hb;>gun5{ML35TB>P|B|HuPN^Emo!3fXeJLzBo8+Hmum_rHiAz%{Ucn2lWU;_Bs;P zI@E7WlTU%vsjUrsg_Q%;*>E-y3&p;0X1X3VtBP6e%oSW-eIpcSqU|^lI*Y5aCZDIa zr`>_@1UFmCz>*0!;>ObXh$W+N*d1^ahdv=1S+ap$S6qe4f=K{P!)^D%P9zhhp1+2` zZWl_&u>I^oR%3w?4yvlHd5odCq_U5u@yyO6Cv|}2R2og2>ps5fp1F^xiIEW;s+XG6 zSE7dPVIhrOowb&T3;Fk zQDWsEQwPb?IOjR7Cqk?hH(qX#)s9%|Kv=Sp z#E!rrlxLQq$eE)GbpFiRT6fWeGosUx^WCR}{+lHt;$;&HxKsaoN z3DK(yrhfMxT=T_|VF0mq@ORtaxcP@Gz7J4SxlY@urScL{%CK52!Q$Rtc>tT+_F!fC zt#C0u8N+OkF6zZ!t?bcOf{~b<#-~j?&?WSN*fjkUbn`bhb{d5_T~2_W+FZ9f8VrxT zyQBW2-6wB&X89j%PTT#%eY^Ry<|`G?#qM@45(Ck|)r2d8j>}IPk{CKbr4r0Vp1dqI%8d7v?{8$32u%r*6~Q z_Bj()$__0hFJkZAq60Q!$K`)`XLLYJoQyC{;?t8mu_xF7!7Hj2#vzONx{Ybt4|6@5 zwpBO2*im~rX6|QL7<}-p&GpmozW(*h;@oG9@IZ_Dv}Ie_Y77L(wR>P6C91w$fN0Gu zvrJPsJLt!T6MJwv(FV~YDO#ge9+V4=EwDrb&P>n>XuG!lcxb*MYDN4hEqS z)n^zx$JmmHvaBMgZd7M0)h3f{W4N5;8YU29NPUlL6Wd<=@YCX1m213(*-w}w6RLHj zt-cb1EXl*u1%8ORe<)Acum=f(@esB&AHwnObC_B%0aFUDKxt+nFLa6eV+GJn*l-0} z%uM++9&tH|u1GKH{AW1Tico9Dmv&T|V0$aE#hl1)xc0gWxqRJco#A!RD0Co8iYN=0#?{TQ~Nt3{73 z1j%bdAXJY%y>-YYZj5*PFfKD6K6e)K+*xo7PM(S=6vqHbAs7vzI}${DxECFv06LQa zq@3Wuh@z+pO1XlV`Nm4lf+40p8+w}2vw!u5Rh_k`MtuVKysX+*-PB+6_Le8A9=drG z2t0aJ4X97>P}tKVre{^~!bU<)p*uE!nvUZ*)Oid6Ap#+jz%D42L@E)a90a}TK?GA_ z)CbNWou-h|gx7uqqU|P83w5IMOC$lr1rU#Nj$qagEiKZ_mYB3i=f{ zYkxd~^Rx@Po!zgl-!p#pUIjHp2N&2&z23l-HBaoM^NWKj^=1P(oPDJ zDJoCz@KsY|Zy^7b^y~_f3Pze&{$Pp3nI?!sQf3gCf>fwG_zj*hG9scn6Jn}S>WvPx z243Fu{I5S^dFWRHC@~nrx<_7Fv*NA4%gvu!`hv2%O%a0$-;)kw&9M!L%1IDA0kQ-& zMNxbzBGw@m0US9gV$~%!4`)ficRWE4dWiaLG6y|)%XxgW2yB80RTa4FRH}YDw zrPQM5cO&o-K%>0_@Bd-dPk$5(hA$-k*dC~h2E%mSBd@%?^4;f!yh-E#lTW;w{KX|1 zvX||$m#jq+m2lakP%|nw&hVHvxZO6Feq3$Ps_ z+S4;oP01vLvMG}7M@-?P&KM}7%VR8mq95CW^?1DGHk^#KTL(yn1`WeBC(+m9e|f{>Kl{;G z!MP}az=Oy^tb6p8cNYHBHyf%RzI82tDH<^tVVALjs=3qS(KeilbYR7}h4{q3hx5h* z<8Q?}|1MOx$D_cZJj~b-YQ~Xp3+^qv0Y?VUqBYiy-}`sqhZDbrb^hI0QMdq6Ie}7V zKK|T$7&n5L9&H&0htq zjvyi@`903Wx^Oz$iF=rd1{*Mtjv+C_g+BoqK;TetO zBmFJ@SGWB0Z~m*jy77|#)5%xLE<^1-^2dMuleeyYbm`7{&-~TTY%cq9P%?Zakq~U` zsX%8wurzlDIum`^-QS24kq)E? zL8ZGG4TI+pOvNAxA`XOF_~QlUtejbODwf<;`@2m~A6UJDOKKyXpaZc5ILuFNgx?QO}K@> zXHP~~Wt8FLuKoNT%;O!8b{d0F9xrNa-F@VxJwJW_z3!teUkw?xUAFoJ)26Ne_Rbgk zSAV)?_EUE)nznM`Q-UPi0bopfg|`Hca-p@IW_$Wi!mehZ>^tWCf7`JO=i?uIk5^K^63?Xnke2D|#?ZU6SWZM$B0f7`VC7M4~npS#jGrSx8# z%P~vY%{D@#Kp+*iY$yn(BM>;J8s9a?wWqiFHjT!v`qS%McGmsAVeOV9k*>b4OJ^<4noxK{X0h)&fRwA+#m6v|Xkjchu@|Nl zZDD_~roXv!N6XIoFV1W^bTW9V{o>uyMYg}lf598<>Z1*7x3x5^-S#FCg*UxLxg>9L zsmqz|De@NP773E*Q~pgLw2D9D50(e?g#Eq#L^#^vuR9%z1p4K4Jo%Rxvflm|*bMwW TK*Id!00000NkvXXu0mjf;D%Zg diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png deleted file mode 100644 index 6eab2408f3057b93cdbebd1a12a5ba9297aedd52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19936 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 diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 92c86ed172039429270abac672336c2738a8f061..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8633 zcmV;qAx7SbP)EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}001A%NklaMPO?|c8_`yW*j{y!L=OgH9VUg-ef0*D=esD32_hyjRnoal`7 zw*=__Eisz6-))djPQ=NHywmt-wlu&!z$rL+Q|xuEa?f(w9+BSVk`MVJ5~ z07DdLZ9dp~dZcIMc-QHk!zXv0ZfZN$5&3h@|IY&0;;+v4t@wKNFy_Oxm;`(a&>wkN7cQhQUJ6(5X$B{qQ|LNdc zM|zV9`Ac2Pmj;;A>%gkNSYCSlf4Ta*{(Rrv016ob3?O5qXc#enPSkfP#~6PyFiY(& z>5gSrExKdbRg1@Nf9$5W_rG!I7u%kAuRb^!`cl;Qq66mgJIU1#Zd|e9+h2Lm;c?sm zP#-`IC}{e1Py;Q?r_&D$_&b}la66dV{^@Q%Qn_rx9rnTUi|FQ zZ9ji+_gMesqWNZ7Q;GnHL? z>FujOxb*hb+uwO&$KUPv<)6-6;0Y&5^8l7q$v}n&>f?! z9zyiV6GNENppsOUme!jR4Hf-t#-M5bV8?6oVw*!Cu(K1vCNA6b-Hp4Pe%DQ}{@oj& zUdZ|{2(a24m*?N}t8Z=tuw2!*^pmE_j_ZGu6bU0!(+k5prtz>;^$jMqo?7atalHO} zYNjtGm)*H`o5SO{{>2}>@>w#ToDl{y25jx^t4eNt?8a@NSgu^$FyK_3xdsB&+@R(G zsj3p{F;oLnTR1n^8c4DQE(>hLD!mq0tBaNCaANv^&w(gr0Lt|UrFkp2tlS<6#%_4y z$8UZj&mc;e5nwC6QJs0)<2Sw`NaAv;dpqc=VMvSBg6qJ5au|rZ>oUy1s*6#bf{Zj$ zOO$tn$|`6i^$7jdDsaTO2q6}msc#^VyY|ktugAi%O!?}6JSrekSS%L&|QF8o>Jtv z^5GPna1sF`H_HSv`yG3gfdrBW(-6iYW9XgeL1(ZBgNYGLAPQMjHv?vMBK)`J&DE`! zIv>Nn5^Wg^Zu>EYC?`C^mxDU^|+| zTM>v4AR$uY2PsaJnsr|%c!rE>!|t}<`oQxK?D@sDPd*bFPoFiK60quPmgcP7vf>3w zNru&!6WtDJ(nM8Tp}Z1ZGuSaq?L2Uy%3X>1+4GU-$cKX}`9Wg(KlQDqVVdFAzGB2c zA~qB|TqtxDU~$$$v;{kGa^y5RV_is^2$``D%KVtraW$mGpeUvdPC^i~=j8pv=D)e> z;5$FtdSJ$Yx%^Jt^7u_ZqZE~sSE5~qTD&4P5iwb{VL}p^u+qUM%*_N4a+{j*m9r$na5&(s6YIm7^4kK@^}=&O=n{BbcR;I~C$t zci$EN^T^i2>pG8jL}vupmEXT|u{+y)k4#M~p_=j5r~y&mYj##K#DdKJ7a__bmigyn zP2MVa1+QvgsVXZeNK8S=NVTszl$;5P0)L#9_b+`WeH=lX#yns1a9<%2cl@r0f_Wgv`6_l1Ix{RlMG^zjz^?j_SFW(TY+J09z^rmq|65j#6+edU zRFc3?eb`WR87jRMkhsTFC{rDqas;w}ca+)7&BGAsM%2 zR;f0Jb;O`ZV5-^9?iLczf{y|EKjVqYS^mLBJT(zvlh(>_SrJ54B zsS9fhR$-pE95!M;wRI0KK48|9vn}z79$Z$u8o`bb8Y69>3^bK22wEhfqMS5W5scZ9 z(&c5}o40QMvrTmkG3`SOV3*#pwp6rB-(b9)n(`~UQ>KO$&OSlKE@Dz5be}x`wy4 zPb`3~zkkDbl9XnsSL70;(1VsnSrO- zwzS6oJcFo)pwM1`&Bb5EJ8d6eP#yt9Eu1rKsv3Ejq)YvdLa4f8(LHiQ~*Q-rLul;-EF6XO5X$xG?mj$j%xIXf>;7;s-BCLGpFLOC!2zqfV&N6#_wi%im;{f z>nQimfj|Xi!P96alO~tw#)^WaXld&~Sd1tc3^T~;c?=i@RnmyPbb0yO&z`G$MUk+o z!WynqfG%FtQnt}VR^BVhhZlU_{2<1$YE|< z-fY~COphP=_Iyy10FmuDK6DbVH*G^uh{7v*;S$^!Nets$xD#8O-^IO4zKIMWQ&;Eo zgQ$@PP~tB{u9%5-xyR@cnrga+%9G;7b7}!7fMpbAEro0<=c}(~p{1(r(j?YJ9hjF< z#-hgQuWGuyj06sJ9l)SGhAdk)zFvMU3Va1<9BRaSEgzsa8Ndr?UW12tkxa%Ri4OFH z`!GtvD6yB|w)tC-?aaoB{*!p8Z3kL|9cUbG!HS$}g^ZpzSO=WMhB>|>w2$>Di4~%V zpW!~Ve3|l^RCC3dbMux!Gx`;mRV^~7L$n;0lBv;X2C;ybDP^B3DO_AVkv6@aw73%{lU7qd~ZL{g;}0%FM| zq6wwSW4GCjbxt!hJH_&8`L0~pWIN)Bt5)5ZZ|X`+F=nACi5_WAZG}Sy$4j$m%aERlDv$E%$ms*$ylNg`mfKT!xC=Wsu%-Isbl)fhV z@lXi7J)*FN_4@bifS&xSTr%kl~hp?ugzuIhjgj*u84bXcwGXv{}ce`{1>MFmNONEjhHq3AXx{Qa9}w}Fw6 z+WZ>WVVf2&V{=9LL^lvi@PJ&`B$JSkl=%w^ZW)p?Lt>ju_|))7rjzuVeP9=C`mR`* z=A;xeMT|u7Vf!BJ>iY~aL9H+o)iY76VlHxYGRqqj!nVnG*Qn!K{o@oEz^%1QUjLCcv;f zj9o2zP+46D8+Ri!@Z7{$Bhk|Bx~vgUol|Q0KLrCx)xD%SEh?)qo2JKl!9xXr{WzXX z%z*bO(s{bC5u=GQP)Sy(3e^m$jGBU_*if<#%>`}P-S#nBf^CQ*lUOzAqoYss96-gN;VsOU=EV8)-!#GKM0jV@6ab!RId+85wG-h?wlBRq_yLfW;_9 zn1b4LeVde>&|ZyJxJWDtxQVIjc`Bn%(KF7re-824zNtr^%@z@*x^RAUcd9XWq0MsBL2? zI-yFJIlE#&Z59^O7-uROp+Jy=`mOMooq$2eSec%w@JM`2^&V4`AcgqKTq0Q>in|dd z`UZ14%vKF!6fd8C9iO)D$I8-bROFN+-;>V^ypd!AJ;70&==~H2JC7nj0)V7uO7--U z3WQ8yGt{(CS6H!vVx-3{JtpJzKi8iWa;sEn0w&S_{w??c_B?E!RX~gDkS@ILocc ze8;1NHJvEVK?_q^Vlv6Gl68ASOp-4qMbylyMz+msYQ9Rpg^V0`kM|*hgqqPq(B(NxJ5x!Qj zna8EFYM0U>#*UBEB+d@ELADt{Q9adRs+~@%p^|eQ`x_%1u;I?YiGn4i`e|W;ON%Eh z?JNYCpkXu*x1+eQU<$a@3M6l2vtw!YBHXd~X8iWZA21}3ar?%AmIQ+0+*0I9xfmHA zK_C`DLQd!ta7s?(dvYPT1$2-1V04_Bf}~Q2Nyu23RfW5%Z$geeQ#BUT)TbyT&=E9^ zc0hJ$(xXX|U_NXT0S*m}o=ikyO15ISW8koY2^I9Cl)Q&(6e&{A#$FnRnz15pF(-j( zhk7-E#~dPR3s-kZ^&{}%WL6m_x?jpctWO^Aq&A~Pd3M-fIz12 zo6tQE0S{ryy`?CdU#j$x5u?x5_<^!vF3E)rm6wAM7LZ6Ot$9YAH7(p>$^_Ql#aPt}wlGxWz-3vwLf*hPQ1Op=Zc5_;!V59akn1)riMqF=(8A%%6c5o8SBU1z%gtr zTmu`i%`9oH2H+Z4+HZ`uaFsV}?mnfnES30Ja54=RI@J$0VNc&N$X?!x%)!@h2vcKG ziwataY-9aPb-O14#$4vnm-jqX`&S!p1BF9h7g2eNmg*o-Q$CtKV-aZ_`vS*M>?*** z%yLMk!rM#-wf;9FFs3?_tY~&@yPr2-!vffN?+87;{lKpl zT)SeU={_mTgrJ*#0&{ASy&H>%5lzNHW|)$?SR>Upu{{jLgLv)K`{)rzAWDW&r5c+z z-`is`S;qU3w*LQhdh5PX^R*^1&VB#YlM_I*~Qg}oM z9D?&pfaLr`Pu$2rXLty&o%#T+=!fVOjhh%O>S&G?Q=JX}J8<4U5VV9PDqzdrkWgbcP{0 zCAF`DYTfX9>$wh?#^v-FQn|!nQ_mBpx9;mpy>{A|X3tYw>lWX9*>(V1w6jbKI@Ajh zHRZ!z^IX|*kg3u=R%31@h!-}fc{V&6pcsmWv9oC}_70we;1xk6(V9WkX_b|88T7)E z`)c|4=dV5^Cnn$FmKLy3V2sxNBDK!(TwHwQ-sQX11X8Q~Dn+IgQ zC!cahaBjQ@yPJ-}ZFgZwQ8{L1=D~0C@=hGV995(tSei7+JgqGwnv9_k$})MFKDQ8M8X6e=_0C6s`}$P4Ona}kRdoR$5Vu| z>=G3DbK$eQ;k7vx;%haP2*qQ(pR7MLg4UrPG!M6-KQWA$LxAKKA&QdT2ST(46IB(7 z#Ws;NOEy$88Iuq0`tkD*hx$jSq-oOv7VI6SyB~Y?k!yZ&?`qK|E~92j&fkdKb~$7b zi!&==CpI4B#;J^f@CXifp2C5FGZ?i+AY=)!2}*i7X$J=7FovT|IM&gq+~EcZ9?=OK zdnYQqNS0;ZPZp752+MI^)8u^0%`R=@9*LOq@w&rP?W;K%s7o%<#n=#Re%#Qp7k1v; zvg>GQI!w-czhvVFhlh_mzw4Ie-`>0nASFiDNTG>L1@mn=$oJ)!dwM8DjM!1DXA(8;q#9MADe9-ObqgS> z@uymYtEqXAAl$z9)IEEje69X`c+BXI+`6B?e%9`H-@N$d%UKYbr%c+ocQ%3;UOe?a zddG(mm14a4KyZrOq$)9+fGSrBdZR-KCY5~sC7xMm5BKvH0TMdObV_mT#LcjD4y^B6Y_1DxNpw&_}BJrXqxEK z&7vWQBrQPc26HV{o>Ju5GjSx?GC4*xv7t1{>-bP(*Y~$Q@YHWuEIpHPK~EKU|Dk6; zOU9BnEWY{j*Foe$qd$T|5U8G6H6}~-yWHOD{RIDE&h?n%EW$E>IeMZ)I5*LQOv!^9 ze-*!D_rT~`Y|5@iM2_>^TK)Jr_$4=L{PQpnAH`679KF#I6gjfFG&zV3D>5n+RVAht z4`S+y)F))V--(Y%*Zzj@Z-3ya-^3>--Q{<200Wn_-+dAfM>kjBwdqxM+poD~U?zpy z#I!t9M|1#nL-n|&Xg#uQUcA)v5!{js56-<29gzW4x=SGv5tsO8^NM#zcmT^YDsgD^ zELLYNz~Rv*Y{;p`zTs2+b)-Fn3U?7|{1rGAY}YSJQ)z@1HEj%a>^=FHfBfrz+BQ?k z(#Gd{GRp3sy>z1QMC%nBe)6qf+TD&@Km<|Y0H*LZHtV7Q#zw>2`}%thH+}2+ zUq84fr?TV;La9f;i{B)1=BZ19$OH5pfrENC42uk0q7r{PL^}tK9hYnO^Ycu|QLb|A zi38boAHty+whipZLvwFLC>g=gU@Mk+=5S9txt3@iBpDhQ`St()@oyh)*>z-E>M-5- zLQi)ZZ6A=hzkOr8d+-ZA^Y05kKP)yL#@;92*ne*4(RE+>+na7Hsjd1U zWOlE3N@aoo$3q=BHPOXOXUs4MCm)S4I>c^82Oz_VL zVse73Wk@!RbEUfo$Aj(sIPJU%{k(({Li&fAyPiG#ukSqFxc$?<&tt2m8W;T;h+PNH zPP}!`lh2f_n*Z$b`>(ln&bq}90a%6e-glv>?eBX&R&S_K4nG#^#HmoXsR@AKkAuh6 z!!6}~_I1-xW7pHie)s+hXWssJBsKYWF~*nnl+CXF4Y98M4R2*t6m460^SYYSHS=%C zTR7)x_LNffIfavNt5j1!)~ciOnR&=YwS;|fZoE72Vf)^bTTi{Vdw1W_rZ4rmu3!3d zT!))`lAk>O3hPTa=qt|oaoNV|lEUhFYx9?s)n?8qTm}&KY>Wa8L{mja50_=NI{`p| z)to~EBgcCVHy#Q!w13=ISKmBvq9y)iuR|Mu)+Yrs4^{vC&W`%$cfP`IbYh>)UboaH zN}|_SlAFu=;MuKDx&$&42e9JuP1^@s67{VYS0004lX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmP!xqvQ>7v;4t5Z6$WWc^Qbim~Ef&E-X)CnqVDi#GXws0R zxHt-~1qXi?s}3&Cx;nTDg5VE`yWphgA|>9J6k5di;PO7sd*^W9eSpxeGu0f31FB{j z*;GO-6j#N-D+Gk7Vh|-}>gn8K9-iy#9zMR`MR}I@y+2n-DVYrLiNtZH8y4{f@!Y1R zbKWNov#O*JpA%0T)FAOA*JYRAI9D7NcxKqhXBUXW#A2n78+j? zIRZwufs5;&Chq~4JHXhJE*X*|`Kg3*8F)XVZz=+#x4`h4JGbsRP9K0g&1(4uI5-5R zDwMtM@$RAix&3>mJHH>dWOBklOcT@q000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}002=_NklglQfyF)!sUtd%d^vrO+f?_;GVL=cH0&Zd>8z$|}PM+zWnV!zwRnPyPr$Rqf zT|Ltib{Ft|``MYE>IzTz)h`DZ{ulliP9V5W^#EQ7gUTi3e}rnm^TZd8xo(6@slge+BzRT2?pt!nL8+aBZmN zlE1yM4Zw0r=@JUC&(#1z{69qiAYL8G-0WJ)&`U!w4Y`0UC{hH714safUG?$HMkvq+ zg5D#~b{;?SY*#-h`Uj5;PsGRL>fn)K8jmDS^>UmPc*P@F^QuN%{ZE(G0chKN&Bo0D zE(UNqfJOi{6!5b1C<;Hz1R3mFhfBmmtIl7kt~!6^6euD9juYUSo*hS@oEVzyeC)e_ z>hIZkOkL<4U&`=`M6l(X+R5ww?&8|b*KFJX;0gd20AS>+mNU4M3zAM1+5eRc!Iy7d z`bhxYXJ5T>7l0=Rj|~6m#U~E+|MIp6(kFRrCmdce2)60!4X*XCTetlDcWk*xN2qfd zu32O!9Vn$m)T%V?Dn8eCyIHO;I*&l3n(F|%7NCFAvbrJKvbtgK>;CSd=Z-wv_1KYT zd-ne6?q?=m32gLbk6<@{|Hg*R*KE8L!1Vww)LGvwREm^`66Mgka_OP-c|>Qm^#ESW z{;xWJ<;Pc@-*ND&Ph9r!;Nju>|9s!`haUg#lesdV@{)s>C4%WJuzu6k8{P!qCQ9jM zeJ&@P{pr+j-d8&zx*s5C0d!;Ys>Yk%a@(~JyydoQe)RpDf4pzkgL|?I8|}%5mlcAY z_x4x$-uR(QH@2*9x)#8jDW%H+dP)%M!~!J%VRLE)=-&bOo14FX!_xqM_1yj2A9?g! zPmBy589CL1EDK&12)60!4W74t?%Fe|TdMvMz_papP`OAo7Yd`DSPgzxM*q8~)+a3+tBD{5_@g5`b1a zO4zeNDRdxZoO9w~PQ;g;%rxWgY`S{GKW@5u!w+^oxaViT{``X@(f)}OH^c?NOA^60 zUA;km>*wFJwx*@(Rse4WP;v5}elof3ytD|S8-36CpLO}#rmHvJxaz!>UwGus#~*t9 zdrxLg%sA%{FF6Ez>uuKrUiWvec^81sP^vC5D3-?Q=1ylAi!2hQY4Nsc=Mc?S|MCI0 zHXDPr!5?0C+ciJF?zU^b^@WSS(lvZ!cb$_4$ zWv5TwB zMJeh^?R^oVl)^bGeq@eAXRK3g7BO0;dF&+$%$~M1P~rdjYi_*Y^4HvW!I!^q$yfe7 zd}QR5x}r`gf>kwF;=5*Zz@6P2hY0d%!|&t>daejzxvL{j_x{kQjzSWB3Rq$E#$I~zINTFt2cZN zz@>A3eko~vj<8_-m@oNTs8?yGdkd%8SONQU?f=MU_k8f~_kRBA|9bZSJ@mCllM5Kh zoZzG(*s@LSpFUz<=?6yoEcPyalj@U&h*SO&ajaxtKvfRpTy2K zeSmt)Syyi)e+%-JpMUmOCp;wRgdAln!T!WIxvX>Mvh&nN!O9c6`8ZCP zrb(UeFASBIRCW2-y&$;eoVUIz(72-Eh97N)&h-p~0Ua8-bQ8#B=t0hGdZAoNGaovWiHr5cA{DB|7|L)!yo;WX9bOby5 z>J8-WU%c+dP+jQDTG|&JR>~^l7wv^L$of~iX z@%r1YxiC~4{0ya3LoRB2%bYgX{En9Vu9PNV-d^8TqA#xfq0UHbyDzn)n69PHu*Z%@ zTdM1>7Af40_Bs$}ZPq}JQc)y?NHZuAnvn1Gy`vJO5w+KExN^h44j&o*%+{|xvS_?= z(GaZl^cM1o2S0KNfNxMr+xfv67GTkY4{H5GLkUSB5KhQdf<@X$9d$5qID*4eC{Z04 z7%3pFacPOApgPu;B4AWiOHwz=`C};(CK@s#c(Sv7{UA%KHU7HzinK3-iohNU=@Vr;d@4Br&NVmh_V?i$TIfx1q`wZ z(gdn-k%1hHJ1M%In;nw~0Z{;1l|iTknYiJWyzojscx5*{#08(s{(Iq(yzs~#NRp&c zG@`L`m8wt_1^K*!jG9MA%^^!O$j}VZN(vbz1BK?GA`eRPP>2eZXjDZTvIIT|3#t)) zPKB3*n37?!s3B4?3TkQOJpO?Zf}DE5p!FNzuDR;Y~yqf314%S{dPg31TtK3 zL53F|1SCHyJe8>N)u7T>4Zk-Guk3+Oa=}9+xHt`y_&3kd+l0i;V zp-Ki*S1eShNcAPcI2_iL8Z=)Qy)+@;NynxIwm?eDm;^Yjv7_nJ*Z%99ZhGMJ|2=Q# z_`DG;R2#%QZ-0A7xGwZ>0D|+qPiZiOvsuIdk%bC2FQPK3)dLUlqEfCzU9b)f!FtsD zY7mlx@DV>`B10wuGqJ0KqUl1H(PV>~QIV=plif(1KDziZ#$NqW5Y?_KwE0_*RTYk4 zW9e~>Bu5aXWyoCOFBiPM%zpt)&b<^#7rJ53ysQ9>505>Ro$bPMHU*@@F>%W{C83lf zoQD8@nIaVMqrqQ;6_xFXW+yS48prXe0Yowpq-a`0GKq36R9gr^!6?UELJQ9}*sdd* z&ZM;zzz5*dZ~Vv0`nsO$y1)DRt~m?+^Fpwd=dF;IZCd&s0B;a1HpR$fS(O43sh00i z&ld!mAFL3ud&$%NYNMt za1x9PgDENL7^jFvV~uM|kl}_`@+0UAq25=IMqdMtPY+-uIg0TdL$oCFRM7=-$@EOj zj1vON3+rAy%JMKvxV93&Kc9K!#;3ZU?;0%YLILK5VAp@{P3KaIPXokPI69NISda$_ zZ<;7yiHl>9E>d)@U3KR)i?J>0f=6|s&Qpsem8YRC)P_oL6?~G9i}YMnw{SiyqLj3j z7g;lC(RZ_fxShr<40h^q zN@`HKQg#qYd@t6Yf5U|z?|#1PlY4)^TPbhm8q68N-u!RZ1X|a%ep=7|nL8M)(Mql? zh$QY~5n>uj0Hs{JV*-4oREg6>Lo_V0i5^>_cxci!=>zH+BOCj@)XH{P{Y zrTAxV@tp}-1jHy%ox*QTev*phHuEDfv>?jlUDE-?>`m;glvIK+31fN1Qmn0Bg*s0? zyu=HMN`;+bl8Y%IONGOw7IO~b>--$hr5>lRq-pghV5&$Zabs0*8S1>1I27wacdQq& z+%&S>#z#zJthOY?G*k$Kv~UDs+U*KT12?VM=Pq(t>zc4b=PWySBdcXU;8(w|SzK8bgD`%c%BiNR=Zn=O` zyuE-Olz%LhI%cAVsL=>65W5IgbQfxvA2}W4uc|liL8G^htN1G_mZC}ybE}iFD3(RC z;lHybTzuTgM?uS|MfPuePbIjC8`Z7~oL;>ORlW+mINpiD)F{%-`6VkH!3xF}Q_|A! zRXk^r^AL*}Xa@b%O0nygpS$uy%gI+dxl{8xh<17>k%pSF`*V7^*adI9`DY*g!9Op( zb;oQcmxW+Aedi`tD(I5AjABmUAOmQ}B@jh|Pj#cwTZ{GeYp^8P3O~G@ZWX_eb|5b! z1S<`iKa{adFIobvK!XI=xC=)U{YXNABIPt=Gm#BH5xt%Z$ zyJKbx|Evi1s<&+MQ57EpL6s$+P|*8}OjqU?PH#;?#xhYu#}le6J^Vh*BCi5|)q}P` z3s%>x#FAheH=0V~gDm8mIKHVbe>BrZ&nUK^__$}n)8Gb1R2)tAA)(7+FsQ#|#Ds}g z7feK@v`WnIn%aQj`}Iw0TfYlnMk+Qdf?f03Yc~SqO}f5Pw0+dnV8oH?ZxDgSU@A_? zZUvJdB9|8Zz>KG@{wADWzYZE(|`C4m$eD4V^Xc)9iejD~f{kLJ;v z97IaWX>TO41`CKtW})>CNH#~PTKk6eH=c3j#$Ee=zq@2e&x{Dxe)dultPNdFK?4>W zf<;I#=y?>yBX#mcQt`O{+jRZtC%CE1Z9%JQSE0q<057-5>*tg-6U?Xqy)40*tx;~6 zZSXf>b?qulE4H^|IN>#56;~jbtj<4C`E#IK5_-CUX&=B`)B9fl+)J0piDL z!4@Ry63C3D5mjPPC6%*BYEmw3%~aFfrvILUg>?p4y5#I-Z*Ayk`p?nMVMk;riD2z# zFU7{I&U!NiU19%jArwLsIgKOY{g^n*;DIqEX4)c+ys;SJBzz088gjZmBMF&Ds1!St*xlA&u7H1}j z?vqmJzsPCUcJs<&Sog~X@kugdgryMHRINf*$zy-y5T=#57M?9>Yg25H7vleouydO^ z%vsncV(<+AArYLh>*YWF;~fvjoW3lA^WSr!n^O8VodgyhDqR| zF=P=zo+X@!TV{*CFg`eCC~3u2Nbz+Bh0_hRdT_?Z)2}$IAg4!k6P$sh@MB_h6_t7S}~T1 zA~BK1G@aIrOS4#TsNHX=?@uw;FQ#?+Jc11!O>YR+gmxyP)~s+x1l#=9Ef-Rt$#F0< zOq9-YPQf-)hz4LkWYvW#xf;u>mLlW|aziR9asd@6-op2N<`Ke{bLl9LSUt%O_L*5m zplfjpMlLgIf^xw>Ap6i!vkar@D7um?);}w(ot5fAI65=WasG~254~~exgB>Lc<6MsMb+U0Aes zhVjj|Ne;1JmO+UDVbFp`*rZ+5g(hDeI%<}3^91`w(UT>l8IhpW0+cvkL<%#}qxde= z=58v-Fk+EsW<6h2gce765#>{s&=MpbEDJZIe`*l%=_GP4J<>udAfr|DE*^=9MB)Ss z#@C__1eK?qy^NJl|F(FaA_P10%CpV{l;w*s?_w~5pVK~iN@OJQ_W zoQA=v5lrS1$h%Z6w|yRuq$OSl3Lz?+a9q0bZFjx*zkdGVyUpS$76fbPXkzDI0ct&N zw{Mj^MvE^J*@1yvMnD{U+v@%GXscKPmKG}!$()8X)7w3ZAV`JH77f-^r=)o`&og(@ zDogLzau{5a3w|jCm*nB&Vq+n~0#box6xNhjocGYHVB}~XDK(9>nl=-4-I5zV$D1twmG~-L}PQ+0KNV@0W@3$##%P{c zd`zVD6gVqb6Ji0WFB+Fv5b1TdUS3OiTVi6X9c#016@61Anwh`E?+b6WwjC_CsjadN zm99$e`Y>q-g>5V62L^d3+<(p@r?NbSe>^^p-bfFIriYQuXE`$Y-9fZeEkRpN3#$E9 zT-oqA^g5-szYJRxqYqhskaoA+%PtVo7Z)8UnQlu#6|_ zF18mycsu4ZUyirh%Mm6O=%`MNB`2rkJ~9#8|97E?Y9vP2GsGGwwc88o$!sIt7w=esV-EK3N-r~;3aO8Vwo>8 z#SGJ#9Yn6g{BRj$(U<7Mp20onjU2;dW(p~q;&m)|b`o{tz~m9sjn$x|b_Lcqoq=X= z1CJ;*JP8oSXI4kz8BQuPY7zs*WA=nr}kF!O25ti8NqC(>koF zTZmK~KCNIW^8p6o`8w3hnmQc8aDj!_27ldi^~1 z$64*?bkrREOJ@`o3Z{+dqQ#Lq?WPGUu&kg81kqN}#H-mXDu}hU0A!%xcwzw09(@)E zqlb}nrL>W$l$RJF++(1J97{l!WEZWuY?2 z;mAY}p6GcR!?_WpU3o6=GPWyG7l_I-vlXaP4yp{~kjI!hfxisB0H4Q)vl`Dtm;`i} z&b+y!a8==Iw)rk1qq(9HHLgm;vI!waZedVL@Mm^LV@=*_has_;{kJo`n*8W zLnp9yzX??rf8>fKPk!?uo^@m*Sg^5Sp9$w3?%?L@GqIv( zxrSi*H2Nm{uy6Pvj-~sNMhbb7$MIM{j*NGs&R@?9;7Q_QFWmNOYU8Y+UQ4(R-fzi%NU=e@Rz4j4&t1)v$3UV6DnL`O-7*c^tMI-vRilLD9&u!fC^tFN3c0}yq{?a^gWOWMNP00Vabo_d;(M!ut_Li zMMarRypNMMDJZ=5^C+;!IA$W)Iq$x(jZ*5x4BK5K2-=Eg%tU@oI}4Q%bO#aghPh~e z0#HkP9@icf#Ntz&B~hY4Rtc&+RajNG61Bb>cuArEshh}H5^l$`>SY)mjv#}S7E{IF zQpLI`)c&$jo%KsvX{MTX1Z6*GPux~UDEzV)?bWSl2{vFjHG-U^@V9?DHH}mz1^8_G z*dhYah5hP46^4^hu2oYagi>*vi3 zBHI&2INS0Vb71mGO`w)nzTv@yCooWt)lp@3C}!+rY=OyM6`l%I`?PFukOG1;VLu=T zQ6FxAcf7gmDU7mAGOy|rc2`)EQ?yDMG6GT%HGyhw`d|!|ZL*>& ze2h-o_Tqq6b=xEP&`{Ng!||h_G_M(Xi`kUp5X$G;=9w%|BFqGR5y9H$F?Oq;qzuqD zp_0`eEYL4PEryE4$+Ff{>SbBaQj$Sc2?{S#BMEjnU6x>}UlQfEE7fd_XPASi4Z&>j zY=Bt-QQ^DhvLLVVcC*?VSp|Fynq679k-22u#Z|#zJ{&{53psg&~+oc}@T{ zup*cyf}MWFMkX4yS_WkU)iM-fma25BB5fpgQxOMM7M249s24S^3b@QDH^aHCI=n)& zthB@0P~BD~QI>f_Q0Wiz%xFTH%`1ng^aO_DLud-tL#6?VY)%qtL0D``kNf|q=jP@Phgw~UHB)9UMMR9zJd{fb6KRnWAw+W4&e2I z*+tNX)m|VVuSq6L1$)M2%wG&^8uOZM4>o{jGZ#dI*=a5bH|=X$mhe-s$~ek&nr-nQV*IJ5M2tE5pen8QY0vp&d{pR zIVZu+v+VM@fSYWGd8scQ!MIV#(d(>pTCsXW+0!aQR0{6gmP>XKn;WWGC#Z6p6>}z! zXD9G<&o=BB*^ihM*9@i9pgNN77SV-vlgf(LF8wWaq^6~|#9%UhhQM#ygG6R;F&Pn4o`EiCnzijMi004&Y__?IJUpy_96570wJcu!RFLa7(9J z4wh*<*sKtCd26QYM8;#N&T}PJr9rzRqh6Dl7P)Mdw=iXGZsks$Aj8UdMPVC5N587EGjN~(&T8l+$SfHhDa}nx^iH*JV{T01s zrpD-G{w+SDcUj^>yTKwA{lBZ|8d2OR@fkvPG3?za1UzHES&{`c5)aC^fH;Df-I!9c z=p8%8-8@t_yb*>9E()>Q16kl9Ga0ZBY-cu~fmTloR{2+AY2{Mv9@vjVkwchLVm#`B zZG>c!D2dY*v(pz()N#YDx>4;8V|~jSY-~LPb%A;$Xc}H`0HZw-9<$Hcp(UIgLQ6nR zNXaT0934A`k*0BkDuQ}jiNylSo$H3E!mR_g7myYl7bOJ$5&~s0WFR0I)1_H4SMOp? zMH{V^LU9DkW_5*bahA=XEb(j{!&Adhc)<@%(TV2;xetc)>n&_bt|x><}|ccHuFZO zj8LRfQ;1GZAfL}^89jPc`@*OQClwmoqPiwb5KTofk{rX5$|cNvwy0uKE}PLi_FCiG zibJs${8XMBDI!>A?$-SBpuqbnvbn6yt+XH}X+k=mLOiEc__N>2LTo8D+afb$97&Ag zFFm{9Ug5{G%4NLBaHSl^y1KP!uU>-5Y!qYD;~0%a5LZ&jDGIk!c_bN?z94GD)o2XX zquN^o4>JJ}nde0gCC2e==XM+zIgG43Z#MrVMWH?d!trjsD$-I0li8S_v+2fsfjC$N zGTAJr-bMpgt5i4-qlncyD*~^AVhH&emD&BwhuC`JlrXRraW~srK#eY8x}41HKB;_0 z>z{4PFH~r+H%DdM=${Q0sXXhGoz{hOBMPDr@nMGg8s#O4HolaUZ+>3aN*O`&u!g33SRpf9X4O0<@-g&I9K*A{J8^it z2YGiMR8oz>n&UPWQlzs6LNEkn?U+^GkZNvAV%reQ&M|u+^NZ$rf{Ua(@{Rc9a-=J( zC0`^Qwkz3UM<5tlQwB*ZS0pMruY^3MN`=Ern~LX?T3k2+dTJeYK;bz6(PK(wL)KHE z>V;Lb+Zr}Ff$Zz8X1IbVQDi(>^rnts{6G|YE8DQTaRpY^EkkXf8a~<2qg`cQfeXB` zDD>P#u3WI3NF{@bbPU7sQS9qKgcpYnV~R|I`Zc4zHkRV12ab9>)f#^H1N@-Rzr(3nq*nb4<3qmE`dXnT{u2D zfW7?(aa!GJJi@icUxf;95Pp}3r~NajiPc0+X0w=1Cpnw#8SBMJYz&jxNn~XOvR~5* zE#tKnjG+`lu7hsCVf`;v7s8$}f7U|5EPX&J(rS*IVTf#Naxb30NXjZeMqnV=Sm#gz zm!te9fDX5FK5l8Zz(=1^a+uC0p!z6}QKAdTDl)2wF*8Bf72xsqBdG}TEF_qyno2Gf z7=ocg7sxzNh$K*53XgDzDS1q#rqS7Zl;=YR+yMk!9?i|dUJ0Jbtss@pA~M9kV1##U+{3+XZ%#Wm7wwfHhgAqcy}JkyA2otnb3KuuEba2L;JFqKMx zxQJQSkQO1;qF@+JMy7eoKaOBe-T6@dH6OWhWHIhs@`?N>L$EwznS`0{WHv6J7m232 z6-wekjEv%R_VocQdeuBjwYYmMt{lOpM|BUaCJL&2WmJ!fEPLx|5=0?Tb5t*!r@Q|d zg>gxcB^8pPTv+1Vtfmo1J0Ym$GmE}xu4+M3MYHDep1}h#`}!27%GP@_9p`zXl1HpYlu_h}Dkv)=TcSF`NxFrcawj=E>QZ&vnUTWJ0t4j& zFVVzB!h`HgNkdmubgPn%czQcQD)={x=A@&wDfbgds)Pzsfi=ymP~l>sJB4MOtCUL3 zz0rZ$mkY!bEIJ@l(JbCnaOe&L5Wt~bIUC3x*9;RGL z3i$<`eesWyz*!3+Hj-ekEtmkP&VpnU!9X>0tOda=D+6;pX3&7bdSQC8u4OIO)U7~J za&ZJxOKxPjpv^CtPvKakpVtW^l2&JfkQrD9Db&ia7%z&BIT>D={6(fABG_o>U|;>p zW>sr(R!;cy{D9eDrn7NO=B5$$1>l)yoPc$LS~y)u4q(G+XJB}G47*46AVD%b?i{cs zr|6NYME5gE#GufISw-b#0eIx;EYb0W*H1FTaCj$Kqe3J9vOohwYEY2*DO`$-W`8rz zK5ZjvTva^cl(R8XphELoCuZ+cFqw(-(o&jPO=Qb9SR5gLc*ot3B_Sf%!H0MD*WYsG z6hNy_WB~)JCs>RmB53s0^7g^=LNQ%41Tmb=5U@D z8OuU#xNyaVSW&qQUfw!K1B(bY=gp^FAz>legVSS}W^Ob~!7e9iL~P&A3yuu#?&Y@? zA2&#WalQHXEW@7Pcl>)6uB@an5F5qviY4%SeDj)$xfHtLQ_nC&fXG-~wE}eYrO52d zpflEkB+ZyrokbR>p{9%5xoRrvc!EYckwH9>KqjB(1?yOqW-9KoAXXY58MR?Aid&N5 z_j}Jm++VI+He zdJGe(3Dmg5+=#hw(rhe^#0#&js9uUoR=*ngLn=CB-MspsB4DM_E0+~WNv0EAaIdUe zidCnr;9<+LSPY}_QB38hk!IcpC2y9))QxG7BpDvJ2NiM~|yfG)gErxO^9M_37J?oBcB z7iX)VZ@*QUkUjkH&Tium6TyEmo4LD=v7XFB|nnfy`;ZFKoKF5*Fh(_?Z-SByR2)KN3OCF3Q#_)XaHXNHghFC6! zoSN4)#X<#FF4w6tf;51YbsgBUYzxk4=+MfD>T=giZo2Y8qnK$HWfJK}G#As|5L6Qm z90G_T$cT<&iz7l79UP2w4IMZB5D;vdP7Ow%s%Wmt0(5bsD(nLy5>k?aqf>)eRlfpZ zIiUAhTLjCszA3EFQCJFNW8;~q307m*u^sr!(QOz?k0P&oU??eQ#f){uGBF%V96>gb zMN35+R#q*8M{)_pxBf`x&va;`st|=0`FUI5gIal$#|A z38XSfy<|Am-3B^aq%uNs2rFurU`zX1Sl6@$4Xg$%djhqF`&n$kbJ=m5a>%G}=lD?^ zPmDkbvg*@DsQSVTAC~8lq9ad4x`xa?-WHu=;Dz3SHJ6>W3#@>c!>X3zVx?X(Cuv` z=y)$uxfG9*FibP7(?~;A1F8cd$V4^s9ZPLCe5sX3X2Q6vQw$&1P9p^3-(w{@BaEC{y!o+p&oe){^S0Q^nKR)5yl%k}`t5#3Cy zvPkxMdZLQq^e6`6gQ%(s!bgK<62#(xmSxBroe~L4gKcPRufww1B{(>62)!dmF*G%d zcqR_NC%{9Uw=Ca;mQV{XP67zEA{^KX8?B2HRJ(%M)V>jkWCDAR?Z@LCe)OluL48E?Na$}1A$ICP zili>;G!klm>5JsABSX7;kBJA0kZ8Pf_=&oXrbz&G&eNF9>{#l1t9^yXp-U>_Y7*TO z$I%d|N0Y~+WkL(4goO}tOIJjqNqKJ8zD5e7BfK1~t6Gs*8pmW}0-0QzYlO9-8eaL@ z2QNBs6bVqhSy2;5XnfX6;{NU?859% zrgX?M%b{W{6~)1k9^_bLhufnSoU^Q}@DxHyaEmgI6(~C+=1(2jx@%PYx(LB~o_TSg zuA^xWfY;7ro@If-2AB^pD^VPakD_+sI4bL_ct?yva_nM1mzaXLmq@(pMwLH^R)0ew zdY@=@7bRWVo{39~RD%of#Em*%Eo%MMT66@}Os_->3M+DfTUTV^bEDA8wkOpLUL5U4 ze|!|O-(}9(cobQrEG6@X8Zd$Ofg@XYT3nY!2=>P>|2nKBCZ_6(!Ys_)ll@p$*@l4M2iL3)nuUPaZH$=tLPSS+=z*tZ-|N{%BA&kQqHLR(p(=(`5gdv3p|+_C6_TtMWD|N$6U*g`1cKSYqQTJ; zDO!$GF&*bd5V2Kcw~lvFq{{+^>c(5`iA=DcNKawgv3(fIMnD3@3~hG2+^$s2GFJP! z+DYb-r@9~CGim?Y5yAHT<}Z6MxaCS_?mye{Q9^imQ47hEi)b_K5Mgr&c+%J!}X|_tF*eRgv@&HxdCzdRWvQ*FX~|N zE?Q(_{Xi@TR{GlcPK64~F6kzTEEEhTA~-PIjhvSWnJ!*)*3?slS{z21Dg(hR1GAX; z9cJJxl=khp_fNZ=zHmgaNY@a?JBRM8>uA0aLhaUhfsJq#4pK8bhJUHIW$8-vqkgg$ zzM8eDkV016UF00WmkX3)VbE2#94Pt|5j@qs6GPc3q_9i3?GaI!oIlKbIUB-*N4DeP-N-OGF9;iEcH34?Now^_|U|E^=~_(IE}s}g6+8HkGb`4z2FCR9nEhCP&50I z6?1y0ann*~=vnoOL@}I=V9)45_}yN#`s;WJZhP&7lLd=u@|{1}6e``+z~a_eH{0!f z`>}tl6Eq}2_R2!3DpJIf3+!=G=EkVkueW_~>%LMalteHF&))g_{nvc+1I)62EsFf_ z_Kl`9Bbk{$r3(CCqim*_soQI^QXXB2KKMu62)CY%8h7R5c8PL=61Of}lRN=nc^Peu zI2dxplr&x#JcOMC`;iY)xO_6_HHK0`jDmZjqT#?biJqBdpH#6=xQN|OgOKm~*B2m3bLg8I#YF8is@)YOh2~c}i0q8$FQdXuJ9+d> z^kc`d1Bgo*5RVLJB7Z_xZO5*=|4@>8VKxMt9-d^Z^3lyVU9!L2R)6IH5$tGAz^gSA z@SMY}s+jNCUn7EvucKB^gJPOyc|^z`JD8rgXvsfx*O~;xlq~j*_2Ai~J28+S2dQxDZD|VUapS5jrBd@n3g|kk z?ZwKT9pHuDC-*&+ipFQ0)2s-_OcsY9-u2tnm!EwrfHPp14TKTe`~NsMc$(=ADqJt| zg28UMB#%?WY^tlrS#gb{^FIJT-l1bpuXg8kj*^V(xL1t{xBb)kC z!R#{|iMRR~i0LEMk2$!OY{zU8f)b)=;jjsDmf{yLFh*P6}E77nX=%`sM@Zz3DR3j;6W zxnp|~MFQ>$58Q5<*BetMQ4+Du!DgZmTI`u#l){)wjkV-=BLw)uQ~z;)*_D{eMlc3D z?|D3P@n_z42SBd`$g<)y#H0e0aF(i8PrYe?)qk*zXO?y*hj{BbmtH||G2m2FKx?lQ zaSJu{%Tm_IJBOpuLG0~6ghSCDBs@8ILSEij)pVl z^qq%3`ky=JGUquV7=wGRxUJ{S-@oPSl`XYjwGcGYfKN->OU$wys1YKT%dd-Gd)cl>-8#Cnd3fx5E_cN*+YEIyj zE79=+cNBWTJu{(=$Ii#~G75}hb&VZGL`j1Lyl{EFT-H)0}(*0B(ZMZ!QE&=9OfTXh4PDymWC4>xEaC~AEL&;IZ)Hw1UK&o^> zmOUDolQb=o*Uqp-q*~fK>%S#IekxvQCpoy-e&M`xTws2z^Wp9Py6?UxW^@Uaf_Wnt zi~rg7y{-3O{OPw{0N`dp!WXm_r^g;GEOy z%F`ULnz+Be6Fd43Vjv#{^~mtlco8RAB$W{yn;6FK$YE4@{AdW(pf%KlwyGvn`h&c- z1hcmp2^&Pu3MYC#rSUA78(okcp~u22x~q$O3t6_5lH=V+lDQ1Vrzg-K8N$Hy5QY=u z+?SYVrUs7;*)7B6)`V((F+vHlg481vxf76#c~0U%r2! z^bKZ)c_SEuUH3eet6I`<`^I-&auGn+n(utU0#TyIs3Fk{O+2aAX*NXsXb#r%I`st? zk^Y8JVm4A>Rbq0iuv#{b!()BeH`s}ui9w{?IY?nQTppKMe2!hf3gcw*Dn|0t7>iD$ zJ2HSkpBG_ofHza93sWM(JeNX3P4NZ`#4kbex*nsb&A2v_q#0?P7?t0B7zI zN}WS8$;kBA9=`S42j;^X4OkF@G1&3LM|w8C>k{Utyazx_`Bw_E71fICdK4F$d^Kne zXhDVs9zt(@!l?yo;t3Vw$w~A^2C#p)8@*FQNVsyG&A3_9b6%8}ngxJ4(c>xDtPPBe zJY^*%^GN5jh$?X$8y|r@EZTxmnO6^@MsG|Mu9Z-n#RI|0UbIXw*2sFUfspeq5;L=m&)&*kbw0fPlTZK0eX;pH zpa2U-Fa|@rd+6@_{&df|w_J4^fLjVZkDN%aAj{~2Gh;Wb7+bZs63vy3ygo%%k9~^g zQ-~xdF)}rVuE=rp#fEsDue_T=s?lT^Q+Cm-2%6SwVtuYrRiCq3N!&P%74s$tvcZmx zTWD;#FlGoD;;JU6F+}1ogi&bDxMSf7P83Q*eydy8JZ3o}&V`sFgLA}#2x6aE>vvYs z*t|bG`iK6%9QxRwKL7vbY?5$-ML{qI&)@Z6s{Pfcf2n!nayFw|3!U5S9wi=pV*X_m zWb>+SG=}Tp^ZPNSrZJUDVJsF!=U6X#BYl|6Pb2SD;qtp6yJUD|nXjFgX`uP$tS$41 z_@hLn91FX#mG)L`p^maiKZLpI*UV(G6U8E{h-75T8z&aOltz5l%s`5-C6a@gvgD1} z2wqG^ra$@X8@@7B>ZG~Cq9GWA```ZM=_|hR!LO{keDfL}X6{21mznd}0ja$q8ho9N;5B$OX5Xz~y$Ca)WBKDH!rxK|n4ReyN432uM~GBPAk( zZNr7Xsr3>Ev@IG!@n;>$e3F~H#^P$W=%Vu2p;Hl)vf1d!^icFu54`{O8AG7w3X6(h z44(Mhy;0dE-@4-UX9WRVQbfXx@|y;YXKYOZQZ$DhgNKk$=eg@dVI!+yWrsZai%1J* z3J1h7eyt0&B;X`3t8V0oY!&rcjcUwX{?rGq#-lc2qr5R!ekvE_BB zaaZ7n{f}TUJAch>9uUpMlAn0s{kK09?HXLv=`K2gu@Kq^KlJURSA64x?^$*E=5GSH z&WdCOv!Nk=P;PQikzrOOH-(EC2lO_5RH#W)Y)-T`(PBB2m)4z)RiV?cEZBl?ANy}i zD=G8rT6YDmZMqN@?jY}c(Kj+?%j+zRP^4bP)wCR_!aU?{aVE@bQRk^b(B(sgD}dqL zq09FnwEs*{ zmWYt;ZBn{|#Nw>{6z;})Wbc~l#L_@B8of0*r*a)0i|#U6X-A+9A(x*w`s_{)maK_2 z+bY|~Z$DPJ)67Ri2N1Qf-QxBwWwJ=y{b!jA6XZYk!aa}NAMF}+>KL3@##LQ{`%|p&m;P<8ZRya>tPD=iSuU-BM~63FdSLP$dU(e)T$ZB?mE@ zndDTG@|?sZa#T|>miwEqHnaqL}uys?RIP$W*NW+F&gV1|M>4d__d#%DCEM4L@)y$`s3a_qNkDm@bfi;0Pvq@vURyy0D!4gus701-m2t%O{&FVV7% zh)ys2q>{iB(cQSd=^|{XSb>A_KAcy*j)(2^BnPoS(Z?wQqcm64ZNUXK>$w#_kx%j@ zlO=&hT+wh2_9TvRs>a4rM+OS2do; z5t(I2v3jkS)NMd_Y6!#g6~ccPIC zCj-F@c;a*SCL*1K|M!yH-p#r|d>ugZeD7sndne2I&R7@MD9;El!#i3o;cZ?RD|$M* z9|=`sf3K=o#VHs2{7iHY9*^$9JDM)Wn(z`Nl?*@55QHH-ql}M^ZpZUe2XSH58F+oe zW=^r5n>@%n$ueLqa(+Af9QMR}@$QyOu`b+>EtPBVSo8&~2`%AGQ(sfF9zWJ8>Jong zXY+gGM|mVjF%-*Z^Iaz`A{D=gbPjytr&oP;a9%f@2b?qnW3czWCvvIi^e?XX=HIiq z->%1!iRsAtnNC%0sOd)&H9plrr=!rSCO$g;0+t4v_{K6A$xfgvJ)}FY2{u-&K6rP(ph`5?TcX}9?QiW@KF3H84E-)BQNAcYB5&pS5 zIgHc8OF4xa$xfj=F^IL{C0H3~MWee4XNH$^cFK@)Z~T}|#$x^~mpJP(<*SmWUS?SP z$?ywZ|MdHRxMNW)^yR`yMKA`PTX(4UUVGawFZ=2Tx@$XHKLwC$3RZs&oR-mQ&@4kQ zCqQ2=f)`@lT#jOwY@a%en3^(c%`(BB!Ljrxl1wHO!;3X%9~2=ZQq>VWuj{3f=3q31 zbZ#=%-Aj300g!aRNcpzrSEJEW#VO;S>7y9Q#Zc=C3D340Ov@GCi_T*M z>q|vqUp@T0=YIUmf84uZ-{M^1q$3!E@q@?J|Nh&r@9emI^Gz3h<{cmTA5ra7TF~Mm zN*lUH+TyL@8_s(5?40g$v|&l4pt&0CPSPm~tJrMM2nxu0q^+I+AllkApa{8q`X|lw z(wiQ|vlB1kvii+j>tvTtWaD^p;s8fiRd2mVDYbei<_`?RABzt~Ke6@JyABNR?m8Lv z;vzUD2nOAZ@xtAINGjR_z z%YHO(t)mcAQfLCu?rTJytAh7=ta1nWcU7(+yoFL6TnS*`xfK`A4zJ`2!$@udSrl?0 zm^p%(HCR23GeS!_az(N+Zqi_|eYy+hRIlM3=Gd5+31vt(s7~gScq+OdHSQ4l(vgKM zE!Eo@|FY}hZU6Gjm+u>h51&-7Xn|9PUpuQoyX$tFR4Bg9?6Zq^eCR3JWxa+pPf9&1??tp4L;U>9sf2U`}hrO-IX{!xWqh{ z$#EZAaxF&;W^HFe`5z;D5LdG10GfQY_^0;k_zS@96U!y>M06iiy^j8PE`i?U2x=v`r*glS=-TkD+t~Rka}&0XO5CH zK|h5F=l700#eIC^`DsVH8oT56cn>;L!`v>#Hkeu4S#V>u96%(Wz_}G#f7a=I5vkte}Z}Qt!W1*!+RiIPM$yGyjWaHpQ4ZM0jqyuMUmgYOVn6;hJM%z!ORe-yeK} zC%TMtR&EpW?TH!%U_#@g@!{wfcHi^Ju03}@>}2maW$=(z*JnEy=Fc{)6naU~E zj*;REtJZKiZy+5(cX~`{E~CMeQg-4F)!8A-vcBu-FaG3rdw%?A+3EZz6JBx%W&q0| z?%cX#ck7nb|L~TdeDeDQ{WSmLkepLfK1xVBoZT1SXzBjkwn z0s(%o@7~9LvGcnRPMk_1el~c?BA5XK+YaZyvFd%>S6;Sx_v)+9{oeA|pM3*BE(d5k zcoh7J)V>KKxi}K}G=^DXte!|__auzx;z%hOjAUbGG=>-{!62iu@b5Gd`3#r+N_m${ zghI3Q$OM3GvHtP95B>V7hr1r$7MFD&LPxVB>%Lc&=7~b8j{_<^K z7-`+I=Fau+y7cEOFW>wo05|Gwpu>y(JZ@C7hcMe9r}qi6LNUH;@>^NJ5Q~N5J{%v4 z{@~y*pFFVr&fm-{v-(uS%MQT|7}$1*4s1I#9R5n}ch+8a;ZIjywz;FGqxB7XL6*~X z&wzYFDBI$Ls{0EWQa#BKYx|wQ**SjjSby(hyBs@cyjz37bY<%wnck}@G)@9%L`+NK~;iaux*0A~+uhx;RMW=3(9p{{& zteAMm5NAhVd~}#K7G}L)hhFIVLwq>e*R^%qNcYxluNb5f;T45ocG&vS|6~;6Ka)-7w83u?)hTi$dUK-K|dtsXMOT$1&=i^?$fJ7J%LcgFJBz(?kMWGPFmfAt7! zmd>OtAIVyYf1M7}m<7zSI8;^N0T*hg&~)!Um|=00000NkvXX Hu0mjfy7cV* diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 5d71d61782fd1dbd5fb1b33b7cc638a472e31d6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24060 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%0Ds`kv_ArG75H-DjffyH})L=0B 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 Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b..00000000 --- a/team_b/yappy/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/team_b/yappy/ios/Runner/Base.lproj/LaunchScreen.storyboard b/team_b/yappy/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7..00000000 --- a/team_b/yappy/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/ios/Runner/Base.lproj/Main.storyboard b/team_b/yappy/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516..00000000 --- a/team_b/yappy/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/ios/Runner/Info.plist b/team_b/yappy/ios/Runner/Info.plist deleted file mode 100644 index c90a827b..00000000 --- a/team_b/yappy/ios/Runner/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Yappy - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - yappy - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - - diff --git a/team_b/yappy/ios/Runner/Runner-Bridging-Header.h b/team_b/yappy/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a56..00000000 --- a/team_b/yappy/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/team_b/yappy/ios/RunnerTests/RunnerTests.swift b/team_b/yappy/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b1..00000000 --- a/team_b/yappy/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/team_b/yappy/lib/audiowave_widget.dart b/team_b/yappy/lib/audiowave_widget.dart deleted file mode 100644 index ea242f69..00000000 --- a/team_b/yappy/lib/audiowave_widget.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:flutter/material.dart'; -import 'dart:math'; -import 'services/speech_state.dart'; - -class AudiowaveWidget extends StatelessWidget { - final SpeechState speechState; - - const AudiowaveWidget({super.key, required this.speechState}); - - @override - Widget build(BuildContext context) { - - // Listens for the change in data - return ValueListenableBuilder>( - valueListenable: speechState.audioSamplesNotifier, - builder: (context, samples, child) { - return SizedBox( - height: 100, - width: MediaQuery.of(context).size.width, - child: CustomPaint( - // Paints the audiowave - painter: _WaveformPainter( - samples.isNotEmpty - ? samples - : List.generate(100, (index) => (index % 2 == 0) ? 1000 : -1000), - Colors.deepPurpleAccent, - ), - ), - ); - }, - ); - } -} - -class _WaveformPainter extends CustomPainter { - final List audioSamples; - final Color waveColor; - - _WaveformPainter(this.audioSamples, this.waveColor); - - @override - void paint(Canvas canvas, Size size) { - final Paint paint = Paint() - ..color = waveColor - ..strokeWidth = 2.0 - ..strokeCap = StrokeCap.round; - - // Centers the waves on the screen - final double midY = size.height / 2; - - // Creates spacing - final double sampleSpacing = size.width / max(audioSamples.length, 1); - - // Actually paints the individual lines - for (int i = 0; i < audioSamples.length; i++) { - final double x = i * sampleSpacing; - - // Scale the sample but ensure it doesn't exceed half of the available height - final double maxAmplitude = size.height / 2 - 4; // Subtract 4 for a small margin - - // Normalize then clamp the value between -maxAmplitude and maxAmplitude - double normalizedSample = (audioSamples[i].toDouble() / 32768.0) * maxAmplitude; - normalizedSample = normalizedSample.clamp(-maxAmplitude, maxAmplitude); - - final double yStart = midY - normalizedSample; - final double yEnd = midY + normalizedSample; - - canvas.drawLine(Offset(x, yStart), Offset(x, yEnd), paint); - } - } - - @override - bool shouldRepaint(covariant _WaveformPainter oldDelegate) { - return oldDelegate.audioSamples != audioSamples; - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/contact_page.dart b/team_b/yappy/lib/contact_page.dart deleted file mode 100644 index e69a2601..00000000 --- a/team_b/yappy/lib/contact_page.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/tool_bar.dart'; - -//**************************************************************** */ -//**************************************************************** */ -//**************************************************************** */ -//Currently the data doesnt go anywhere. You would need to add an Email address and a way to send the data to that email address -//This is a simple form that takes in a name, email, and message and sends it to an email address -//The user will be notified that the message has been sent -//**************************************************************** */ -//**************************************************************** */ -//**************************************************************** */ -class ContactApp extends StatelessWidget { - const ContactApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: ContactPage(), - ); - } -} - -class ContactPage extends StatelessWidget { - final TextEditingController nameController = TextEditingController(); - final TextEditingController emailController = TextEditingController(); - final TextEditingController messageController = TextEditingController(); -//Creates a page for the Contact Us page -//The page will contain a form for the user to input their name, email, and message - ContactPage({super.key}); - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(140), - child: ToolBar(), - ), - drawer: HamburgerDrawer(), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Contact Us', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - TextField( - controller: nameController, - decoration: InputDecoration( - labelText: 'Name', - labelStyle: TextStyle(color: Colors.white), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.white), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blue), - ), - ), - style: TextStyle(color: Colors.white), - ), - SizedBox(height: 16), - TextField( - controller: emailController, - decoration: InputDecoration( - labelText: 'Email', - labelStyle: TextStyle(color: Colors.white), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.white), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blue), - ), - ), - style: TextStyle(color: Colors.white), - ), - SizedBox(height: 16), - TextField( - controller: messageController, - decoration: InputDecoration( - labelText: 'Message', - labelStyle: TextStyle(color: Colors.white), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.white), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.blue), - ), - ), - style: TextStyle(color: Colors.white), - maxLines: 5, - ), - SizedBox(height: 20), - ElevatedButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Thank You'), - content: Text('Your message has been sent.'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('OK'), - ), - ], - ); - }, - ).then((_) { - // Clear the text fields - nameController.clear(); - emailController.clear(); - messageController.clear(); - }); - }, - child: Text('Send'), - ), - ], - ), - ), - ); - } -} diff --git a/team_b/yappy/lib/env.dart b/team_b/yappy/lib/env.dart deleted file mode 100644 index 49313d57..00000000 --- a/team_b/yappy/lib/env.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:envied/envied.dart'; - -// part 'env.g.dart'; // Uncomment this line to generate the env.g.dart file - -// Run `flutter pub run build_runner build` to generate the env.g.dart file -@Envied(path: '.env') -abstract class Env { - @EnviedField(varName: 'OPENAI_API_KEY') - // Use this value instead for local testing: "_Env.apiKey;" - // Otherwise, provide an API key within the application's settings while running - static String apiKey = ''; -} diff --git a/team_b/yappy/lib/help.dart b/team_b/yappy/lib/help.dart deleted file mode 100644 index f1e3fb5b..00000000 --- a/team_b/yappy/lib/help.dart +++ /dev/null @@ -1,144 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/tutorial_page.dart'; - - -class HelpApp extends StatelessWidget { - const HelpApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: HelpPage(), - ); - } -} -//Creates a page for the Help industry -//The page will contain the industry menu and the transcription box -class HelpPage extends StatelessWidget { - const HelpPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(MediaQuery.of(context).size.height * 0.2), - child: ToolBar() - ), - drawer: HamburgerDrawer(), - body: SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Align( - alignment: Alignment.center, - child: Text( - 'Lets Yap about Yappy', - style: TextStyle( - color: Colors.white, - fontSize: 24, - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Align( - alignment: Alignment.center, - child: Column( - children: [ - Text( - 'Welcome to Yappy! If this is your first time and need help with using Yappy, please select the button below.', - style: TextStyle( - color: const Color.fromRGBO(255, 255, 255, 1), - fontSize: 12, - ), - ), - SizedBox(height: 20), - ElevatedButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TutorialPage(), - ), - ); - }, - child: Text('It\'s my first time'), - ), - SizedBox(height: 20), - Text( - 'Reporting a Problem with Yappy\n' - 'If something is not working on Yappy, please follow the instructions below to let us know.\n\n', - style: TextStyle( - color: Colors.white, - fontSize: 12, - ), - ), - SizedBox(height: 5), - ElevatedButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Report a Problem'), - content: Text('Please call: +1-800-123-4567'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ); - }, - ); - }, - child: Text('Report a problem'), - ), - SizedBox(height: 5), - Text( - '\n\nFeedback from the people who use Yappy has helped us redesign our products, improve our policies and fix technical problems. We really appreciate you taking the time to share your thoughts and suggestions with us.\n', - style: TextStyle( - color: Colors.white, - fontSize: 12, - ), - ), - SizedBox(height: 5), - ElevatedButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Feedback for the Help Center'), - - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ); - }, - ); - }, - child: Text('Feedback for the Help Center'), - ), - SizedBox(height: 20), - - ], - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/team_b/yappy/lib/home_page.dart b/team_b/yappy/lib/home_page.dart deleted file mode 100644 index 578dc7d6..00000000 --- a/team_b/yappy/lib/home_page.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/contact_page.dart'; -import 'package:yappy/help.dart'; -import 'package:yappy/mechanic.dart'; -import 'package:yappy/medical_doctor.dart'; -import 'package:yappy/medical_patient.dart'; -import 'package:yappy/restaurant.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/settings_page.dart'; -import 'package:yappy/tutorial_page.dart'; -import './services/model_manager.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class HomePage extends StatefulWidget { - const HomePage({super.key}); - - @override - State createState() => _HomePageState(); -} - -class _HomePageState extends State { - final ModelManager _modelManager = ModelManager(); - - - Future _checkFirstTimeUser() async { - final prefs = await SharedPreferences.getInstance(); - final isFirstTime = prefs.getBool('isFirstTime') ?? true; - - if (isFirstTime && mounted) { - final shouldShowDialog = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Welcome!'), - content: const Text('Is this your first time using the app?'), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text('No'), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: const Text('Yes'), - ), - ], - ), - ); - - if (shouldShowDialog != null && shouldShowDialog) { - await prefs.setBool('isFirstTime', false); - if (mounted) { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => TutorialPage()), - ); - } - } - } - } - - Future _checkModelsExist() async { - try { - // Skip check if downloads are already in progress - if (_modelManager.isDownloadInProgress()) { - return; - } - - final modelsExist = await _modelManager.modelsExist(); - if (!modelsExist && mounted) { - // Models don't exist, prompt for download - final shouldDownload = await _modelManager.showDownloadDialog(context); - if (shouldDownload && mounted) { - await _modelManager.downloadModels(context); - } - } - } catch (e) { - debugPrint('Error checking models: $e'); - } - } - - @override - void initState() { - super.initState(); - // Check if models exist after the first frame is rendered - WidgetsBinding.instance.addPostFrameCallback((_) { - _checkModelsExist(); - _checkFirstTimeUser(); - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(140), - child: ToolBar(showHamburger: false), // Using the ToolBar widget - ), - body: Column( - children: [ - _buildButton('Restaurant', context, RestaurantPage()), - _buildButton('Vehicle Maintenance', context, MechanicalAidPage()), - _buildButton('Medical Doctor', context, MedicalDoctorPage()), - _buildButton('Medical Patient', context, MedicalPatientPage()), - _buildButton('Help', context, HelpPage()), - _buildButton('Contact', context, ContactPage()), - _buildButton('Settings', context, SettingsPage()), - ], - ), - ); - } - - // Function for button navigation - Widget _buildButton(String text, BuildContext context, Widget page) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => page), - ); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.grey[900], - padding: const EdgeInsets.symmetric(vertical: 15), - ), - child: Text( - text, - style: const TextStyle(color: Colors.white, fontSize: 16), - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/industry_menu.dart b/team_b/yappy/lib/industry_menu.dart deleted file mode 100644 index 0217e665..00000000 --- a/team_b/yappy/lib/industry_menu.dart +++ /dev/null @@ -1,823 +0,0 @@ -import 'dart:io'; -import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:intl/intl.dart'; -import 'package:record/record.dart'; -import 'package:share_plus/share_plus.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'services/openai_helper.dart'; -import 'services/database_helper.dart'; -import 'services/file_handler.dart'; -import 'services/model_manager.dart'; -import 'services/speech_state.dart'; -import 'package:file_picker/file_picker.dart'; -import 'package:yappy/services/restaurant_api_module.dart'; - - -class IndustryMenu extends StatefulWidget { - final String title; - final IconData icon; - final SpeechState speechState; - final ModelManager modelManager; - - const IndustryMenu( - {required this.title, - required this.icon, - super.key, - required this.speechState, - required this.modelManager}); - - @override - State createState() => _IndustryMenuState(); -} - -class _IndustryMenuState extends State { - bool modelsExist = false; - - @override - void initState() { - super.initState(); - _checkModels(); - } - - Future _checkModels() async { - final exist = await widget.modelManager.modelsExist(); - if (mounted) { - setState(() { - modelsExist = exist; - }); - } - } - - // This method generates a transcript dialog including the options for sharing, downloading, and deleting the transcript - Widget generateTranscript( - BuildContext context, String title, String content, int transcript) { - return AlertDialog( - title: Text(title), - content: SingleChildScrollView( - child: Text(content), - ), - actions: [ - //add export capes - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - IconButton( - icon: Icon(Icons.share), - onPressed: () { - // Add your share functionality here - Share.share( - content, - subject: title, - ); - }, - ), - IconButton( - icon: Icon(Icons.download), - onPressed: () async { - // Download button - try { - // Request storage permission - if (await Permission.storage.request().isGranted || - await Permission.manageExternalStorage - .request() - .isGranted) { - // Attempt to find the Downloads directory - final directories = await getExternalStorageDirectories( - type: StorageDirectory.downloads); - final downloadsDirectory = directories?.first; - - if (downloadsDirectory != null) { - final filePath = '${downloadsDirectory.path}/$title.txt'; - final file = File(filePath); - await file.writeAsBytes(utf8.encode(content), - flush: true); - - await MethodChannel('com.yourcompany.yappy/files') - .invokeMethod('scanFile', {'filePath': filePath}); - - FileHandler fileHandler = FileHandler(); - await fileHandler.addDocument(file); - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Transcript saved to $filePath')), - ); - } - debugPrint('File saved at: $filePath'); - } else { - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: - Text('Failed to find Downloads directory')), - ); - } - } - } else { - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Storage permission denied')), - ); - } - } - } catch (e) { - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to save file: $e')), - ); - } - debugPrint('Failed to save file: $e'); - } - }, - ), - IconButton( - icon: Icon(Icons.delete), - onPressed: () async { - // Add your delete functionality here - bool confirmDelete = await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Confirm Delete'), - content: Text( - 'Are you sure you want to delete this transcript?'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(false); - }, - child: Text('Cancel'), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(true); - }, - child: Text('Delete'), - ), - ], - ); - }, - ); - - if (confirmDelete) { - // Perform the delete operation - await DatabaseHelper().deleteTranscript(transcript); - if (!context.mounted) return; - Navigator.of(context).pop(); - } - }, - ), - ], - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ); - } - - // This method fetches all transcripts from the database - Future>> _fetchTranscripts() async { - DatabaseHelper dbHelper = DatabaseHelper(); - return await dbHelper.getAllTranscripts(); - } - - // This method builds the industry menu widget where the user can record, view transcripts, and view transcript history - // Added the fourth button for Chat Bot - @override - Widget build(BuildContext context) { - // Gets the width and height of the current screen - double screenWidth = MediaQuery.of(context).size.width; - double screenHeight = MediaQuery.of(context).size.height; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - - // Creates a column for the items within the menu - child: Column( - children: [ - Center( - // Creates the text box above the icons - child: Container( - width: screenWidth * .75, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: const Color.fromARGB(255, 67, 67, 67), - ), - padding: EdgeInsets.all(12), - child: Center( - child: Text( - widget.title, - style: TextStyle(fontSize: 24, color: Colors.white), - ), - ), - )), - - SizedBox(height: screenHeight * .03), - - // Creates a row of clickable menu icons - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Creates the chat button for each menu - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: !modelsExist - ? Color.fromRGBO(128, 128, 128, 0.5) - : (widget.speechState.recordState == RecordState.stop - ? Colors.grey - : Colors.red)), - padding: EdgeInsets.all(5), - child: Tooltip( - message: !modelsExist - ? "Download required models to enable recording" - : (widget.speechState.recordState == RecordState.stop - ? "Start recording" - : "Stop recording"), - child: IconButton( - icon: Icon( - widget.speechState.recordState == RecordState.stop - ? Icons.mic - : Icons.stop, - color: !modelsExist - ? Color.fromRGBO(255, 255, 255, 0.5) - : Colors.white, - size: screenHeight * .05, - ), - onPressed: !modelsExist - ? null - : () async { - await widget.speechState.toggleRecording(); - // When speechState.stop happens it needs to store the text in the database - // The new text file needs to get the USERID, create a new Transcript ID, - // The user will be asked to edit the text to ensure accuracy. After hitting save, the text will be saved to the database in the transcript table using the same transcript ID - if (widget.speechState.recordState == - RecordState.stop) { - // Fetch the recorded text - String recordedText = - await widget.speechState.getRecordedText(); - - // Get the user ID (assuming you have a method to get the current user ID) - int userId = 0001; - - // Create a new transcript ID - int transcriptId = - DateTime.now().millisecondsSinceEpoch; - - // Show a dialog to edit the text - TextEditingController controller = - TextEditingController(text: recordedText); - if (!context.mounted) return; - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Edit Transcript'), - content: TextField( - controller: controller, - decoration: InputDecoration( - hintText: 'Edit the transcript text'), - maxLines: null, - ), - actions: [ - TextButton( - onPressed: () async { - // Save the edited text to the database - await DatabaseHelper().saveTranscript( - userId: userId, - transcriptId: transcriptId, - text: controller.text, - industry: widget.title, - ); - // Kick off the AI summarization process - var openAIHelper = OpenAIHelper(); - String aiResponse = ''; - try { - aiResponse = await openAIHelper - .summarizeTranscription(userId, - widget.title, transcriptId); - } catch (e) { - // Lets the user know that transcription summarization failed (likely because of a lack of OpenAI API key) - if (context.mounted) { - ScaffoldMessenger.of(context) - .showSnackBar( - SnackBar( - content: Text( - 'Failed to summarize transcription: $e')), - ); - } - } - // Place API hook here to parse aiResponse String and populate additional information based on industry: - debugPrint( - aiResponse); // not a necessary statement after implementation - - if (!context.mounted) return; - Navigator.of(context).pop(); - }, - child: Text('Save'), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Cancel'), - ), - ], - ); - }, - ); - } - }, - ), - ), - ), - SizedBox(width: screenWidth * .06), - - // Creates a industry specific icon based on user input - Container( - decoration: - BoxDecoration(shape: BoxShape.circle, color: Colors.grey), - padding: EdgeInsets.all(5), - child: IconButton( - icon: Icon( - widget.icon, - color: Colors.white, - size: screenHeight * .05, - ), - onPressed: () { - _showTranscriptsBottomSheet(context); - }, - ), - ), - SizedBox(width: screenWidth * .06), - - // Creates a transcript history button - Container( - decoration: - BoxDecoration(shape: BoxShape.circle, color: Colors.grey), - padding: EdgeInsets.all(5), - child: IconButton( - icon: Icon( - Icons.file_copy, - color: Colors.white, - size: screenHeight * .05, - ), - onPressed: () { - _showTranscriptsHistoryBottomSheet(context); - }, - ), - ), - - SizedBox(width: screenWidth * .06), - - // Creates a chatbot button - Container( - decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.grey), - padding: EdgeInsets.all(5), - child: IconButton( - icon: Icon( - Icons.android, - color: Colors.white, - size: screenHeight * .05, - ), - onPressed: () async { - // Kick off the AI chat session - var openAIHelper = OpenAIHelper(); - TextEditingController chatController = TextEditingController(); - String? aiResponse = ''; - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Ask Yappy about stored transcripts'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextField( - controller: chatController, - decoration: InputDecoration(hintText: 'Enter a question'), - ), - ], - ), - actions: [ - TextButton( - onPressed: () async { - String userInput = chatController.text; - if (userInput.isNotEmpty) { - // Show intermediary dialog - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Generating Response'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CircularProgressIndicator(), - SizedBox(height: 20), - Text('Please wait while the response is being generated...'), - ], - ), - ); - }, - ); - - aiResponse = await openAIHelper.startTranscriptChatAssistant(userInput, widget.title); - if (!context.mounted) return; - Navigator.of(context).pop(); // Close the intermediary dialog - Navigator.of(context).pop(); // Close the first dialog - if (aiResponse != null) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Yappy Response'), - content: SingleChildScrollView( - child: Text(aiResponse ?? "No response"), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ); - }, - ); - } - } - }, - child: Text('Submit'), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Cancel'), - ), - ], - ); - }, - ); - }, - ), - ), - ], - ), - ], - ), - ); - } - - // Extract the functionality to show transcripts into a separate method - void _showTranscriptsBottomSheet(BuildContext context) async { - // Fetch transcripts first - List> transcripts = await _fetchTranscripts(); - - // Check if the context is still valid - if (!context.mounted) return; - - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return Container( - padding: EdgeInsets.all(16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: const Color.fromARGB(255, 67, 67, 67), - ), - child: Center( - child: Column( - children: [ - Expanded( - child: ListView.builder( - itemCount: transcripts.length, - itemBuilder: (context, index) { - Map transcript = transcripts[index]; - if (transcript['industry'] == widget.title) { - return ListTile( - title: Text( - // Format the transcript ID to Day Month Year Time - DateFormat('dd MMM yyyy HH:mm').format( - DateTime.fromMillisecondsSinceEpoch( - transcript['transcript_id'])), - style: TextStyle(color: Colors.white), - ), - onTap: () async { - Navigator.pop(context); - if (widget.title == 'Restaurant') { - // Fetch the AI response from the database - List validatedMenuItems = []; - - try { - final aiResponse = transcript['transcript_ai_response']; - String parsedResponse = aiResponse.replaceAll(RegExp(r'\[OpenAIChatCompletionChoiceMessageContentItemModel\(type: text, text: '), '').replaceAll(RegExp(r'\)\]'), ''); - List parsedResponseList = parsedResponse.split('\n').where((item) => item.trim().isNotEmpty).toList(); - // [OpenAIChatCompletionChoiceMessageContentItemModel(type: text, text: Seat 1: Burger, fries, and a soda. - // I/flutter (17322): - // I/flutter (17322): Seat 2: Burger, fries, and a soda. - // I/flutter (17322): - // I/flutter (17322): Seat 3: Burger, fries, and a soda. - // I/flutter (17322): - // I/flutter (17322): Seat 4: Double burger with large fries and a soda.)] - var restaurantAPI = RestaurantAPI(); - validatedMenuItems = await restaurantAPI.validateMenuItems(parsedResponseList); - if (!context.mounted) return; - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - - return KanbanBoard(tasks: validatedMenuItems); - }, - ); - } catch (e) { - // Handle API call failure - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Failed to validate menu items: $e')), - ); - } - } - } else { - final aiResponse = transcript['transcript_ai_response']; - String parsedResponse = aiResponse.replaceAll(RegExp(r'\[OpenAIChatCompletionChoiceMessageContentItemModel\(type: text, text: '), '').replaceAll(RegExp(r'\)\]'), ''); - // Show regular transcript for other industries - // Show the parsedResponse in a regular dialog with a close button at the bottom - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Transcript'), - content: SingleChildScrollView( - child: Text(parsedResponse), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ); - }, - ); - } - }, - ); - } else { - return SizedBox.shrink(); - } - }, - ), - ), - ], - ), - ), - ); - }, - ); - } - - - - // Extract the functionality to show transcript history into a separate method - void _showTranscriptsHistoryBottomSheet(BuildContext context) async { - // Fetch transcripts first - List> transcripts = await _fetchTranscripts(); - - // Check if the context is still valid - if (!context.mounted) return; - - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return Container( - padding: EdgeInsets.all(16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: const Color.fromARGB(255, 67, 67, 67), - ), - child: Center( - child: Column( - children: [ - Expanded( - child: ListView.builder( - itemCount: transcripts.length, - itemBuilder: (context, index) { - Map transcript = transcripts[index]; - if (transcript['industry'] == widget.title) { - return ListTile( - title: Text( - // Format the transcript ID to Day Month Year Time - DateFormat('dd MMM yyyy HH:mm').format( - DateTime.fromMillisecondsSinceEpoch( - transcript['transcript_id'])), - style: TextStyle(color: Colors.white), - ), - onTap: () { - Navigator.pop(context); - showDialog( - context: context, - builder: (BuildContext context) { - return generateTranscript( - context, - 'Transcript', - transcript['transcript_text_data'] ?? - 'No content available', - transcript['transcript_id'], - ); - }, - ); - }, - ); - } else { - return SizedBox.shrink(); - } - }, - ), - ), - // Add an upload bar at the bottom - Padding( - padding: const EdgeInsets.only(top: 16.0), - child: ElevatedButton.icon( - onPressed: () async { - // Upload button - FilePickerResult? result = - await FilePicker.platform.pickFiles(); - if (result != null) { - PlatformFile file = result.files.first; - String uploadedFileName = file.name; - String uploadedFileContent = - await File(file.path!).readAsString(); - - await DatabaseHelper().saveTranscript( - userId: 0001, - transcriptId: DateTime.now().millisecondsSinceEpoch, - text: uploadedFileContent, - industry: widget.title); - - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: - Text('File uploaded: $uploadedFileName')), - ); - } else { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('File upload canceled')), - ); - } - }, - icon: Icon(Icons.upload), - label: Text('Upload Transcript'), - style: ElevatedButton.styleFrom( - backgroundColor: const Color.fromARGB(255, 26, 26, 27), - foregroundColor: const Color.fromARGB(255, 229, 217, 217), - ), - ), - ), - ], - ), - ), - ); - }, - ); - } -} - -class KanbanBoard extends StatefulWidget { - final List tasks; - - const KanbanBoard({super.key, required this.tasks}); - - @override - KanbanBoardState createState() => KanbanBoardState(); -} - -class KanbanBoardState extends State { - late List tasks; - - @override - void initState() { - super.initState(); - tasks = widget.tasks; - } - - //creates the kanban board sytle widget for the restaurant - //need to allow the user to edit the order by holding the card - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('Restaurant Order'), - ), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - Expanded( - child: ListView.builder( - itemCount: tasks.length, - itemBuilder: (context, index) { - return Card( - elevation: 4, - margin: const EdgeInsets.symmetric(vertical: 8), - child: ListTile( - title: Text(tasks[index]), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: Icon(Icons.arrow_upward), - onPressed: index > 0 - ? () { - setState(() { - final temp = tasks[index]; - tasks[index] = tasks[index - 1]; - tasks[index - 1] = temp; - }); - } - : null, - ), - IconButton( - icon: Icon(Icons.arrow_downward), - onPressed: index < tasks.length - 1 - ? () { - setState(() { - final temp = tasks[index]; - tasks[index] = tasks[index + 1]; - tasks[index + 1] = temp; - }); - } - : null, - ), - IconButton( - icon: Icon(Icons.edit), - onPressed: () { - TextEditingController controller = - TextEditingController(text: tasks[index]); - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Edit Task'), - content: TextField( - controller: controller, - decoration: InputDecoration( - hintText: 'Enter new task'), - ), - actions: [ - TextButton( - onPressed: () { - setState(() { - tasks[index] = controller.text; - }); - Navigator.of(context).pop(); - }, - child: Text('Save'), - ), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Cancel'), - ), - ], - ); - }, - ); - }, - ), - ], - ), - ), - ); - }, - ), - ), - // Add a close button at the bottom - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text('Close'), - ), - ], - ), - ), - ); - } -} diff --git a/team_b/yappy/lib/login_page.dart b/team_b/yappy/lib/login_page.dart deleted file mode 100644 index cb14275f..00000000 --- a/team_b/yappy/lib/login_page.dart +++ /dev/null @@ -1,132 +0,0 @@ -import 'package:flutter/material.dart'; -import 'sign_up_page.dart'; // Import the SignUpPage - -class LoginPage extends StatefulWidget { - const LoginPage({super.key}); - - @override - LoginPageState createState() => LoginPageState(); -} - -class LoginPageState extends State { - final TextEditingController _usernameController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - - @override - void dispose() { - _usernameController.dispose(); - _passwordController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - body: Center( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircleAvatar( - backgroundColor: Colors.white, - radius: 30, - child: Icon(Icons.chat, color: Colors.green, size: 40), - ), - const SizedBox(height: 20), - - // Login Button - ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 80), - ), - child: const Text( - 'Login', - style: TextStyle(color: Colors.white, fontSize: 18), - ), - ), - const SizedBox(height: 20), - - // Username TextField - TextField( - controller: _usernameController, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - filled: true, - fillColor: Colors.grey[900], - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), - labelText: 'Username', - labelStyle: const TextStyle(color: Colors.white), - ), - ), - const SizedBox(height: 10), - - // Password TextField - TextField( - controller: _passwordController, - obscureText: true, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - filled: true, - fillColor: Colors.grey[900], - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), - labelText: 'Password', - labelStyle: const TextStyle(color: Colors.white), - ), - ), - const SizedBox(height: 20), - - // Submit Button - ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 40), - ), - child: const Text( - 'Submit', - style: TextStyle(color: Colors.white, fontSize: 16), - ), - ), - const SizedBox(height: 30), - - // Terms and Conditions - const Text( - 'Terms and Conditions', - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), - ), - const SizedBox(height: 5), - const Text( - 'Ensure consent is obtained before using the application, as required in certain states.', - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white60, fontSize: 12), - ), - const SizedBox(height: 20), - - // Sign-up Button with Navigation - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => SignUpPage()), // Navigate to SignUpPage - ); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 60), - ), - child: const Text( - 'Sign-up', - style: TextStyle(color: Colors.white, fontSize: 16), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/team_b/yappy/lib/main.dart b/team_b/yappy/lib/main.dart deleted file mode 100644 index b19706b7..00000000 --- a/team_b/yappy/lib/main.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:yappy/home_page.dart'; -import 'package:yappy/services/database_helper.dart'; -import 'package:dart_openai/dart_openai.dart'; -import 'package:yappy/env.dart'; -import './toast_widget.dart'; - -// Create a global instance of DatabaseHelper -final DatabaseHelper dbHelper = DatabaseHelper(); -final GlobalKey navigatorKey = GlobalKey(); -late SharedPreferences preferences; - -void main() async{ - WidgetsFlutterBinding.ensureInitialized(); - preferences = await SharedPreferences.getInstance(); - - // Env file setup for local development - String apiKey = Env.apiKey; - if (apiKey.isNotEmpty) { - OpenAI.apiKey = apiKey; - await preferences.setString('openai_api_key', apiKey); - } - - await dbHelper.database; - - WidgetsBinding.instance.addPostFrameCallback((_) { - // Shows dialog requesting an OpenAI API key if not set - if (apiKey.isEmpty) { - showDialog( - context: navigatorKey.currentContext!, - builder: (BuildContext context) { - return AlertDialog( - title: Text('OpenAI API Key Required'), - content: Text('Please add a valid OpenAI API key via the Settings menu.'), - actions: [ - TextButton( - child: Text('OK'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - } - }); - - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - navigatorKey: navigatorKey, - debugShowCheckedModeBanner: false, - title: 'Yappy', - theme: ThemeData( - primarySwatch: Colors.lightGreen, - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - home: HomePage(), - builder: (context, child) { - // Wrap every screen with ToastWidget - return ToastWidget(child: child ?? Container()); - }, - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/mechanic.dart b/team_b/yappy/lib/mechanic.dart deleted file mode 100644 index 6029a25c..00000000 --- a/team_b/yappy/lib/mechanic.dart +++ /dev/null @@ -1,75 +0,0 @@ -import 'package:flutter/material.dart'; -import 'audiowave_widget.dart'; -import 'industry_menu.dart'; -import 'tool_bar.dart'; -import 'transcription_box.dart'; -import 'services/speech_state.dart'; -import 'services/model_manager.dart'; -import 'search_bar_widget.dart'; - -void main() { - runApp(MechanicalAidApp()); -} - -class MechanicalAidApp extends StatelessWidget { - const MechanicalAidApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: MechanicalAidPage(), - ); - } -} -//Creates a page for the Mechanical Aid industry -//The page will contain the industry menu and the transcription box -class MechanicalAidPage extends StatelessWidget { - MechanicalAidPage({super.key}); - final speechState = SpeechState(); - final modelManager = ModelManager(); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(100), - child: ToolBar(), - ), - drawer: HamburgerDrawer(), - body: ListenableBuilder( - listenable: speechState, - builder: (context, child) { - return SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: SearchBarWidget(industry: "Vehicle Maintenance"), - ), - - IndustryMenu( - title: "Vehicle Maintenance", - icon: Icons.directions_car, - speechState: speechState, - modelManager: modelManager, - ), - - Padding( - padding: const EdgeInsets.all(16.0), - child: Column(children: [ - AudiowaveWidget(speechState: speechState), - TranscriptionBox( - controller: speechState.controller, - ), - ],) - - ), - ], - ) - ); - } - ), - ); - } -} diff --git a/team_b/yappy/lib/medical_doctor.dart b/team_b/yappy/lib/medical_doctor.dart deleted file mode 100644 index 7ae00cf4..00000000 --- a/team_b/yappy/lib/medical_doctor.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:flutter/material.dart'; -import 'audiowave_widget.dart'; -import 'industry_menu.dart'; -import 'tool_bar.dart'; -import 'transcription_box.dart'; -import 'services/speech_state.dart'; -import 'services/model_manager.dart'; -import 'search_bar_widget.dart'; - - -class MedicalDoctorApp extends StatelessWidget { - const MedicalDoctorApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: MedicalDoctorPage(), - ); - } -} -//Creates a page for the Medical Doctor industry -//The page will contain the industry menu and the transcription box -class MedicalDoctorPage extends StatelessWidget { - MedicalDoctorPage({super.key}); - final speechState = SpeechState(); - final modelManager = ModelManager(); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(100), - child: ToolBar() - ), - drawer: HamburgerDrawer(), - body: ListenableBuilder( - listenable: speechState, - builder: (context, child) { - return SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: SearchBarWidget(industry: "Medical Doctor"), - ), - IndustryMenu( - title: "Medical Doctor", - icon: Icons.medical_services, - speechState: speechState, - modelManager: modelManager, - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Column(children: [ - AudiowaveWidget(speechState: speechState), - TranscriptionBox( - controller: speechState.controller, - ), - ],) - - ), - ], - ) - ); - } - ), - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/medical_patient.dart b/team_b/yappy/lib/medical_patient.dart deleted file mode 100644 index a5b7eaf5..00000000 --- a/team_b/yappy/lib/medical_patient.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:flutter/material.dart'; -import 'audiowave_widget.dart'; -import 'tool_bar.dart'; -import 'industry_menu.dart'; -import 'transcription_box.dart'; -import 'services/speech_state.dart'; -import 'services/model_manager.dart'; -import 'search_bar_widget.dart'; - - -class MedicalPatientApp extends StatelessWidget { - const MedicalPatientApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: MedicalPatientPage(), - ); - } -} -//Creates a page for the Medical Patient industry -//The page will contain the industry menu and the transcription box -class MedicalPatientPage extends StatelessWidget { - MedicalPatientPage({super.key}); - final speechState = SpeechState(); - final modelManager = ModelManager(); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(100), - child: ToolBar() - ), - drawer: HamburgerDrawer(), - body: ListenableBuilder( - listenable: speechState, - builder: (context, child) { - return SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: SearchBarWidget(industry: "Medical Patient"), - ), - IndustryMenu( - title: "Medical Patient", - icon: Icons.local_pharmacy, - speechState: speechState, - modelManager: modelManager, - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Column(children: [ - AudiowaveWidget(speechState: speechState), - TranscriptionBox( - controller: speechState.controller, - ), - ],) - ), - ], - ) - ); - - } - ), - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/restaurant.dart b/team_b/yappy/lib/restaurant.dart deleted file mode 100644 index 62e3f215..00000000 --- a/team_b/yappy/lib/restaurant.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:flutter/material.dart'; -import 'audiowave_widget.dart'; -import 'tool_bar.dart'; -import 'industry_menu.dart'; -import 'transcription_box.dart'; -import 'services/speech_state.dart'; -import 'services/model_manager.dart'; -import 'package:yappy/search_bar_widget.dart'; - -class RestaurantPage extends StatelessWidget { - RestaurantPage({super.key}); - final speechState = SpeechState(); - final modelManager = ModelManager(); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(100), - child: ToolBar(), - ), - drawer: HamburgerDrawer(), - body: ListenableBuilder( - listenable: speechState, - builder: (context, child) { - return SingleChildScrollView( - child: Column( - children: [ - // Padding the search bar and using a smaller height - Padding( - padding: const EdgeInsets.all(8.0), - child: SearchBarWidget(industry: "Restaurant"), - ), - // The rest of the widgets below the search bar - IndustryMenu( - title: "Restaurant", - icon: Icons.restaurant_menu, - speechState: speechState, - modelManager: modelManager, - ), - - Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - AudiowaveWidget(speechState: speechState), - TranscriptionBox( - controller: speechState.controller, - ), - ], - ), - ), - ], - ), - ); - }, - ), - ); - } -} - diff --git a/team_b/yappy/lib/search_bar_widget.dart b/team_b/yappy/lib/search_bar_widget.dart deleted file mode 100644 index 20c8b3d1..00000000 --- a/team_b/yappy/lib/search_bar_widget.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/services/database_helper.dart'; - -class SearchBarWidget extends StatefulWidget { - final String industry; - const SearchBarWidget({super.key, required this.industry}); - - @override - State createState() => _SearchBarWidgetState(); -} - -class _SearchBarWidgetState extends State { - late final SearchController _searchController; - DatabaseHelper dbHelp = DatabaseHelper(); - - @override - void initState() { - super.initState(); - _searchController = SearchController(); - } - - @override - void dispose() { - _searchController.dispose(); - super.dispose(); - } - - Future> _fetchSuggestions(String query, String industry) async { - List results = await dbHelp.searchTranscripts(query, industry); - - return results.map((item) { - return ListTile( - title: Text(item), - onTap: () { - _showDetailsDialog(item); - }, - ); - }).toList(); - } - - @override - Widget build(BuildContext context) { - return Container( - color: const Color.fromARGB(255, 0, 0, 0), - child: Padding( - padding: const EdgeInsets.only(left: 4.0, right: 4.0), - child: SearchAnchor( - searchController: _searchController, - suggestionsBuilder: (BuildContext context, SearchController controller) async { - return _fetchSuggestions(controller.text, widget.industry); - }, - builder: (BuildContext context, SearchController controller) { - return SearchBar( - controller: _searchController, - padding: const WidgetStatePropertyAll( - EdgeInsets.symmetric(horizontal: 2.0), - ), - onTap: () { - controller.openView(); - }, - onChanged: (_) { - controller.openView(); - }, - leading: const Icon(Icons.search), - ); - }, - ), - ), - ); - } - - // Opens a pop-up window when users clicks on a specific search result - void _showDetailsDialog(String entry) async { - Map? transcriptDetails = await dbHelp.getTranscriptDetails(entry); - - if (transcriptDetails == null || !mounted) { - return; - } - - // Extract the results from the database query - String text = transcriptDetails['text'] ?? "No text available."; - String timestamp = transcriptDetails['timestamp'] ?? "No timestamp available."; - - // Shows the information extracted from the query - if (mounted) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text("Transcript Details"), - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Timestamp: $timestamp"), - SizedBox(height: 15.0), - Text("Transcript Text: $text"), - ], - ), - ), - actions: [ - TextButton( - child: const Text('Close'), - onPressed: () { - Navigator.of(context).pop(); - }, - ) - ], - ); - }, - ); - } - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/database_helper.dart b/team_b/yappy/lib/services/database_helper.dart deleted file mode 100644 index b74b94b6..00000000 --- a/team_b/yappy/lib/services/database_helper.dart +++ /dev/null @@ -1,668 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:sqflite/sqflite.dart'; -import 'package:path/path.dart'; -import 'package:flutter/services.dart' show rootBundle; -import 'dart:io'; - -class DatabaseHelper { - static final DatabaseHelper _instance = DatabaseHelper._internal(); - static Database? _database; - - factory DatabaseHelper() { - return _instance; - } - - DatabaseHelper._internal(); - - Future get database async { - if (_database != null) return _database!; - _database = await _initDatabase(); - return _database!; - } - - Future _initDatabase() async { - String databasesPath = await getDatabasesPath(); - String path = join(databasesPath, 'yappy_database.db'); - - // Check if the database already exists - bool exists = await databaseExists(path); - - if (!exists) { - // Copy the database from assets if one doesn't exist on the device's filesystem - try { - ByteData data = await rootBundle.load('assets/yappy_database.db'); - List bytes = data.buffer.asUint8List(); - await File(path).writeAsBytes(bytes); - } catch (e) { - // Can create logging function in later task if wanted - if (kDebugMode) { - print('Error copying database: $e'); - } - } - } - - return await openDatabase( - path, - version: 1, - onCreate: _onCreate, - onOpen: (db) async { - // Check if the tables exist and create them if they don't - await _createTablesIfNotExists(db); - }, - ); - } - - Future _onCreate(Database db, int version) async { - // Create tables if needed - await _createTablesIfNotExists(db); - } - - Future _createTablesIfNotExists(Database db) async { - // Create Users table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS Users ( - user_id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT, - password TEXT, - role TEXT - ) - '''); - - // Create Vehicle table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS Vehicle ( - vehicle_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER, - vehicle_make TEXT, - vehicle_model TEXT, - vehicle_year INTEGER, - FOREIGN KEY (user_id) REFERENCES Users(user_id) - ) - '''); - - - - // Create Transcript table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS Transcript ( - transcript_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER, - transcript_text_data TEXT, - transcript_timestamp DATETIME, - transcript_ai_response TEXT, - transcript_document BLOB, - industry TEXT, - FOREIGN KEY (user_id) REFERENCES Users(user_id) - ) - '''); - - // Create VehicleMaintenance table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS VehicleMaintenance ( - maintenance_id INTEGER PRIMARY KEY AUTOINCREMENT, - transcript_id INTEGER, - user_id INTEGER, - vehicle_id INTEGER, - vehicle_diagnosis_description TEXT, - vehicle_required_parts TEXT, - FOREIGN KEY (transcript_id) REFERENCES Transcript(transcript_id), - FOREIGN KEY (user_id) REFERENCES Users(user_id), - FOREIGN KEY (vehicle_id) REFERENCES Vehicle(vehicle_id) - ) - '''); - - // Create SpecialRequest table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS SpecialRequest ( - special_request_id INTEGER PRIMARY KEY AUTOINCREMENT, - special_request_description TEXT - ) - '''); - - // Create MenuItem table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS MenuItem ( - item_id INTEGER PRIMARY KEY AUTOINCREMENT, - special_request_id INTEGER, - item_name TEXT, - item_description TEXT, - item_price REAL, - seat_position INTEGER, - FOREIGN KEY (special_request_id) REFERENCES SpecialRequest(special_request_id) - ) - '''); - - // Create RestaurantOrder table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS RestaurantOrder ( - order_id INTEGER PRIMARY KEY AUTOINCREMENT, - transcript_id INTEGER, - order_status TEXT, - order_total_cost REAL, - FOREIGN KEY (transcript_id) REFERENCES Transcript(transcript_id) - ) - '''); - - // Create OrderItems table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS OrderItems ( - order_item_id INTEGER PRIMARY KEY AUTOINCREMENT, - order_id INTEGER, - item_id INTEGER, - order_item_qty INTEGER, - FOREIGN KEY (order_id) REFERENCES RestaurantOrder(order_id), - FOREIGN KEY (item_id) REFERENCES MenuItem(item_id) - ) - '''); - - // Create Patient table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS Patient ( - patient_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER, - patient_first_name TEXT, - patient_last_name TEXT, - patient_phone TEXT, - FOREIGN KEY (user_id) REFERENCES Users(user_id) - ) - '''); - - // Create DoctorVisit table if it doesn't exist - await db.execute(''' - CREATE TABLE IF NOT EXISTS DoctorVisit ( - visit_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER, - transcript_id INTEGER, - patient_id INTEGER, - doctor_visit_symptoms TEXT, - doctor_visit_diagnosis TEXT, - FOREIGN KEY (user_id) REFERENCES Users(user_id), - FOREIGN KEY (transcript_id) REFERENCES Transcript(transcript_id), - FOREIGN KEY (patient_id) REFERENCES Patient(patient_id) - ) - '''); - } - - // Users table methods - Future>> getUsers() async { - final db = await database; - return await db.query('Users'); - } - - Future insertUser(Map user) async { - final db = await database; - return await db.insert('Users', user); - } - - Future updateUser(Map user) async { - final db = await database; - int id = user['user_id']; - return await db.update('Users', user, where: 'user_id = ?', whereArgs: [id]); - } - - Future deleteUser(int id) async { - final db = await database; - return await db.delete('Users', where: 'user_id = ?', whereArgs: [id]); - } - - // Vehicle table methods - Future insertVehicle(Map vehicle) async { - final db = await database; - return await db.insert('Vehicle', vehicle); - } - - Future updateVehicle(Map vehicle) async { - final db = await database; - int id = vehicle['vehicle_id']; - return await db.update('Vehicle', vehicle, where: 'vehicle_id = ?', whereArgs: [id]); - } - - Future deleteVehicle(int id) async { - final db = await database; - return await db.delete('Vehicle', where: 'vehicle_id = ?', whereArgs: [id]); - } - - // VehicleMaintenance table methods - Future insertVehicleMaintenance(Map maintenance) async { - final db = await database; - return await db.insert('VehicleMaintenance', maintenance); - } - - Future updateVehicleMaintenance(Map maintenance) async { - final db = await database; - int id = maintenance['maintenance_id']; - return await db.update('VehicleMaintenance', maintenance, where: 'maintenance_id = ?', whereArgs: [id]); - } - - Future deleteVehicleMaintenance(int id) async { - final db = await database; - return await db.delete('VehicleMaintenance', where: 'maintenance_id = ?', whereArgs: [id]); - } - - //Transcript table methods - Future insertTranscript(Map transcript) async { - final db = await database; - return await db.insert('Transcript', transcript); - } - - Future updateTranscript(Map transcript) async { - final db = await database; - int id = transcript['transcript_id']; - return await db.update( - 'Transcript', - transcript, - where: 'transcript_id = ?', - whereArgs: [id], - ); - } - - Future deleteTranscript(int id) async { - final db = await database; - return await db.delete('Transcript', where: 'transcript_id = ?', whereArgs: [id]); - } - - // Retrieve all transcripts - Future>> getAllTranscripts() async { - final db = await database; - return await db.query( - 'Transcript', - orderBy: 'transcript_timestamp DESC', - ); - } - - // Retrieve all transcripts by industry - Future>> getAllTranscriptsByIndustry(String industry) async { - final db = await database; - return await db.query( - 'Transcript', - where: 'industry = ?', - whereArgs: [industry], - orderBy: 'transcript_timestamp DESC', - ); - } - - // Retrieve a specific transcript by ID - Future?> getTranscriptById(int transcriptId) async { - final db = await database; - List> results = await db.query( - 'Transcript', - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - if (results.isNotEmpty) { - return results.first; - } - return null; - } - - // RestaurantOrder table methods - Future insertOrder(Map order) async { - final db = await database; - return await db.insert('RestaurantOrder', order); - } - - Future updateOrder(Map order) async { - final db = await database; - int id = order['order_id']; - return await db.update('RestaurantOrder', order, where: 'order_id = ?', whereArgs: [id]); - } - - Future deleteOrder(int id) async { - final db = await database; - return await db.delete('RestaurantOrder', where: 'order_id = ?', whereArgs: [id]); - } - - // OrderItems table methods - Future insertOrderItem(Map orderItem) async { - final db = await database; - return await db.insert('OrderItems', orderItem); - } - - Future updateOrderItem(Map orderItem) async { - final db = await database; - int id = orderItem['order_item_id']; - return await db.update('OrderItems', orderItem, where: 'order_item_id = ?', whereArgs: [id]); - } - - Future deleteOrderItem(int id) async { - final db = await database; - return await db.delete('OrderItems', where: 'order_item_id = ?', whereArgs: [id]); - } - - // MenuItem table methods - Future>> getMenuItems() async { - final db = await database; - return await db.query('MenuItem'); - } - - Future insertMenuItem(Map menuItem) async { - final db = await database; - return await db.insert('MenuItem', menuItem); - } - - Future updateMenuItem(Map menuItem) async { - final db = await database; - int id = menuItem['item_id']; - return await db.update('MenuItem', menuItem, where: 'item_id = ?', whereArgs: [id]); - } - - Future deleteMenuItem(int id) async { - final db = await database; - return await db.delete('MenuItem', where: 'item_id = ?', whereArgs: [id]); - } - - // SpecialRequest table methods - Future insertSpecialRequest(Map specialRequest) async { - final db = await database; - return await db.insert('SpecialRequest', specialRequest); - } - - Future updateSpecialRequest(Map specialRequest) async { - final db = await database; - int id = specialRequest['special_request_id']; - return await db.update('SpecialRequest', specialRequest, where: 'special_request_id = ?', whereArgs: [id]); - } - - Future deleteSpecialRequest(int id) async { - final db = await database; - return await db.delete('SpecialRequest', where: 'special_request_id = ?', whereArgs: [id]); - } - - // DoctorVisit table methods - Future>> getDoctorVisits() async { - final db = await database; - return await db.query('DoctorVisit'); - } - - Future insertDoctorVisit(Map doctorVisit) async { - final db = await database; - return await db.insert('DoctorVisit', doctorVisit); - } - - Future updateDoctorVisit(Map doctorVisit) async { - final db = await database; - int id = doctorVisit['visit_id']; - return await db.update('DoctorVisit', doctorVisit, where: 'visit_id = ?', whereArgs: [id]); - } - - Future deleteDoctorVisit(int id) async { - final db = await database; - return await db.delete('DoctorVisit', where: 'visit_id = ?', whereArgs: [id]); - } - - // Patient table methods - Future insertPatient(Map patient) async { - final db = await database; - return await db.insert('Patient', patient); - } - - Future updatePatient(Map patient) async { - final db = await database; - int id = patient['patient_id']; - return await db.update('Patient', patient, where: 'patient_id = ?', whereArgs: [id]); - } - - Future deletePatient(int id) async { - final db = await database; - return await db.delete('Patient', where: 'patient_id = ?', whereArgs: [id]); - } - - // Specific use-case Query functions - - // Given DoctorVisit visit_id, get doctor_visit_symptoms and doctor_visit_diagnosis - Future?> getDoctorVisitById(int visitId) async { - final db = await database; - List> results = await db.query( - 'DoctorVisit', - columns: ['doctor_visit_symptoms', 'doctor_visit_diagnosis'], - where: 'visit_id = ?', - whereArgs: [visitId], - ); - if (results.isNotEmpty) { - return results.first; - } - return null; - } - - // Given DoctorVisit patient_id, get doctor_visit_symptoms and doctor_visit_diagnosis - Future>> getDoctorVisitsByPatientId(int patientId) async { - final db = await database; - return await db.query( - 'DoctorVisit', - columns: ['doctor_visit_symptoms', 'doctor_visit_diagnosis'], - where: 'patient_id = ?', - whereArgs: [patientId], - ); - } - - // Given VehicleMaintenance maintenance_id, get vehicle_diagnosis_description and vehicle_required_parts - Future?> getVehicleMaintenanceById(int maintenanceId) async { - final db = await database; - List> results = await db.query( - 'VehicleMaintenance', - columns: ['vehicle_diagnosis_description', 'vehicle_required_parts'], - where: 'maintenance_id = ?', - whereArgs: [maintenanceId], - ); - if (results.isNotEmpty) { - return results.first; - } - return null; - } - - // Given Vehicle vehicle_id, get vehicle_make, vehicle_model, and vehicle_year - Future?> getVehicleById(int vehicleId) async { - final db = await database; - List> results = await db.query( - 'Vehicle', - columns: ['vehicle_make', 'vehicle_model', 'vehicle_year'], - where: 'vehicle_id = ?', - whereArgs: [vehicleId], - ); - if (results.isNotEmpty) { - return results.first; - } - return null; - } - - // Given Vehicle user_id, get all vehicle_id with given user_id - Future> getVehicleIdsByUserId(int userId) async { - final db = await database; - List> results = await db.query( - 'Vehicle', - columns: ['vehicle_id'], - where: 'user_id = ?', - whereArgs: [userId], - ); - return results.map((result) => result['vehicle_id'] as int).toList(); - } - // Get all transcript_id with given user_id - Future> getTranscriptIdsByUserId(int userId) async { - final db = await database; - List> results = await db.query( - 'Transcript', - columns: ['transcript_id'], - where: 'user_id = ?', - whereArgs: [userId], - ); - return results.map((result) => result['transcript_id'] as int).toList(); - } - - // Get all maintenance_id with given user_id - Future> getMaintenanceIdsByUserId(int userId) async { - final db = await database; - List> results = await db.query( - 'VehicleMaintenance', - columns: ['maintenance_id'], - where: 'user_id = ?', - whereArgs: [userId], - ); - return results.map((result) => result['maintenance_id'] as int).toList(); - } - - // Get all item_id from order items with matching given order_id - Future> getItemIdsByOrderId(int orderId) async { - final db = await database; - List> results = await db.query( - 'OrderItems', - columns: ['item_id'], - where: 'order_id = ?', - whereArgs: [orderId], - ); - return results.map((result) => result['item_id'] as int).toList(); - } - - saveTranscript({required int userId, required int transcriptId, required String text, - required String industry,}) async { - Map transcript = { - 'user_id': userId, - 'transcript_id': transcriptId, - 'transcript_text_data': text, - 'transcript_timestamp': DateTime.now().toIso8601String(), - 'transcript_ai_response': '', - 'industry': industry, - }; - await insertTranscript(transcript); - } - - saveTranscriptAiResponse({required int userId, required int transcriptId, - required String text, required String aiResponse, required String industry}) async { - // Save the new transcript to the database using the provided information - Map transcript = { - 'user_id': userId, - 'transcript_id': transcriptId, - 'transcript_text_data': text, - 'transcript_timestamp': DateTime.now().toIso8601String(), - 'transcript_ai_response': aiResponse, - 'industry': industry - }; - await updateTranscript(transcript); - } - - // Search method that will query the transcript information in the database and return - // search results based on the information found. -Future> searchTranscripts(String query, String industry) async { - final db = await database; - - // Compares the query with the data within the transcripts and returns the entries. - final List> results = await db.query( - 'Transcript', - where: '(LOWER(transcript_text_data) LIKE LOWER(?) OR LOWER(transcript_ai_response) LIKE LOWER(?)) AND industry = ?', - whereArgs: ['%$query%', '%$query%', industry], - ); - - return results.map((row) => row['transcript_text_data'] as String).toList(); -} - -Future?> getTranscriptDetails(String entry) async { - final db = await database; - // Select the information i want to display from database - var result = await db.rawQuery( - "SELECT transcript_text_data, transcript_timestamp, transcript_ai_response FROM Transcript WHERE transcript_text_data = ? OR transcript_ai_response = ?", - [entry, entry] - ); - - // Grabs the results and return them - if (result.isNotEmpty) { - return { - 'text': result.first['transcript_text_data'] as String, - 'timestamp': result.first['transcript_timestamp'] as String, - 'ai_response': result.first['transcript_ai_response'] as String, - }; - } - return null; - } - - // Method to insert a document into the Transcript table - Future insertDocument(int transcriptId, String fileName, List fileBytes) async { - final db = await database; - Map document = { - 'transcript_id': transcriptId, - 'transcript_document': fileBytes, - }; - return await db.update( - 'Transcript', - document, - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - } - - // Method to get transcript text data and industry by transcriptId - Future?> getTranscriptTextDataAndIndustryById(int transcriptId) async { - final db = await database; - List> results = await db.query( - 'Transcript', - columns: ['transcript_text_data', 'industry'], - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - if (results.isNotEmpty) { - return { - 'transcript_text_data': results.first['transcript_text_data'] as String, - 'industry': results.first['industry'] as String, - }; - } - return null; - } - - // Method to get document (BLOB) and industry by transcriptId - Future?> getDocumentAndIndustryById(int transcriptId) async { - final db = await database; - List> results = await db.query( - 'Transcript', - columns: ['transcript_document', 'industry'], - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - if (results.isNotEmpty) { - return { - 'transcript_document': results.first['transcript_document'], - 'industry': results.first['industry'] as String, - }; - } - return null; - } - - // Method to insert AI response into the Transcript table by transcriptId - Future insertAiResponse(int transcriptId, String aiResponse) async { - final db = await database; - Map values = { - 'transcript_ai_response': aiResponse, - }; - return await db.update( - 'Transcript', - values, - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - } - - Future updateTranscriptDocument(int transcriptId, List documentBytes) async { - final db = await database; - int count = await db.update( - 'Transcript', - {'transcript_document': documentBytes}, - where: 'transcript_id = ?', - whereArgs: [transcriptId], - ); - return count > 0; - } -} - - // Commented out this method for future use - /* getTranscriptCountForDate(String date) { - // Get the number of transcripts for a given date - Future getTranscriptCountForDate(String date) async { - final db = await database; - List> results = await db.rawQuery( - 'SELECT COUNT(*) as count FROM Transcript WHERE DATE(transcript_timestamp) = ?', - [date], - ); - if (results.isNotEmpty) { - return results.first['count'] as int; - } - return 0; - } - } - }*/ diff --git a/team_b/yappy/lib/services/file_handler.dart b/team_b/yappy/lib/services/file_handler.dart deleted file mode 100644 index 6f30dd95..00000000 --- a/team_b/yappy/lib/services/file_handler.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'dart:io'; -import 'package:flutter/services.dart' show rootBundle; -import 'package:path_provider/path_provider.dart'; -import 'package:path/path.dart'; -import 'package:sqflite/sqflite.dart'; -import 'package:yappy/services/database_helper.dart'; -import 'package:flutter/foundation.dart'; - -class FileHandler { - Future get localStoragePath async { - final directory = await getApplicationDocumentsDirectory(); - return directory.path; - } - - Future get databasePath async { - final databasesPath = await getDatabasesPath(); - return join(databasesPath, 'yappy_database.db'); - } - - Future addDocument(File file) async { - try { - final path = await localStoragePath; - final newFile = File(join(path, basename(file.path))); - await file.copy(newFile.path); - if (kDebugMode) { - print('File added to local storage: ${newFile.path}'); - } - } catch (e) { - if (kDebugMode) { - print('Error adding document: $e'); - } - } - } - - // Used to move a file the user uploads from local storage to the database - Future moveFileToDatabase(DatabaseHelper dbHelper, String fileName, int transcriptId) async { - try { - final path = await localStoragePath; - final file = File(join(path, fileName)); - if (await file.exists()) { - final bytes = await file.readAsBytes(); - await dbHelper.insertDocument(transcriptId, fileName, bytes); - - await file.delete(); - if (kDebugMode) { - print('File moved to database and deleted from local storage: $fileName'); - } - } else { - if (kDebugMode) { - print('File not found in local storage: $fileName'); - } - } - } catch (e) { - if (kDebugMode) { - print('Error moving file to database: $e'); - } - } - } - - // Method to save transcript text data to local storage as a text file - Future saveTranscriptTextToLocal(DatabaseHelper dbHelper, int transcriptId) async { - try { - final transcriptData = await dbHelper.getTranscriptTextDataAndIndustryById(transcriptId); - if (transcriptData != null) { - final textData = transcriptData['transcript_text_data']!; - final industry = transcriptData['industry']!; - final fileName = 'transcript_text_${transcriptId}_$industry.txt'; - final path = await localStoragePath; - final file = File(join(path, fileName)); - await file.writeAsString(textData); - if (kDebugMode) { - print('Transcript text data saved to local storage: $fileName'); - } - return fileName; - } else { - if (kDebugMode) { - print('No transcript data found for ID: $transcriptId'); - } - } - } catch (e) { - if (kDebugMode) { - print('Error saving transcript text data to local storage: $e'); - } - } - return ''; - } - - // Method to save document (BLOB) to local storage as a text file - Future saveDocumentToLocal(DatabaseHelper dbHelper, int transcriptId) async { - try { - final documentData = await dbHelper.getDocumentAndIndustryById(transcriptId); - if (documentData != null) { - final documentBytes = documentData['transcript_document'] as List?; - final industry = documentData['industry']!; - if (documentBytes != null) { - final fileName = 'transcript_document_${transcriptId}_$industry.txt'; - final path = await localStoragePath; - final file = File(join(path, fileName)); - await file.writeAsBytes(documentBytes); - if (kDebugMode) { - print('Document saved to local storage: $fileName'); - } - } else { - if (kDebugMode) { - print('No document found for ID: $transcriptId'); - } - } - } else { - if (kDebugMode) { - print('No document data found for ID: $transcriptId'); - } - } - } catch (e) { - if (kDebugMode) { - print('Error saving document to local storage: $e'); - } - } - } - - Future deleteFile(String fileName) async { - try { - final path = await localStoragePath; - final file = File(join(path, fileName)); - if (await file.exists()) { - await file.delete(); - if (kDebugMode) { - print('File deleted from local storage: $fileName'); - } - } else { - if (kDebugMode) { - print('File not found in local storage: $fileName'); - } - } - } catch (e) { - if (kDebugMode) { - print('Error deleting file: $e'); - } - } - } - - Future copyAssetToLocalStorage(String assetPath, String fileName) async { - try { - final byteData = await rootBundle.load(assetPath); - final file = File(join(await localStoragePath, fileName)); - await file.writeAsBytes(byteData.buffer.asUint8List()); - if (kDebugMode) { - print('File copied from assets to local storage: $fileName'); - } - } catch (e) { - if (kDebugMode) { - print('Error copying file from assets to local storage: $e'); - } - } - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/mechanic_api_module.dart b/team_b/yappy/lib/services/mechanic_api_module.dart deleted file mode 100644 index 3a677473..00000000 --- a/team_b/yappy/lib/services/mechanic_api_module.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'database_helper.dart'; - -class MechanicAPI { - final DatabaseHelper dbHelper = DatabaseHelper(); - - // Fetch the latest transcription for a given user. - // This function gets the transcript IDs for the user, - // then retrieves the text from the most recent transcript. - Future getLatestTranscription(int userId) async { - List transcriptIds = await dbHelper.getTranscriptIdsByUserId(userId); - if (transcriptIds.isEmpty) return null; - int latestTranscriptId = transcriptIds.last; - final db = await dbHelper.database; - List> result = await db.query( - 'Transcript', - columns: ['transcript_text_data'], - where: 'transcript_id = ?', - whereArgs: [latestTranscriptId], - ); - if (result.isNotEmpty) { - return result.first['transcript_text_data'] as String?; - } - return null; - } - - // Simulated extraction function. - // Since the NLP extraction and summarization are assumed to be completed already, - // thisfunction returns processed details based on the transcription content. - Map extractMechanicData(String transcription) { - if (transcription.contains("Honda")) { - return { - 'vehicle': 'Honda Civic 2015', - 'diagnosis': - 'Brake pads require inspection, possible wear; engine knocking suggests immediate engine checkup.', - 'parts': 'Brake pads, Engine oil' - }; - } else { - return { - 'vehicle': 'Unknown Vehicle', - 'diagnosis': 'No diagnostic details available', - 'parts': 'N/A' - }; - } - } - - // Store the processed mechanic service details into the VehicleMaintenance table. - // Note: The VehicleMaintenance table requires a vehicle_id. - // if the vehicle is not directly identified, a dummy value (e.g., 0) is used. - Future storeMechanicService( - int userId, int transcriptId, Map mechanicData) async { - int vehicleId = 1; // Ensure this is valid from DB - - await dbHelper.insertVehicleMaintenance({ - 'transcript_id': transcriptId, - 'user_id': userId, - 'vehicle_id': vehicleId, - 'vehicle_diagnosis_description': mechanicData['diagnosis'], - 'vehicle_required_parts': mechanicData['parts'] - }); - - debugPrint(" Mechanic service stored successfully!"); - } - - // Combines steps: Fetch transcription, extract data, and store the report. - // Returns a report containing the transcription and the processed mechanic data. - Future?> getLatestMechanicReport(int userId) async { - String? transcription = await getLatestTranscription(userId); - if (transcription == null) return null; - Map mechanicData = extractMechanicData(transcription); - List transcriptIds = await dbHelper.getTranscriptIdsByUserId(userId); - int latestTranscriptId = transcriptIds.last; - await storeMechanicService(userId, latestTranscriptId, mechanicData); - return { - 'transcription': transcription, - 'vehicle': mechanicData['vehicle'], - 'diagnosis': mechanicData['diagnosis'], - 'parts': mechanicData['parts'] - }; - } - - // Retrieve the service history for the mechanic API. - // This fetches all maintenance records associated with the user. - Future>> getMechanicServiceHistory( - int userId) async { - List maintenanceIds = await dbHelper.getMaintenanceIdsByUserId(userId); - final db = await dbHelper.database; - List> history = []; - for (int id in maintenanceIds) { - List> result = await db.query( - 'VehicleMaintenance', - where: 'maintenance_id = ?', - whereArgs: [id], - ); - if (result.isNotEmpty) { - history.add(result.first); - } - } - return history; - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/medical_api_module.dart b/team_b/yappy/lib/services/medical_api_module.dart deleted file mode 100644 index 642d6f32..00000000 --- a/team_b/yappy/lib/services/medical_api_module.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'database_helper.dart'; - -class MedicalAPI { - final DatabaseHelper dbHelper = DatabaseHelper(); - - /// 📌 Step 3.1: Retrieve the latest transcription of a patient's consultation. - Future getConsultationTranscription(int visitId) async { - Map? visitData = await dbHelper.getDoctorVisitById(visitId); - - // Extract the transcription text if available, otherwise return null - return visitData?['transcription_text'] as String? ?? "No Transcription Available"; -} - - /// 📌 Step 3.2: Retrieve symptoms & diagnosis already stored in the database. - Future?> getSymptomsAndDiagnosis(int patientId) async { - final records = await dbHelper.getDoctorVisitsByPatientId(patientId); - - if (records.isNotEmpty) { - final latestRecord = records.last; // Get the most recent visit entry - return { - 'symptoms': latestRecord['doctor_visit_symptoms'] ?? 'Unknown', - 'diagnosis': latestRecord['doctor_visit_diagnosis'] ?? 'Unknown', - }; - } - - return null; // No records found - } - - /// 📌 Step 4.1: Store the visit into the DoctorVisit table - Future storeDoctorVisit({ - required int userId, - required int patientId, - required int transcriptId, - required String symptoms, - required String diagnosis, - }) async { - final visitMap = { - 'user_id': userId, - 'transcript_id': transcriptId, - 'patient_id': patientId, - 'doctor_visit_symptoms': symptoms, - 'doctor_visit_diagnosis': diagnosis, - }; - - int visitId = await dbHelper.insertDoctorVisit(visitMap); - return visitId; - } - - /// 📌 Step 4.2: Ensure only authorized users can access records. - /// (For now, we're assuming a secure retrieval function is in place) - Future authorizeUser(int userId) async { - // Assume only doctors or the patient themselves can access - // You can implement role-based access checks here. - return true; // Placeholder for now - } - - /// 📌 Step 5.1: Retrieve ALL medical records for a given patient. - Future>> getPatientMedicalRecords( - int patientId) async { - return await dbHelper.getDoctorVisitsByPatientId(patientId); - } - - /// 📌 Step 5.2: Retrieve past consultations (Transcript + Diagnosis). - Future>> getPastConsultations(int patientId) async { - final medicalRecords = await getPatientMedicalRecords(patientId); - - // Ensure pastConsultations list is initialized - List> pastConsultations = []; - - for (var record in medicalRecords) { - int? transcriptId = - record['transcript_id'] as int?; // Ensure transcriptId is nullable - - // Safely retrieve transcript - String? transcriptText; - if (transcriptId != null) { - Map? transcriptData = await dbHelper.getTranscriptById(transcriptId); - - // Extract the actual transcript text if available - transcriptText = transcriptData?['transcript_text'] as String? ?? "No Transcript Available"; - } else { - transcriptText = "No Transcript Available"; // Fallback for null transcriptId - } - - // Add the record with the transcript to the consultations list - pastConsultations.add({ - ...record, - 'transcript_text': transcriptText, // Include transcript text in the result - }); - - } - - return pastConsultations; - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/model_manager.dart b/team_b/yappy/lib/services/model_manager.dart deleted file mode 100644 index c216c29a..00000000 --- a/team_b/yappy/lib/services/model_manager.dart +++ /dev/null @@ -1,578 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:isolate'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:http/http.dart' as http; -import 'package:archive/archive.dart'; -import 'package:path/path.dart' as path; -import 'package:connectivity_plus/connectivity_plus.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'toast_service.dart'; - -// Data class for passing to isolate -class ExtractionData { - final List fileBytes; - final String modelDir; - final List outputMappings; - final SendPort sendPort; - - ExtractionData({ - required this.fileBytes, - required this.modelDir, - required this.outputMappings, - required this.sendPort, - }); -} - -// Class for mapping source files to destination names -class OutputFileMapping { - final String source; - final String destination; - - OutputFileMapping({ - required this.source, - required this.destination, - }); - - // Factory constructor from JSON - factory OutputFileMapping.fromJson(Map json) { - return OutputFileMapping( - source: json['source'], - destination: json['destination'], - ); - } -} - -class ModelInfo { - final String id; - final String name; - final String url; - final bool isCompressed; - final String type; - final String? modelType; - final List outputFiles; - final double size; // Size in MB - - ModelInfo({ - required this.id, - required this.name, - required this.url, - required this.isCompressed, - required this.type, - this.modelType, - required this.outputFiles, - required this.size, - }); - - // Factory constructor to create ModelInfo from JSON - factory ModelInfo.fromJson(Map json) { - final outputFilesJson = json['outputFiles'] as List; - - return ModelInfo( - id: json['id'], - name: json['name'], - url: json['url'], - isCompressed: json['isCompressed'], - type: json['type'], - modelType: json['modelType'], // Added modelType - outputFiles: outputFilesJson - .map((fileJson) => OutputFileMapping.fromJson(fileJson)) - .toList(), - size: json['size'], - ); - } - - String getFilename() { - return path.basename(url); - } -} - -class ModelManager { - // Base directory for storing models - late final Future _modelDirPath; - - // List to hold models loaded from config - List _models = []; - - // Config file path in assets - static const String _configAssetPath = 'assets/models_config.json'; - - final _toastService = ToastService(); - - ModelManager() { - _modelDirPath = _initModelDir(); - _loadModelsFromConfig(); - } - - // Initialize the models directory - Future _initModelDir() async { - final appDir = await getApplicationCacheDirectory(); - final modelDir = Directory('${appDir.path}/models'); - if (!await modelDir.exists()) { - await modelDir.create(recursive: true); - } - return modelDir.path; - } - - // Load models from the config file - Future _loadModelsFromConfig() async { - try { - // Load the JSON file from assets - final String jsonContent = await rootBundle.loadString(_configAssetPath); - final Map configData = json.decode(jsonContent); - - // Parse models - final List modelsJson = configData['models']; - _models = modelsJson.map((modelJson) => ModelInfo.fromJson(modelJson)).toList(); - - debugPrint('Loaded ${_models.length} models from config'); - } catch (e) { - debugPrint('Error loading models from config: $e'); - // Fallback to empty list - _models = []; - } - } - - // Reload models from config - Future reloadModelsConfig() async { - await _loadModelsFromConfig(); - } - - // Get the list of models (for UI display) - List get models => List.unmodifiable(_models); - - // Get model path by type and file type - Future getModelPath(String modelType, String fileName) async { - final modelDir = await _modelDirPath; - return '$modelDir/$fileName'; - } - - // Find a model by type - ModelInfo? getModelByType(String type) { - return _models.firstWhere( - (model) => model.type == type, - orElse: () => throw Exception('No model found with type: $type'), - ); - } - - // Get model type string by type - Future getModelTypeString(String type) async { - try { - final model = getModelByType(type); - return model?.modelType; - } catch (e) { - debugPrint('Error getting model type: $e'); - return null; - } - } - - // Check if all required models exist - Future modelsExist() async { - try { - final modelDir = await _modelDirPath; - - // Check for a marker file indicating successful model installation - final markerFile = File('$modelDir/models_installed.txt'); - if (await markerFile.exists()) { - return true; - } - - // Make sure we've loaded the models config - if (_models.isEmpty) { - await _loadModelsFromConfig(); - } - - // Check if all destination files exist for all models - for (var model in _models) { - for (var outputFile in model.outputFiles) { - final file = File('$modelDir/${outputFile.destination}'); - if (!await file.exists()) { - return false; - } - } - } - - // If all files exist but marker doesn't, create the marker - await markerFile.writeAsString('Models installed on ${DateTime.now()}'); - return true; - } catch (e) { - debugPrint('Error checking models: $e'); - return false; - } - } - - // Check if we should only download on Wi-Fi - Future _getWifiOnlySetting() async { - final prefs = await SharedPreferences.getInstance(); - return prefs.getBool('wifi_only_downloads') ?? true; // Default to true - } - - // Save Wi-Fi only setting - Future saveWifiOnlySetting(bool wifiOnly) async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setBool('wifi_only_downloads', wifiOnly); - } - - // Check network connectivity - Future _checkConnectivity() async { - final wifiOnly = await _getWifiOnlySetting(); - - if (!wifiOnly) { - return true; // Download allowed on any connection - } - - // Check for WiFi connection - final connectivityResult = await Connectivity().checkConnectivity(); - return connectivityResult.contains(ConnectivityResult.wifi); - } - - // Show download dialog to user - Future showDownloadDialog(BuildContext context) async { - // Make sure models are loaded - if (_models.isEmpty) { - await _loadModelsFromConfig(); - } - - // Calculate total download size - final totalSize = _models.fold(0.0, (sum, model) => sum + model.size); - - if (!context.mounted) return false; - return await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext dialogContext) { - return AlertDialog( - title: const Text('Download AI Models'), - content: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'This app requires downloading speech recognition models ' - 'to function properly (${totalSize.toStringAsFixed(1)} MB total).', - ), - const SizedBox(height: 12), - const Text( - 'Models will be downloaded when connected to WiFi. ' - 'You can change this in Settings later.', - ), - const SizedBox(height: 16), - const Text('Models to download:'), - ...List.generate(_models.length, (index) { - final model = _models[index]; - return Padding( - padding: const EdgeInsets.only(top: 8), - child: Text( - '• ${model.name} (${model.size.toStringAsFixed(1)} MB)', - style: const TextStyle(fontSize: 14), - ), - ); - }), - ], - ), - ), - actions: [ - TextButton( - child: const Text('Later'), - onPressed: () { - Navigator.of(dialogContext).pop(false); - }, - ), - TextButton( - child: const Text('Download Now'), - onPressed: () { - Navigator.of(dialogContext).pop(true); - }, - ), - ], - ); - }, - ) ?? false; // Default to false if dialog is dismissed - } - - // Show connectivity warning dialog - Future _showConnectivityWarning(BuildContext context) async { - return await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext dialogContext) { - return AlertDialog( - title: const Text('Wi-Fi Required'), - content: const Text( - 'You have selected to download models only on Wi-Fi. ' - 'Please connect to a Wi-Fi network or change your settings to continue.' - ), - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(dialogContext).pop(false); - }, - ), - TextButton( - child: const Text('Change Setting'), - onPressed: () { - Navigator.of(dialogContext).pop(true); - }, - ), - ], - ); - }, - ) ?? false; // Default to false if dialog is dismissed - } - - // Check if downloads are currently in progress - bool isDownloadInProgress() { - return _toastService.isToastVisible; - } - - // Download all models - Future downloadModels(BuildContext context) async { - // Make sure models are loaded - if (_models.isEmpty) { - await _loadModelsFromConfig(); - - // If still empty after loading, show error - if (_models.isEmpty) { - _toastService.showError('Failed to load model configuration.'); - return false; - } - } - - // Check connectivity first - still need context for initial dialogs - final canDownload = await _checkConnectivity(); - if (!canDownload && context.mounted) { - final changeSettings = await _showConnectivityWarning(context); - if (changeSettings) { - // User wants to change settings - await saveWifiOnlySetting(false); - } else { - // User canceled download - return false; - } - } - - // Start async download process - _startDownloadProcess(); - - // Return true to indicate the download has started - return true; - } - - // Handle the download process independently of any specific context - Future _startDownloadProcess() async { - try { - // Show initial toast notification - _toastService.showToast('Starting downloads...', progress: 0.0); - - final modelDir = await _modelDirPath; - int completedModels = 0; - - // Process each model - for (var model in _models) { - // Update progress - _toastService.showToast( - 'Downloading ${model.name}...', - progress: completedModels / _models.length, - ); - - // Download file - final response = await http.get(Uri.parse(model.url)); - if (response.statusCode != 200) { - throw Exception('Failed to download ${model.name}'); - } - - // Process based on file type - if (model.isCompressed) { - // Update progress - _toastService.showToast( - 'Extracting ${model.name}...', - progress: completedModels / _models.length, - ); - - // Handle compressed .bz2 file - now using isolate - await _processCompressedFileInIsolate( - response.bodyBytes, - modelDir, - model.outputFiles, - ); - } else { - // Handle direct files with mapping to new name - for (var outputFile in model.outputFiles) { - final file = File('$modelDir/${outputFile.destination}'); - await file.writeAsBytes(response.bodyBytes); - } - } - - completedModels++; - _toastService.updateProgress(completedModels / _models.length); - } - - // Create marker file to indicate successful installation - final markerFile = File('$modelDir/models_installed.txt'); - await markerFile.writeAsString('Models installed on ${DateTime.now()}'); - - // Hide toast and show success toast - _toastService.hideToast(); - _toastService.showSuccess('All models have been downloaded successfully.'); - - } catch (e) { - debugPrint('Error downloading models: $e'); - - // Hide progress toast - _toastService.hideToast(); - - // Show error toast - _toastService.showError('Failed to download models: $e'); - } - } - - // Process compressed file in a separate isolate - Future _processCompressedFileInIsolate( - List fileBytes, - String modelDir, - List outputMappings, - ) async { - // Create a ReceivePort for communication - final receivePort = ReceivePort(); - - // Prepare data to send to isolate - final data = ExtractionData( - fileBytes: fileBytes, - modelDir: modelDir, - outputMappings: outputMappings, - sendPort: receivePort.sendPort, - ); - - // Spawn the isolate - await Isolate.spawn(_extractInIsolate, data); - - // Wait for a result from the isolate - await for (final message in receivePort) { - if (message == 'done') { - // Extraction completed - break; - } else if (message is String && message.startsWith('error:')) { - // Error occurred in isolate - throw Exception(message.substring(6)); - } - } - - // Close the port when done - receivePort.close(); - } - - // Isolate entry point for extraction - static Future _extractInIsolate(ExtractionData data) async { - try { - // Decompress bz2 - final archive = BZip2Decoder().decodeBytes(data.fileBytes); - - // Extract tar archive - final tarArchive = TarDecoder().decodeBytes(archive); - - // Create a mapping for efficient lookup - final Map pathMappings = {}; - for (final mapping in data.outputMappings) { - pathMappings[mapping.source] = mapping.destination; - } - - // Track which files we've processed - final Set processedDestinations = {}; - - // Process each file in the archive - for (final file in tarArchive) { - if (!file.isFile) continue; - - // Check for exact matches - String? destinationFile; - - for (final sourcePath in pathMappings.keys) { - if (file.name == sourcePath) { - destinationFile = pathMappings[sourcePath]; - break; - } - } - - // Skip files we don't need - if (destinationFile == null) continue; - - // Mark as processed - processedDestinations.add(destinationFile); - - // Create the destination file - final filePath = '${data.modelDir}/$destinationFile'; - - // Create parent directories if needed - final parentDir = Directory(path.dirname(filePath)); - if (!await parentDir.exists()) { - await parentDir.create(recursive: true); - } - - // Write file - await File(filePath).writeAsBytes(file.content as List); - } - - // Check if all needed files were found - if (processedDestinations.length != pathMappings.length) { - throw Exception('Not all required files were found in the archive'); - } - - // Signal completion - data.sendPort.send('done'); - } catch (e) { - // Send error back to main isolate - data.sendPort.send('error: $e'); - } finally { - // Terminate the isolate - Isolate.exit(); - } - } - - // Delete all downloaded models - Future deleteModels() async { - try { - final modelDir = await _modelDirPath; - final directory = Directory(modelDir); - - if (await directory.exists()) { - // Get all immediate children first - List children = await directory.list().toList(); - - // Delete each child recursively - for (var entity in children) { - try { - await entity.delete(recursive: true); - } catch (e) { - // Log but continue with other deletions - debugPrint('Error deleting ${entity.path}: $e'); - } - } - } - - // Double-check the marker file - final markerFile = File('$modelDir/models_installed.txt'); - if (await markerFile.exists()) { - await markerFile.delete(); - } - - return true; - } catch (e) { - debugPrint('Error deleting models: $e'); - return false; - } - } - - // Trigger model download from settings page - Future downloadModelsFromSettings(BuildContext context) async { - final shouldDownload = await showDownloadDialog(context); - if (shouldDownload && context.mounted) { - return await downloadModels(context); - } - return false; - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/offline_model.dart b/team_b/yappy/lib/services/offline_model.dart deleted file mode 100644 index 32eec9cd..00000000 --- a/team_b/yappy/lib/services/offline_model.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; -import 'model_manager.dart'; - -Future getOfflineModelConfig( - {required int type}) async { - final modelManager = ModelManager(); - - switch (type) { - case 0: - final modelType = await modelManager.getModelTypeString('offline') ?? 'whisper'; - - return sherpa_onnx.OfflineModelConfig( - whisper: sherpa_onnx.OfflineWhisperModelConfig( - encoder: await modelManager.getModelPath('offline', 'offline_encoder.onnx'), - decoder: await modelManager.getModelPath('offline', 'offline_decoder.onnx'), - ), - tokens: await modelManager.getModelPath('offline', 'offline_tokens.txt'), - modelType: modelType, - debug: false, - numThreads: 1 - ); - default: - throw ArgumentError('Unsupported type: $type'); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/online_model.dart b/team_b/yappy/lib/services/online_model.dart deleted file mode 100644 index e2c9ddd0..00000000 --- a/team_b/yappy/lib/services/online_model.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; -import 'model_manager.dart'; - -Future getOnlineModelConfig( - {required int type}) async { - final modelManager = ModelManager(); - - switch (type) { - case 0: - final modelType = await modelManager.getModelTypeString('online') ?? 'zipformer'; - - return sherpa_onnx.OnlineModelConfig( - transducer: sherpa_onnx.OnlineTransducerModelConfig( - encoder: await modelManager.getModelPath('online', 'online_encoder.onnx'), - decoder: await modelManager.getModelPath('online', 'online_decoder.onnx'), - joiner: await modelManager.getModelPath('online', 'online_joiner.onnx'), - ), - tokens: await modelManager.getModelPath('online', 'online_tokens.txt'), - modelType: modelType, - ); - default: - throw ArgumentError('Unsupported type: $type'); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/openai_helper.dart b/team_b/yappy/lib/services/openai_helper.dart deleted file mode 100644 index d2fb29d4..00000000 --- a/team_b/yappy/lib/services/openai_helper.dart +++ /dev/null @@ -1,429 +0,0 @@ -import 'dart:convert'; - -import 'package:dart_openai/dart_openai.dart'; -import 'package:flutter/foundation.dart'; -import 'package:http/http.dart' as http; -import 'package:yappy/main.dart'; -import 'package:yappy/services/database_helper.dart'; -import 'package:yappy/services/file_handler.dart'; - -class OpenAIHelper { - final List> messages = []; - final currentOpenAIModel = "gpt-4o-mini"; // Ensure this is a current and valid model - - final String restaurantContextPrompt = - '''You are a restaurant assistant. Take the following audio transcript of a waiter taking patrons' orders and generate a summary of patrons' orders at a restaurant. You must separate out different speakers' orders and refer to them using using "Seat 1", "Seat 2", "Seat 3", etc. - - Respond in plain text. - - Example format: - - Seat 1: Hamburger, hold the lettuce, fries, Diet Dr. Pepper. - - Seat 2: Caesar salad, iced tea. - - Audio Transcript: - '''; - - final String mechanicContextPrompt = - '''You are a vehicle mechanic assistant. Take the following audio transcript of a customer describing their vehicle's issues and generate a summary of vehicle's issues and include suggestions for resolution. - - Respond in plain text. - - Example format: - - Customer: My car is making a weird whirring noise at idle. It is also leaking oil. - - Audio Transcript: - '''; - - final String medicalContextPrompt = - '''You are a medical assistant. Take the following audio transcript of a physician discussing a patient's concerns and generate a summary of patient's issues and include suggestions for resolution. - - Respond in plain text. - - Example format: - - Patient: I've been feeling really itchy recently. And I've been having trouble sleeping. - - Physician: I see. I recommend you take an antihistamine for the itching and try to avoid caffeine in the evenings. - - Audio Transcript: - '''; - - Future summarizeTranscription(int userId, String industry, int transcriptId) async { - // Pulls the transcript text from the database - Map? transcript = await dbHelper.getTranscriptById(transcriptId); - if (transcript == null) { - throw Exception('Transcript with given ID not found'); - } - - String contextPrompt = ""; - switch (industry) { - case "Restaurant": - contextPrompt = restaurantContextPrompt; - break; - case "Medical Doctor" || "Medical Patient": - contextPrompt = medicalContextPrompt; - break; - case "Vehicle Maintenance": - contextPrompt = mechanicContextPrompt; - break; - } - - String fullPromptToSend = contextPrompt + transcript['transcript_text_data']; - - List messages = [ - OpenAIChatCompletionChoiceMessageModel( - role: OpenAIChatMessageRole.user, content: [OpenAIChatCompletionChoiceMessageContentItemModel.text(fullPromptToSend)]) - ]; - - try { - final completion = await OpenAI.instance.chat - .create(model: currentOpenAIModel, messages: messages); - // Adds the AI response to the previously saved transcript in the database - await dbHelper.saveTranscriptAiResponse(userId: userId, - transcriptId: transcriptId, - text: transcript['transcript_text_data'], - aiResponse: completion.choices[0].message.content.toString(), industry: industry); - return completion.choices[0].message.content.toString(); - } catch (e) { - rethrow; - } - } - - Future startTranscriptChatAssistant(String userQuery, String industry) async { - - /** - * Chat assistant setup works as follows: - * 1. Upload a file to OpenAI - * 2. Create a vector store - * 3. Attach the file to the vector store - * 4. Create an assistant - * 5. Create a thread for the assistant to use - */ - - FileHandler fileHandler = FileHandler(); - OpenAIHelper openAIHelper = OpenAIHelper(); - DatabaseHelper dbHelper = DatabaseHelper(); - String? response = ""; - String? apiKey = preferences.getString('openai_api_key'); - - // Pulls all transcripts for the current industry - List> transcripts = await dbHelper.getAllTranscriptsByIndustry(industry); - // Saves all industry transcripts to local storage - List localTranscriptFileNames = []; - for (var transcript in transcripts) { - String currentFileName = await fileHandler.saveTranscriptTextToLocal(dbHelper, transcript['transcript_id']); - localTranscriptFileNames.add(currentFileName); - } - - List transcriptPaths = []; - for (String transcriptId in localTranscriptFileNames) { - String path = '${await fileHandler.localStoragePath}/$transcriptId'; - transcriptPaths.add(path); - } - - List? fileIds = await openAIHelper.uploadFile(transcriptPaths, apiKey); - String? vectorStoreId = "", assistantId = "", threadId = ""; - - bool successfulSetup = false; - if (fileIds != null) { - vectorStoreId = await openAIHelper.createVectorStore(apiKey); - if (vectorStoreId != null) { - // Attach the files to the vector store - bool attached = await openAIHelper.attachFilesToVectorStore(vectorStoreId, fileIds, apiKey); - if (attached) { - // Create an Assistant - assistantId = await createOpenAIAssistant(vectorStoreId, fileIds, apiKey); - if (assistantId != null) { - // Create a Thread - threadId = await createNewThreadForAssistant(apiKey); - if (threadId != null) { - debugPrint("✅ All chat setup steps completed successfully!"); - successfulSetup = true; - } - } - } - } - } - - /** - * Chat assistant run works as follows: - * 1. Send the user message to the created thread - * 2. Run the assistant on the thread - * 3. Query the current vector store using the assistant for information based on the user's input question - * 4. Polls for results and returns them to the user as a response - */ - if (successfulSetup) { - await openAIHelper.sendMessageToThread(threadId!, userQuery, apiKey); - String? runId = await openAIHelper.runAssistantOnThread(threadId, assistantId!, apiKey!); - if (runId != null) { - debugPrint("🚀 Polling in background for Yappy assistant response!"); - response = await openAIHelper.getAssistantResponseInBackground(threadId, runId, apiKey); - } - } - - // Clean up local storage after assistant processing has completed - for (String currentFileName in localTranscriptFileNames) { - await fileHandler.deleteFile(currentFileName); - } - - return response; - } - - Future?> uploadFile(List filePaths, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/files"); - - List fileIds = []; - for (String filePath in filePaths) { - var request = http.MultipartRequest("POST", url) - ..headers["Authorization"] = "Bearer $apiKey" - ..headers["OpenAI-Beta"] = "assistants=v2" - ..fields["purpose"] = "assistants" - ..files.add(await http.MultipartFile.fromPath("file", filePath)); - - var response = await request.send(); - var responseBody = await response.stream.bytesToString(); - var jsonResponse = jsonDecode(responseBody); - - if (response.statusCode == 200) { - debugPrint("✅ File uploaded: ${jsonResponse["id"]}"); - fileIds.add(jsonResponse["id"]); - } else { - debugPrint("❌ File upload failed: $responseBody"); - return null; - } - } - return fileIds; - } - - Future createVectorStore(apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/vector_stores"); - - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json" - }, - body: jsonEncode({"name": "Transcript Vector Store"}), - ); - var jsonResponse = jsonDecode(response.body); - - if (response.statusCode == 200) { - debugPrint("✅ Vector store created: ${jsonResponse["id"]}"); - return jsonResponse["id"]; - } else { - debugPrint("❌ Vector store creation failed: ${response.body}"); - return null; - } - } - - Future attachFilesToVectorStore(String vectorStoreId, List fileIds, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/vector_stores/$vectorStoreId/files"); - - for (String fileId in fileIds) { - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - }, - body: jsonEncode({"file_id": fileId}), - ); - - if (response.statusCode != 200) { - debugPrint("❌ Attaching file failed: ${response.body}"); - return false; - } else { - debugPrint("✅ File with ID $fileId attached to vector store."); - } - } - return true; - } - - Future createOpenAIAssistant(String vectorStoreId, List fileIds, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/assistants"); - - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }, - body: jsonEncode({ - "name": "Yappy", - "instructions": "You can retrieve transcript information from a vector store. No need to cite sources, and please use complete sentences rather then bullet points. Respond in plain text.", - "model": currentOpenAIModel, - "tools": [ - {"type": "file_search"}, - {"type": "code_interpreter"}, - ], - "tool_resources": { - "file_search": { - "vector_store_ids": [vectorStoreId] - }, - "code_interpreter": { - "file_ids": fileIds - } - } - }), - ); - - if (response.statusCode == 200) { - var jsonResponse = jsonDecode(response.body); - debugPrint("✅ Assistant created: ${jsonResponse["id"]}"); - return jsonResponse["id"]; // Return Assistant ID - } else { - debugPrint("❌ Assistant creation failed: ${response.body}"); - return null; - } - } - - Future createNewThreadForAssistant(apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/threads"); - - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }, - body: jsonEncode({}), - ); - - if (response.statusCode == 200) { - var jsonResponse = jsonDecode(response.body); - debugPrint("✅ Thread created: ${jsonResponse["id"]}"); - return jsonResponse["id"]; - } else { - debugPrint("❌ Thread creation failed: ${response.body}"); - return null; - } - } - - Future sendMessageToThread(String threadId, String message, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/threads/$threadId/messages"); - - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }, - body: jsonEncode({ - "role": "user", - "content": message - }), - ); - - return response.statusCode == 200; - } - - Future runAssistantOnThread(String threadId, String assistantId, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/threads/$threadId/runs"); - - var response = await http.post( - url, - headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }, - body: jsonEncode({ - "assistant_id": assistantId - }), - ); - - if (response.statusCode == 200) { - var jsonResponse = jsonDecode(response.body); - debugPrint("✅ Run created: ${jsonResponse["id"]}"); - return jsonResponse["id"]; - } else { - debugPrint("❌ Failed to run assistant: ${response.body}"); - return null; - } - } - - Future getAssistantResponseInBackground(String threadId, String runId, String apiKey) async { - return compute(getAssistantResponseIsolate, {"threadId": threadId, "runId": runId, "apiKey": apiKey}); - } - - Future getAssistantResponseIsolate(Map params) async { - String threadId = params["threadId"]!; - String runId = params["runId"]!; - String apiKey = params["apiKey"]!; - - return await getAssistantResponse(threadId, runId, apiKey); - } - - Future getAssistantResponse(String threadId, String runId, apiKey) async { - var url = Uri.parse("https://api.openai.com/v1/threads/$threadId/runs/$runId"); - int maxAttempts = 5; // Limit retries - int attempt = 0; - - while (attempt < maxAttempts) { - // Poll at an interval => on separate thread to prevent blocking the UI - await Future.delayed(Duration(seconds: 3)); - attempt++; - - var response = await http.get(url, headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }); - - var jsonResponse = jsonDecode(utf8.decode(response.bodyBytes)); - String status = jsonResponse["status"]; - - if (status == "completed") { - break; // Exit loop when assistant has finished processing - } else if (status == "failed" || status == "cancelled") { - debugPrint("❌ Assistant run failed: $jsonResponse"); - return null; - } - } - - // Fetch latest messages in the thread to get assistant's response - return getLatestAssistantMessage(threadId, apiKey); - } - - Future getLatestAssistantMessage(String threadId, apiKey) async { - debugPrint("Fetching latest assistant response on thread with ID $threadId"); - var url = Uri.parse("https://api.openai.com/v1/threads/$threadId/messages"); - - var response = await http.get(url, headers: { - "Authorization": "Bearer $apiKey", - "Content-Type": "application/json", - "OpenAI-Beta" : "assistants=v2" - }); - - if (response.statusCode == 200) { - var jsonResponse = jsonDecode(utf8.decode(response.bodyBytes)); - var messages = jsonResponse["data"]; - - for (var message in messages.reversed) { // Read messages from newest to oldest - if (message["role"] == "assistant") { - String textResponse = message["content"][0]["text"]["value"]; - return cleanResponse(textResponse); - } - } - } else { - debugPrint("❌ Failed to fetch messages: ${response.body}"); - } - - return null; - } - - // Helper function to remove unwanted characters - String cleanResponse(String response) { - // Remove source citations - response = response.replaceAll(RegExp(r'【\d+:\d+†source】'), '').trim(); - // Remove unwanted characters and return - return response.replaceAll(RegExp(r'[\u0000-\u001F\u007F-\u009F]'), '').trim(); - } -} diff --git a/team_b/yappy/lib/services/restaurant_api_module.dart b/team_b/yappy/lib/services/restaurant_api_module.dart deleted file mode 100644 index 6e847bb6..00000000 --- a/team_b/yappy/lib/services/restaurant_api_module.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'database_helper.dart'; - -class RestaurantAPI { - final DatabaseHelper dbHelper = DatabaseHelper(); - - //Steps 1,2,3,4 needs to be done then in step 4 we will get extractedItems List - which contains exact orders - e.g[pizza,coke,chips] then that extractedItems - //needs to be passed to step 5 - - /// STEP 5: VALIDATE AGAINST THE RESTAURANT MENU - /// We get a list of items from the LLM (e.g. ["Margherita Pizza", "Coke"]). - /// We compare each item with what’s in the MenuItem table. - /// Only items that match are returned in `validItems`. - Future> validateMenuItems(List extractedItems) async { - // 1) Fetch the menu from the database (MenuItem table). - final db = await dbHelper.database; - final menuRows = - await db.query('MenuItem'); // Must contain 'item_name' column - - // Convert each item_name to lowercase for easy comparison - List menuNames = menuRows - .map((row) => (row['item_name'] as String).toLowerCase()) - .toList(); - - // 2) Check which extracted items exist in the menu - List validItems = []; - for (var item in extractedItems) { - for (var menuItem in menuNames) { - if (item.toLowerCase().contains(menuItem)) { - validItems.add(item); - break; - } - } - } - - return validItems; - } - - /// STEP 6: STORE THE VALIDATED ORDER IN THE DATABASE - /// Once we have a list of valid items, we store them in RestaurantOrder - /// with a "Pending" status. For simplicity, we join them into a single string - /// (e.g. "Margherita Pizza, Coke, Garlic Bread"). - Future storeValidatedOrder(List validItems) async { - if (validItems.isEmpty) { - debugPrint(" No valid items to store in database.Please chech whether MenuItem table and RestaurantOrder table has column or not.If not then create it"); - return; - } - - String orderText = validItems.join(", "); - debugPrint("Storing order: $orderText"); - - final db = await dbHelper.database; - await db.insert('RestaurantOrder', { - 'order_text': orderText, - 'order_status': 'Pending', - }); - - debugPrint("Order successfully stored in database."); - } - - /// STEP 7: UI FETCHES & DISPLAYS ORDER SUMMARY - /// - /// We provide a method to retrieve the latest orders from RestaurantOrder - /// so the UI can display them. - Future>> getOrderHistory() async { - final db = await dbHelper.database; - return await db.query('RestaurantOrder', orderBy: 'order_id DESC'); - } - - // ------------------------------------------------------------------- - // Optional convenience method that does Steps 5 & 6 in one shot: - // Given a list of extracted items, validate them, then store them. - // The UI can then call getOrderHistory to show it. - // ------------------------------------------------------------------- - Future processValidatedItems(List extractedItems) async { - // Step 5 - List validItems = await validateMenuItems(extractedItems); - - // Step 6 - await storeValidatedOrder(validItems); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/speaker_model.dart b/team_b/yappy/lib/services/speaker_model.dart deleted file mode 100644 index dd59d212..00000000 --- a/team_b/yappy/lib/services/speaker_model.dart +++ /dev/null @@ -1,12 +0,0 @@ -import './model_manager.dart'; - -Future getSpeakerModel({required int type}) async { - final modelManager = ModelManager(); - - switch (type) { - case 0: - return await modelManager.getModelPath('speaker', 'speaker_model.onnx'); - default: - throw ArgumentError('Unsupported type: $type'); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/speech_isolate.dart b/team_b/yappy/lib/services/speech_isolate.dart deleted file mode 100644 index 5860c44e..00000000 --- a/team_b/yappy/lib/services/speech_isolate.dart +++ /dev/null @@ -1,326 +0,0 @@ -import 'dart:isolate'; -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; - -// Message to be sent to the isolate -class ProcessSegmentMessage { - final Float32List samples; - final int sampleRate; - final int segmentIndex; - final Map recognizerConfigs; - - ProcessSegmentMessage({ - required this.samples, - required this.sampleRate, - required this.segmentIndex, - required this.recognizerConfigs, - }); -} - -// Response from the isolate -class ProcessSegmentResult { - final int segmentIndex; - final String text; - final String speakerId; - final Float32List? embedding; - final bool success; - final String? error; - final int? newSpeakerCount; - - ProcessSegmentResult({ - required this.segmentIndex, - required this.text, - required this.speakerId, - this.embedding, - required this.success, - this.error, - this.newSpeakerCount, - }); -} - -class SpeechProcessingIsolate { - Isolate? _isolate; - SendPort? _sendPort; - final _receivePort = ReceivePort(); - final _responseCompleter = Completer(); - - // Stream controller for receiving results - final _resultController = StreamController.broadcast(); - Stream get results => _resultController.stream; - - // Keep track of speaker count locally in the isolate handler - int _currentSpeakerCount = 0; - - // Initialize the isolate and recognizers - Future initialize(Map configs) async { - // Check if already initialized - if (_isolate != null) return; - - // Start the isolate - _isolate = await Isolate.spawn( - _isolateEntry, - [_receivePort.sendPort, configs] - ); - - // Set up communication - _receivePort.listen((message) { - if (message is SendPort) { - // First message is the SendPort for communicating with the isolate - _sendPort = message; - _responseCompleter.complete(message); - } else if (message is ProcessSegmentResult) { - // Subsequent messages are results from the isolate - - // Debug the speaker ID - debugPrint("Received result from isolate - Speaker ID: ${message.speakerId}, Count: ${message.newSpeakerCount}"); - - // Update local speaker count if needed - if (message.newSpeakerCount != null && message.newSpeakerCount! > _currentSpeakerCount) { - _currentSpeakerCount = message.newSpeakerCount!; - debugPrint("Updated local speaker count to: $_currentSpeakerCount"); - } - - _resultController.add(message); - } - }); - - // Wait until communication is established - await _responseCompleter.future; - } - - // Process a segment asynchronously - Future processSegment(ProcessSegmentMessage message) async { - if (_sendPort == null) { - throw Exception('Isolate not initialized'); - } - - // Update our local copy of speaker count if the incoming count is higher - if (message.recognizerConfigs['currentSpeakerCount'] != null) { - int incomingSpeakerCount = message.recognizerConfigs['currentSpeakerCount']; - if (incomingSpeakerCount > _currentSpeakerCount) { - _currentSpeakerCount = incomingSpeakerCount; - debugPrint("Updated isolate speaker count to: $_currentSpeakerCount"); - } - } - - // Send the message to isolate with updated speaker count - final updatedMessage = ProcessSegmentMessage( - samples: message.samples, - sampleRate: message.sampleRate, - segmentIndex: message.segmentIndex, - recognizerConfigs: { - ...message.recognizerConfigs, - 'currentSpeakerCount': _currentSpeakerCount, - }, - ); - - _sendPort!.send(updatedMessage); - } - - // Update the speaker count (call this when a new speaker is detected in the main thread) - void updateSpeakerCount(int count) { - if (count > _currentSpeakerCount) { - _currentSpeakerCount = count; - debugPrint("Manually updated isolate speaker count to: $_currentSpeakerCount"); - } - } - - // Dispose resources - void dispose() { - _isolate?.kill(priority: Isolate.immediate); - _isolate = null; - _sendPort = null; - _receivePort.close(); - _resultController.close(); - } - - // Static entry point for the isolate - static void _isolateEntry(List args) { - final SendPort sendPort = args[0]; - final configs = args[1] as Map; - - final receivePort = ReceivePort(); - sendPort.send(receivePort.sendPort); - - // Initialize recognizers - sherpa_onnx.initBindings(); - sherpa_onnx.OfflineRecognizer? offlineRecognizer; - sherpa_onnx.SpeakerEmbeddingExtractor? speakerExtractor; - sherpa_onnx.SpeakerEmbeddingManager? speakerManager; - - // Track speaker count inside the isolate - int isolateSpeakerCount = 0; - - _initializeRecognizers(configs).then((initialized) { - if (initialized != null) { - offlineRecognizer = initialized['offlineRecognizer']; - speakerExtractor = initialized['speakerExtractor']; - speakerManager = initialized['speakerManager']; - - receivePort.listen((message) { - if (message is ProcessSegmentMessage) { - // Update speaker count from message if available - if (message.recognizerConfigs['currentSpeakerCount'] != null) { - int msgCount = message.recognizerConfigs['currentSpeakerCount']; - if (msgCount > isolateSpeakerCount) { - isolateSpeakerCount = msgCount; - debugPrint("Isolate updated count to: $isolateSpeakerCount"); - } - } - - _processSegment( - message, - offlineRecognizer!, - speakerExtractor!, - speakerManager!, - sendPort, - isolateSpeakerCount, - (newCount) { - isolateSpeakerCount = newCount; - debugPrint("Callback updated isolate count to: $isolateSpeakerCount"); - } - ); - } - }); - } - }); - } - - // Initialize recognizers inside the isolate - static Future?> _initializeRecognizers(Map configs) async { - try { - // Create offline recognizer - final offlineConfig = sherpa_onnx.OfflineRecognizerConfig( - model: configs['offlineModelConfig'] - ); - final offlineRecognizer = sherpa_onnx.OfflineRecognizer(offlineConfig); - - // Create speaker extractor - final speakerConfig = sherpa_onnx.SpeakerEmbeddingExtractorConfig( - model: configs['speakerModel'], - numThreads: 2, - debug: false, - provider: 'cpu', - ); - final speakerExtractor = sherpa_onnx.SpeakerEmbeddingExtractor(config: speakerConfig); - - // Create speaker manager - final speakerManager = sherpa_onnx.SpeakerEmbeddingManager(speakerExtractor.dim); - - return { - 'offlineRecognizer': offlineRecognizer, - 'speakerExtractor': speakerExtractor, - 'speakerManager': speakerManager, - }; - } catch (e) { - debugPrint('Error initializing recognizers in isolate: $e'); - return null; - } - } - - // Process a segment inside the isolate - static Future _processSegment( - ProcessSegmentMessage message, - sherpa_onnx.OfflineRecognizer offlineRecognizer, - sherpa_onnx.SpeakerEmbeddingExtractor speakerExtractor, - sherpa_onnx.SpeakerEmbeddingManager speakerManager, - SendPort sendPort, - int currentSpeakerCount, - Function(int) updateSpeakerCount - ) async { - try { - debugPrint('Isolate: Processing segment ${message.segmentIndex} (${message.samples.length} samples)'); - - if (message.samples.isEmpty) { - sendPort.send(ProcessSegmentResult( - segmentIndex: message.segmentIndex, - text: '', - speakerId: 'Unknown', - success: false, - error: 'Empty samples', - )); - return; - } - - // Perform offline speech recognition - final offlineStream = offlineRecognizer.createStream(); - offlineStream.acceptWaveform( - samples: message.samples, - sampleRate: message.sampleRate - ); - - offlineRecognizer.decode(offlineStream); - final result = offlineRecognizer.getResult(offlineStream); - - debugPrint('Isolate: Recognition result: "${result.text}"'); - - // Skip speaker identification if result is empty - if (result.text.trim().isEmpty) { - sendPort.send(ProcessSegmentResult( - segmentIndex: message.segmentIndex, - text: result.text, - speakerId: 'Unknown', - success: true, - )); - - offlineStream.free(); - return; - } - - // Speaker identification - final speakerStream = speakerExtractor.createStream(); - speakerStream.acceptWaveform( - samples: message.samples, - sampleRate: message.sampleRate, - ); - - speakerStream.inputFinished(); - final embedding = speakerExtractor.compute(speakerStream); - - // Search for matching speaker - final threshold = 0.5; - var speakerId = speakerManager.search(embedding: embedding, threshold: threshold); - - int newSpeakerCount = currentSpeakerCount; - - // If no match, register a new speaker - if (speakerId.isEmpty) { - // Increment speaker count for the new speaker - newSpeakerCount = currentSpeakerCount + 1; - - speakerId = 'Speaker $newSpeakerCount'; - debugPrint('Isolate: New speaker detected: $speakerId (count: $newSpeakerCount)'); - speakerManager.add(name: speakerId, embedding: embedding); - - // Update the callback - updateSpeakerCount(newSpeakerCount); - } else { - debugPrint('Isolate: Matched existing speaker: $speakerId'); - } - - // Send the result back with updated speaker count - sendPort.send(ProcessSegmentResult( - segmentIndex: message.segmentIndex, - text: result.text, - speakerId: speakerId, - embedding: embedding, - success: true, - newSpeakerCount: newSpeakerCount, - )); - - // Clean up - offlineStream.free(); - speakerStream.free(); - } catch (e) { - debugPrint('Isolate: Error processing segment: $e'); - sendPort.send(ProcessSegmentResult( - segmentIndex: message.segmentIndex, - text: '', - speakerId: 'Unknown', - success: false, - error: e.toString(), - )); - } - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/speech_state.dart b/team_b/yappy/lib/services/speech_state.dart deleted file mode 100644 index 992c3c6d..00000000 --- a/team_b/yappy/lib/services/speech_state.dart +++ /dev/null @@ -1,718 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:typed_data'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:record/record.dart'; -import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; -import 'utils.dart'; -import 'online_model.dart'; -import 'offline_model.dart'; -import 'speaker_model.dart'; -import 'speech_isolate.dart'; - -Future createOnlineRecognizer() async { - final type = 0; - - final modelConfig = await getOnlineModelConfig(type: type); - final config = sherpa_onnx.OnlineRecognizerConfig( - model: modelConfig, - ruleFsts: '', - ); - - return sherpa_onnx.OnlineRecognizer(config); -} - -Future createOfflineRecognizer() async { - final type = 0; - - final modelConfig = await getOfflineModelConfig(type: type); - final config = sherpa_onnx.OfflineRecognizerConfig( - model: modelConfig - ); - - return sherpa_onnx.OfflineRecognizer(config); -} - -Future createSpeakerExtractor() async { - final type = 0; - - final model = await getSpeakerModel(type: type); - final config = sherpa_onnx.SpeakerEmbeddingExtractorConfig( - model: model, - numThreads: 2, - debug: false, - provider: 'cpu', - ); - - return sherpa_onnx.SpeakerEmbeddingExtractor(config: config); -} - -class Conversation { - final List segments; - final String audioFilePath; - - Conversation({ - required this.segments, - required this.audioFilePath, - }); - - // Convert to JSON for persistence - Map toJson() => { - 'segments': segments.map((s) => s.toJson()).toList(), - 'audioFilePath': audioFilePath, - }; - - factory Conversation.fromJson(Map json) => Conversation( - segments: (json['segments'] as List) - .map((s) => RecognizedSegment.fromJson(s)) - .toList(), - audioFilePath: json['audioFilePath'], - ); - - // Generate a transcript from the conversation - String getTranscript({bool includeSpeakerTags = true}) { - final buffer = StringBuffer(); - RecognizedSegment? lastSegment; - - for (final segment in segments) { - if (segment.text.isEmpty) continue; - - if (buffer.isNotEmpty) { - // Add a newline if the speaker changes or if this is a new thought - if (lastSegment == null || - lastSegment.speakerId != segment.speakerId) { - buffer.write('\n\n'); - } else { - buffer.write('\n'); - } - } - - // Add speaker tag if requested and available - if (includeSpeakerTags && segment.speakerId != null) { - buffer.write('${segment.speakerId}: '); - } - - buffer.write(segment.text); - lastSegment = segment; - } - - return buffer.toString(); - } -} - -class RecognizedSegment { - final int index; - String text; - String? speakerId; - bool isProcessed; - double start; - double end; - Float32List? speakerEmbedding; - - RecognizedSegment({ - required this.index, - required this.text, - this.speakerId, - this.isProcessed = false, - required this.start, - required this.end, - this.speakerEmbedding, - }); - - // Add a method to convert to/from JSON for persistence - Map toJson() => { - 'index': index, - 'text': text, - 'speakerId': speakerId, - 'isProcessed': isProcessed, - 'start': start, - 'end': end, - }; - - factory RecognizedSegment.fromJson(Map json) => RecognizedSegment( - index: json['index'], - text: json['text'], - speakerId: json['speakerId'], - isProcessed: json['isProcessed'], - start: json['start'], - end: json['end'], - ); -} - -class AudioSegment { - final Float32List samples; - final int sampleRate; - final int index; - final double start; - final double end; - - AudioSegment({ - required this.samples, - required this.sampleRate, - required this.index, - required this.start, - required this.end, - }); -} - -class SpeechState extends ChangeNotifier { - final TextEditingController controller = TextEditingController(); - final AudioRecorder audioRecorder = AudioRecorder(); - - ValueNotifier> audioSamplesNotifier = ValueNotifier>([]); - - RecordState recordState = RecordState.stop; - bool isInitialized = false; - int currentIndex = 0; - double currentTimestamp = 0.0; - int currentSpeakerCount = 0; - - void updateAudioSamples(List newSamples) { - audioSamplesNotifier.value = newSamples; - } - // Store all recognized segments - final List recognizedSegments = []; - - // First pass - streaming recognition - sherpa_onnx.OnlineRecognizer? onlineRecognizer; - sherpa_onnx.OnlineStream? onlineStream; - - // Second pass - offline processing - SpeechProcessingIsolate? speechIsolate; - - List allAudioSamples = []; - // Buffer for collecting samples between endpoints - List currentSegmentSamples = []; - final int sampleRate = 16000; - - // Store segments that need offline processing - List pendingSegments = []; - bool isProcessingOffline = false; - - // Path to save the complete audio recording - String? recordingFilePath; - - // Create a Conversation object when recording is stopped - Conversation? lastConversation; - - Future initialize() async { - if (!isInitialized) { - try { - // init online recognizer - sherpa_onnx.initBindings(); - onlineRecognizer = await createOnlineRecognizer(); - onlineStream = onlineRecognizer?.createStream(); - - // Initialize the isolate with configuration - speechIsolate = SpeechProcessingIsolate(); - final offlineModelConfig = await getOfflineModelConfig(type: 0); - final speakerModel = await getSpeakerModel(type: 0); - - await speechIsolate?.initialize({ - 'offlineModelConfig': offlineModelConfig, - 'speakerModel': speakerModel, - }); - - // Set up listener for results from the isolate - speechIsolate?.results.listen((result) { - debugPrint("Received result from isolate: ${result.segmentIndex}, Speaker: ${result.speakerId}"); - - // Update speaker count if a new speaker was detected - if (result.newSpeakerCount != null && result.newSpeakerCount! > currentSpeakerCount) { - currentSpeakerCount = result.newSpeakerCount!; - debugPrint('Updated main thread speaker count to: $currentSpeakerCount'); - } - - // Ignore empty results - if (result.success && result.text.trim().isNotEmpty) { - // Make sure speakerId is not null or empty - String speakerId = result.speakerId; - if (speakerId.isEmpty) { - speakerId = 'Speaker Unknown'; - } - - _updateRecognizedSegment( - result.segmentIndex, - result.text, - speakerId: speakerId, - embedding: result.embedding, - ); - _updateDisplayText(); - } - }); - - isInitialized = true; - notifyListeners(); - } catch (e) { - debugPrint('Sherpa initialization failed: $e'); - } - } - } - - // Helper method to update the displayed text - void _updateDisplayText() { - final buffer = StringBuffer(); - - // Debug log - // debugPrint('Updating display text with ${recognizedSegments.length} segments'); - - for (final segment in recognizedSegments) { - // Debug log - // debugPrint('Segment ${segment.index}: "${segment.text}" (Speaker: ${segment.speakerId ?? "Unknown"})'); - - if (segment.text.isNotEmpty) { - if (buffer.isNotEmpty) { - buffer.write('\n'); - } - // Make sure we have a speaker ID display string - final prefix = (segment.speakerId != null && segment.speakerId!.isNotEmpty) - ? segment.speakerId! - : 'Speaker Unknown'; - buffer.write('$prefix: ${segment.text}'); - } - } - - // final displayText = buffer.toString(); - // debugPrint('Setting display text: $displayText'); - - controller.value = TextEditingValue( - text: buffer.toString(), - selection: TextSelection.collapsed(offset: buffer.length), - ); - - notifyListeners(); // Make sure UI gets updated - } - - // Add a new segment of recognized text - void _addRecognizedSegment(String text, double start) { - recognizedSegments.add(RecognizedSegment( - index: currentIndex, - text: text, - start: start, - end: start, // Will be updated when segment ends - )); - - debugPrint('Added new segment $currentIndex: "$text" (${start.toStringAsFixed(2)}s - ${start.toStringAsFixed(2)}s)'); - } - - // Update an existing segment with improved recognition - void _updateRecognizedSegment(int index, String newText, {String? speakerId, Float32List? embedding}) { - final segmentIndex = recognizedSegments.indexWhere((s) => s.index == index); - if (segmentIndex != -1) { - if (newText.trim().isNotEmpty) { - recognizedSegments[segmentIndex].text = newText; - } - recognizedSegments[segmentIndex].isProcessed = true; - - // Make sure speakerId is not null or empty - if (speakerId != null && speakerId.isNotEmpty) { - recognizedSegments[segmentIndex].speakerId = speakerId; - debugPrint('Updated segment $index with speaker: $speakerId'); - } - - if (embedding != null) { - recognizedSegments[segmentIndex].speakerEmbedding = embedding; - } - - // _updateDisplayText(); - } - } - - // Replace the processSegmentOffline method with this version -Future processSegmentOffline(AudioSegment segment) async { - debugPrint('Processing segment ${segment.index} offline (${segment.samples.length} samples)'); - - if (segment.samples.isEmpty) { - debugPrint('Empty samples for segment ${segment.index}, skipping'); - return; - } - - try { - if (speechIsolate == null) { - debugPrint('Speech isolate not initialized, failing silently'); - return; - } - - // Debug current speaker count - debugPrint('Sending segment with current speaker count: $currentSpeakerCount'); - - // Use the isolate to process this segment - await speechIsolate!.processSegment(ProcessSegmentMessage( - samples: segment.samples, - sampleRate: sampleRate, - segmentIndex: segment.index, - recognizerConfigs: { - 'currentSpeakerCount': currentSpeakerCount, - }, - )); - - // Processing will continue asynchronously, and results will be handled by the listener - - } catch (e) { - debugPrint('Error processing segment ${segment.index} offline: $e'); - } -} - - Future processPendingSegments() async { - if (pendingSegments.isEmpty || isProcessingOffline) { - debugPrint('No pending segments to process or already processing'); - return; - } - - debugPrint('Processing ${pendingSegments.length} pending segments'); - isProcessingOffline = true; - - try { - // Create a local copy to process to avoid modification during iteration - final segmentsToProcess = List.from(pendingSegments); - pendingSegments.clear(); - - for (final segment in segmentsToProcess) { - debugPrint('Processing pending segment ${segment.index}'); - await processSegmentOffline(segment); - // Update display after each segment is processed - _updateDisplayText(); - } - } catch (e) { - debugPrint('Error processing pending segments: $e'); - } finally { - isProcessingOffline = false; - debugPrint('Finished processing pending segments'); - } - } - - Future toggleRecording() async { - if (recordState == RecordState.stop) { - controller.value = TextEditingValue( - text: "Initializing Yappy!, just a moment..." - ); - await startRecording(); - } else { - await stopRecording(); - } - } - - Future _createRecordingFilePath() async { - // final dir = await getApplicationDocumentsDirectory(); - final timestamp = DateTime.now().millisecondsSinceEpoch; - // return '${dir.path}/recording_$timestamp.wav'; - return '/storage/emulated/0/Documents/recording_$timestamp.wav'; - } - - Future startRecording() async { - if (!isInitialized) { - await initialize(); - } - - try { - if (await audioRecorder.hasPermission()) { - // Reset speakers for new recording - currentSpeakerCount = 0; - recognizedSegments.clear(); - - // Create a path for saving the recording - recordingFilePath = await _createRecordingFilePath(); - - const config = RecordConfig( - encoder: AudioEncoder.pcm16bits, - sampleRate: 16000, - numChannels: 1, - ); - - final recordStream = await audioRecorder.startStream(config); - currentSegmentSamples.clear(); - allAudioSamples.clear(); - currentTimestamp = 0.0; - currentIndex = 0; - - recordState = RecordState.record; - controller.value = TextEditingValue( - text: "Listening..." - ); - notifyListeners(); - - recordStream.listen( - (data) { - final samplesFloat32 = convertBytesToFloat32(Uint8List.fromList(data)); - - // Add samples to current segment buffer - currentSegmentSamples.add(samplesFloat32); - allAudioSamples.add(samplesFloat32); - - // Update current timestamp based on number of samples - currentTimestamp += samplesFloat32.length / sampleRate; - - // ALYS CODE TO HELP UPDATE THE AUDIOWAVE SAMPLES - audioSamplesNotifier.value = samplesFloat32 - .map((e) => (e * 100000).toInt()) - .toList(); - - onlineStream!.acceptWaveform( - samples: samplesFloat32, - sampleRate: sampleRate - ); - - while (onlineRecognizer!.isReady(onlineStream!)) { - onlineRecognizer!.decode(onlineStream!); - } - - final text = onlineRecognizer!.getResult(onlineStream!).text; - - if (text.isNotEmpty) { - // Update or add the current segment - final existingSegmentIndex = recognizedSegments.indexWhere((s) => s.index == currentIndex); - - if (existingSegmentIndex != -1) { - // Update existing segment - recognizedSegments[existingSegmentIndex].text = text; - // debugPrint('Updated segment $currentIndex with text: "$text"'); - } else { - // Add new segment - debugPrint('Adding new segment $currentIndex with text: "$text"'); - _addRecognizedSegment(text, currentTimestamp); - } - - // Always update display when we have new text - _updateDisplayText(); - } - - if (onlineRecognizer!.isEndpoint(onlineStream!)) { - // Store the current segment for offline processing - - //ISSUE IS HERE, need to use recognizedSegments.LastOrNull like before, or integrate VAD - if (currentSegmentSamples.isNotEmpty && recognizedSegments.lastOrNull != null - ) { - // Combine all Float32Lists into a single one - final combinedSamples = Float32List(currentSegmentSamples.fold( - 0, (sum, list) => sum + list.length)); - var offset = 0; - for (var samples in currentSegmentSamples) { - combinedSamples.setRange(offset, offset + samples.length, samples); - offset += samples.length; - } - - final segmentStart = recognizedSegments.lastOrNull?.start ?? 0.0; - - pendingSegments.add(AudioSegment( - samples: combinedSamples, - sampleRate: sampleRate, - index: currentIndex, - start: segmentStart, - end: currentTimestamp, - )); - - // Process with online recognizer in the background - processPendingSegments(); - } - - // Reset for next segment - onlineRecognizer!.reset(onlineStream!); - currentSegmentSamples.clear(); - currentIndex += 1; - } - }, - onError: (error) { - debugPrint('Error from audio stream: $error'); - }, - onDone: () { - debugPrint('Audio stream done'); - }, - ); - } - } catch (e) { - debugPrint('Error starting recording: $e'); - } - } - - Future saveWavFile() async { - if (allAudioSamples.isEmpty || recordingFilePath == null) return; - - try { - // Combine all audio samples - final totalSamples = allAudioSamples.fold(0, (sum, list) => sum + list.length); - final combinedSamples = Float32List(totalSamples); - - var offset = 0; - for (var samples in allAudioSamples) { - combinedSamples.setRange(offset, offset + samples.length, samples); - offset += samples.length; - } - - // Convert Float32List to Int16List for WAV format - final int16Samples = Int16List(combinedSamples.length); - for (var i = 0; i < combinedSamples.length; i++) { - // Scale and clamp to Int16 range - final scaledSample = combinedSamples[i] * 32767; - int16Samples[i] = scaledSample.clamp(-32768, 32767).toInt(); - } - - // Create WAV file - final file = File(recordingFilePath!); - final sink = file.openWrite(); - - // WAV header (44 bytes) - final header = ByteData(44); - - // RIFF chunk descriptor - header.setUint8(0, 0x52); // 'R' - header.setUint8(1, 0x49); // 'I' - header.setUint8(2, 0x46); // 'F' - header.setUint8(3, 0x46); // 'F' - - // Chunk size (file size - 8) - final dataSize = int16Samples.length * 2; // 2 bytes per sample - final fileSize = 36 + dataSize; - header.setUint32(4, fileSize, Endian.little); - - // Format ('WAVE') - header.setUint8(8, 0x57); // 'W' - header.setUint8(9, 0x41); // 'A' - header.setUint8(10, 0x56); // 'V' - header.setUint8(11, 0x45); // 'E' - - // 'fmt ' subchunk - header.setUint8(12, 0x66); // 'f' - header.setUint8(13, 0x6D); // 'm' - header.setUint8(14, 0x74); // 't' - header.setUint8(15, 0x20); // ' ' - - // Subchunk1 size (16 for PCM) - header.setUint32(16, 16, Endian.little); - - // Audio format (1 for PCM) - header.setUint16(20, 1, Endian.little); - - // Number of channels (1 for mono) - header.setUint16(22, 1, Endian.little); - - // Sample rate - header.setUint32(24, sampleRate, Endian.little); - - // Byte rate (SampleRate * NumChannels * BitsPerSample/8) - header.setUint32(28, sampleRate * 1 * 16 ~/ 8, Endian.little); - - // Block align (NumChannels * BitsPerSample/8) - header.setUint16(32, 1 * 16 ~/ 8, Endian.little); - - // Bits per sample - header.setUint16(34, 16, Endian.little); - - // 'data' subchunk - header.setUint8(36, 0x64); // 'd' - header.setUint8(37, 0x61); // 'a' - header.setUint8(38, 0x74); // 't' - header.setUint8(39, 0x61); // 'a' - - // Subchunk2 size (data size) - header.setUint32(40, dataSize, Endian.little); - - // Write header - sink.add(header.buffer.asUint8List()); - - // Write data - final dataBytes = int16Samples.buffer.asUint8List(); - sink.add(dataBytes); - - await sink.close(); - - debugPrint('WAV file saved to: $recordingFilePath'); - } catch (e) { - debugPrint('Error saving WAV file: $e'); - } - } - - Future createConversation() async { - // Ensure WAV file is saved - await saveWavFile(); - - // Create conversation object - return Conversation( - segments: List.from(recognizedSegments), // Make a copy - audioFilePath: recordingFilePath ?? '', - ); - } - - Future stopRecording() async { - debugPrint('Stopping recording'); - - try { - // Update UI immediately to show we're stopping - recordState = RecordState.stop; - notifyListeners(); - - // Process any remaining audio - if (currentSegmentSamples.isNotEmpty) { - debugPrint('Processing final segment $currentIndex'); - - // Combine all Float32Lists into a single one - final combinedSamples = Float32List(currentSegmentSamples.fold( - 0, (sum, list) => sum + list.length)); - var offset = 0; - for (var samples in currentSegmentSamples) { - combinedSamples.setRange(offset, offset + samples.length, samples); - offset += samples.length; - } - - final segmentStart = recognizedSegments.lastOrNull?.start ?? 0.0; - - pendingSegments.add(AudioSegment( - samples: combinedSamples, - sampleRate: sampleRate, - index: currentIndex, - start: segmentStart, - end: currentTimestamp, - )); - } - - // Clean up resources - if (onlineStream != null) { - onlineStream!.free(); - onlineStream = onlineRecognizer?.createStream(); - } - - await audioRecorder.stop(); - - // Process final segments - debugPrint('Processing final segments with offline recognizer'); - await processPendingSegments(); - - // Save the recording as a WAV file - debugPrint('Saving WAV file'); - await saveWavFile(); - - // Create conversation object - debugPrint('Creating conversation object'); - lastConversation = await createConversation(); - - currentSegmentSamples.clear(); - // allAudioSamples.clear(); - // Final update to display text - _updateDisplayText(); - - debugPrint('Recording stopped successfully'); - } catch (e) { - debugPrint('Error stopping recording: $e'); - } finally { - notifyListeners(); - } - } - - @override - void dispose() { - controller.dispose(); - audioRecorder.dispose(); - onlineStream?.free(); - onlineRecognizer?.free(); - speechIsolate?.dispose(); - super.dispose(); - } - - getRecordedText() { - if (lastConversation != null) { - return lastConversation!.getTranscript(); - } else { - return "No recording available."; - } - } -} diff --git a/team_b/yappy/lib/services/toast_service.dart b/team_b/yappy/lib/services/toast_service.dart deleted file mode 100644 index 489e52e7..00000000 --- a/team_b/yappy/lib/services/toast_service.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'dart:async'; - -/// A service that manages toast notifications through stream controllers -class ToastService { - // Singleton pattern - static final ToastService _instance = ToastService._internal(); - factory ToastService() => _instance; - ToastService._internal(); - - // Stream controllers - final _messageController = StreamController.broadcast(); - final _progressController = StreamController.broadcast(); - final _visibilityController = StreamController.broadcast(); - final _successController = StreamController.broadcast(); - final _errorController = StreamController.broadcast(); - - // Track toast visibility - bool _isToastVisible = false; - - // Stream getters - Stream get messageStream => _messageController.stream; - Stream get progressStream => _progressController.stream; - Stream get visibilityStream => _visibilityController.stream; - Stream get successStream => _successController.stream; - Stream get errorStream => _errorController.stream; - - // Check if toast is visible (i.e., download in progress) - bool get isToastVisible => _isToastVisible; - - // Methods to control the toast - void showToast(String message, {double progress = 0.0}) { - _messageController.add(message); - _progressController.add(progress); - _visibilityController.add(true); - _isToastVisible = true; - } - - void updateProgress(double progress) { - _progressController.add(progress); - } - - void updateMessage(String message) { - _messageController.add(message); - } - - void hideToast() { - _visibilityController.add(false); - _isToastVisible = false; - } - - void showSuccess(String message) { - _successController.add(message); - } - - void showError(String message) { - _errorController.add(message); - } - - // Clean up resources - void dispose() { - _messageController.close(); - _progressController.close(); - _visibilityController.close(); - _successController.close(); - _errorController.close(); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/services/utils.dart b/team_b/yappy/lib/services/utils.dart deleted file mode 100644 index 12a044c8..00000000 --- a/team_b/yappy/lib/services/utils.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2024 Xiaomi Corporation -import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:flutter/services.dart' show rootBundle; -import 'dart:typed_data'; -import "dart:io"; - -// Copy the asset file from src to dst -Future copyAssetFile(String src, [String? dst]) async { - final Directory directory = await getApplicationCacheDirectory(); - dst ??= basename(src); - final target = join(directory.path, dst); - bool exists = await File(target).exists(); - - final data = await rootBundle.load(src); - - if (!exists || File(target).lengthSync() != data.lengthInBytes) { - final List bytes = - data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - await File(target).writeAsBytes(bytes); - } - - return target; -} - -Float32List convertBytesToFloat32(Uint8List bytes, [endian = Endian.little]) { - final values = Float32List(bytes.length ~/ 2); - - final data = ByteData.view(bytes.buffer); - - for (var i = 0; i < bytes.length; i += 2) { - int short = data.getInt16(i, endian); - values[i ~/ 2] = short / 32678.0; - } - - return values; -} diff --git a/team_b/yappy/lib/settings_page.dart b/team_b/yappy/lib/settings_page.dart deleted file mode 100644 index 54835e6b..00000000 --- a/team_b/yappy/lib/settings_page.dart +++ /dev/null @@ -1,253 +0,0 @@ -import 'package:dart_openai/dart_openai.dart'; -import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import './services/model_manager.dart'; -import 'package:yappy/main.dart'; - -class SettingsPage extends StatefulWidget { - const SettingsPage({super.key}); - - @override - State createState() => _SettingsPageState(); -} - -class _SettingsPageState extends State { - bool _modelsDownloaded = false; - bool _wifiOnlyDownloads = true; - bool _isLoading = true; - final ModelManager _modelManager = ModelManager(); - - @override - void initState() { - super.initState(); - _loadSettings(); - } - - Future _loadSettings() async { - try { - // Check models status - final exist = await _modelManager.modelsExist(); - - // Load Wi-Fi only setting - final prefs = await SharedPreferences.getInstance(); - final wifiOnly = prefs.getBool('wifi_only_downloads') ?? true; - - if (mounted) { - setState(() { - _modelsDownloaded = exist; - _wifiOnlyDownloads = wifiOnly; - _isLoading = false; - }); - } - } catch (e) { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('Settings'), - ), - body: _isLoading - ? const Center(child: CircularProgressIndicator()) - : ListView( - children: [ - // Original settings items - ListTile( - leading: const Icon(Icons.account_circle), - title: const Text('Account'), - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Version'), - content: const Text('Version 1.0.0'), - actions: [ - TextButton( - child: const Text('OK'), - onPressed: () { - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - ], - ); - }, - ); - }, - ), - ListTile( - leading: const Icon(Icons.key), - title: const Text('API Keys'), - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - TextEditingController apiKeyController = TextEditingController(); - return AlertDialog( - title: const Text('Enter API Key'), - content: TextField( - controller: apiKeyController, - decoration: const InputDecoration(hintText: "API Key"), - ), - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: const Text('Save'), - onPressed: () async { - // Save the API key - String apiKey = apiKeyController.text; - await preferences.setString('openai_api_key', apiKey); - OpenAI.apiKey = apiKey; - if (!context.mounted) return; - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - }, - ), - - // Divider to separate original and new settings - const Divider(), - - // New model management settings - const Padding( - padding: EdgeInsets.fromLTRB(16, 16, 16, 8), - child: Text( - 'AI Speech Models', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.grey, - ), - ), - ), - - ListTile( - leading: const Icon(Icons.cloud_download), - title: const Text('Speech Recognition Models'), - subtitle: Text(_modelsDownloaded - ? 'Downloaded and ready to use' - : 'Not downloaded'), - trailing: _modelsDownloaded - ? const Icon(Icons.check_circle, color: Colors.green) - : ElevatedButton( - onPressed: () => _handleModelDownload(context), - child: const Text('Download'), - ), - ), - - SwitchListTile( - secondary: const Icon(Icons.wifi), - title: const Text('Download on Wi-Fi only'), - subtitle: const Text( - 'When enabled, models will only download when connected to Wi-Fi'), - value: _wifiOnlyDownloads, - onChanged: (value) async { - setState(() { - _wifiOnlyDownloads = value; - }); - // Save preference to shared preferences - await _modelManager.saveWifiOnlySetting(value); - }, - ), - - if (_modelsDownloaded) - ListTile( - leading: const Icon(Icons.delete_outline), - title: const Text('Delete Models'), - subtitle: const Text('Free up space by removing downloaded models'), - onTap: () => _handleDeleteModels(context), - ), - ], - ), - ); - } - - Future _handleModelDownload(BuildContext context) async { - await _modelManager.downloadModelsFromSettings(context); - - if (!mounted) return; - - // Refresh the model status - final exist = await _modelManager.modelsExist(); - - if (!mounted) return; - - setState(() { - _modelsDownloaded = exist; - }); - } - - Future _handleDeleteModels(BuildContext context) async { - final shouldDelete = await showDialog( - context: context, - builder: (dialogContext) => AlertDialog( - title: const Text('Delete Models?'), - content: const Text( - 'This will delete all downloaded speech models. ' - 'You will need to download them again to use the app\'s ' - 'speech recognition features.' - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(dialogContext).pop(false), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () => Navigator.of(dialogContext).pop(true), - child: const Text('Delete'), - ), - ], - ), - ) ?? false; - - if (!shouldDelete || !mounted) return; - - final success = await _modelManager.deleteModels(); - - if (!mounted) return; - - setState(() { - _modelsDownloaded = !success; - }); - - _showResultSnackBar(success); - } - - // Separate method for showing the snackbar to avoid context across async gap - void _showResultSnackBar(bool success) { - if (success) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Models deleted successfully'), - duration: Duration(seconds: 2), - ), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Failed to delete models'), - backgroundColor: Colors.red, - duration: Duration(seconds: 2), - ), - ); - } - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/sign_up_page.dart b/team_b/yappy/lib/sign_up_page.dart deleted file mode 100644 index 90e6369a..00000000 --- a/team_b/yappy/lib/sign_up_page.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:flutter/material.dart'; - -class SignUpPage extends StatefulWidget { - const SignUpPage({super.key}); - - @override - SignUpPageState createState() => SignUpPageState(); -} - -class SignUpPageState extends State { - final TextEditingController _usernameController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - final TextEditingController _reenterPasswordController = TextEditingController(); - - @override - void dispose() { - // Dispose controllers to prevent memory leaks - _usernameController.dispose(); - _passwordController.dispose(); - _reenterPasswordController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - body: Center( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircleAvatar( - backgroundColor: Colors.white, - radius: 30, - child: Icon(Icons.chat, color: Colors.green, size: 40), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 80), - ), - child: const Text( - 'Sign-Up', - style: TextStyle(color: Colors.white, fontSize: 18), - ), - ), - const SizedBox(height: 20), - TextField( - controller: _usernameController, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - filled: true, - fillColor: Colors.grey[900], - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), - labelText: 'Username', - labelStyle: const TextStyle(color: Colors.white), - ), - ), - const SizedBox(height: 10), - TextField( - controller: _passwordController, - obscureText: true, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - filled: true, - fillColor: Colors.grey[900], - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), - labelText: 'Password', - labelStyle: const TextStyle(color: Colors.white), - ), - ), - const SizedBox(height: 10), - TextField( - controller: _reenterPasswordController, - obscureText: true, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - filled: true, - fillColor: Colors.grey[900], - border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), - labelText: 'Re-Enter Password', - labelStyle: const TextStyle(color: Colors.white), - ), - ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.black, - padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 40), - ), - child: const Text( - 'Submit', - style: TextStyle(color: Colors.white, fontSize: 16), - ), - ), - const SizedBox(height: 30), - const Text( - 'Yappy! Is not responsible for any legal consequences due to the use of this application', - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white60, fontSize: 12), - ), - ], - ), - ), - ), - ); - } -} diff --git a/team_b/yappy/lib/toast_widget.dart b/team_b/yappy/lib/toast_widget.dart deleted file mode 100644 index 574b07ae..00000000 --- a/team_b/yappy/lib/toast_widget.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter/material.dart'; -import 'services/toast_service.dart'; - -/// Widget that displays persistent toast notifications across all screens -class ToastWidget extends StatefulWidget { - final Widget child; - - const ToastWidget({super.key, required this.child}); - - @override - State createState() => _ToastWidgetState(); -} - -class _ToastWidgetState extends State { - final _toastService = ToastService(); - bool _visible = false; - String _message = ''; - double _progress = 0.0; - - @override - void initState() { - super.initState(); - - // Listen to service streams - _toastService.messageStream.listen((message) { - if (mounted) { - setState(() => _message = message); - } - }); - - _toastService.progressStream.listen((progress) { - if (mounted) { - setState(() => _progress = progress); - } - }); - - _toastService.visibilityStream.listen((visible) { - if (mounted) { - setState(() => _visible = visible); - } - }); - - _toastService.successStream.listen(_showSuccessSnackBar); - _toastService.errorStream.listen(_showErrorSnackBar); - } - - void _showSuccessSnackBar(String message) { - // Use ScaffoldMessenger to show SnackBar globally - final messenger = ScaffoldMessenger.of(context); - - messenger.clearSnackBars(); - messenger.showSnackBar( - SnackBar( - content: Text(message), - backgroundColor: Colors.green, - duration: const Duration(seconds: 3), - behavior: SnackBarBehavior.floating, - ), - ); - } - - void _showErrorSnackBar(String message) { - // Use ScaffoldMessenger to show SnackBar globally - final messenger = ScaffoldMessenger.of(context); - - messenger.clearSnackBars(); - messenger.showSnackBar( - SnackBar( - content: Text(message), - backgroundColor: Colors.red, - duration: const Duration(seconds: 5), - behavior: SnackBarBehavior.floating, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Material( - // Ensure Material is available for elevation and visual elements - type: MaterialType.transparency, - child: Stack( - children: [ - // Main content - widget.child, - - // Toast notification - AnimatedPositioned( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - bottom: _visible ? 32.0 : -100.0, - left: 16.0, - right: 16.0, - child: SafeArea( - child: Material( - elevation: 4.0, - borderRadius: BorderRadius.circular(8.0), - color: Colors.black87, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 12.0, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const SizedBox( - height: 24, - width: 24, - child: CircularProgressIndicator( - strokeWidth: 2.0, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ), - const SizedBox(width: 12.0), - Expanded( - child: Text( - _message, - style: const TextStyle( - color: Colors.white, - fontSize: 14.0, - ), - ), - ), - ], - ), - const SizedBox(height: 8.0), - LinearProgressIndicator( - value: _progress, - backgroundColor: Colors.white24, - valueColor: const AlwaysStoppedAnimation(Colors.white), - ), - ], - ), - ), - ), - ), - ), - ], - ), - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/tool_bar.dart b/team_b/yappy/lib/tool_bar.dart deleted file mode 100644 index 63ceb8b1..00000000 --- a/team_b/yappy/lib/tool_bar.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/home_page.dart'; -import 'package:yappy/restaurant.dart'; -import 'package:yappy/contact_page.dart'; -import 'package:yappy/help.dart'; -import 'package:yappy/medical_patient.dart'; -import 'package:yappy/medical_doctor.dart'; -import 'package:yappy/mechanic.dart'; -import 'package:yappy/settings_page.dart'; - -// Defines a reusable Hamburger Menu Widget (AppBar + Drawer) -class ToolBar extends StatelessWidget { - final bool showHamburger; - - const ToolBar({super.key, this.showHamburger = true}); - - @override - Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - double screenHeight = MediaQuery.of(context).size.height; - - return AppBar( - // Creates the hamburger icon for the menu - backgroundColor: Colors.black, - leading: showHamburger - ? Builder( - builder: (context) { - return IconButton( - icon: const Icon(Icons.menu, color: Colors.white), - onPressed: () { - Scaffold.of(context).openDrawer(); - }, - ); - }, - ): SizedBox(width: screenHeight * 0.08), - toolbarHeight: screenHeight * 0.11, - // Contains the Yappy! icon - title: Center( - child: CircleAvatar( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - radius: screenWidth * 0.2, - child: Image.asset( - 'assets/icon/app_icon.png', - width: screenWidth * 0.22, - height: screenWidth * 0.22, - ), - ), - ), - actions: [ - // Contains the information button - IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - // Creates a pop up when the button is pressed - return AlertDialog( - title: const Text('Information'), - content: const Text('Yappy Terms & Conditions\n\n''By using Yappy,' - 'you agree to Use the app responsibly and comply ' - 'with all applicable laws. Respect user privacy ' - 'and refrain from harmful or abusive behavior.\n\n' - 'Understand that Yappy is not liable for ' - 'any misuse or legal consequences arising from its use. ' - 'We may update these terms as needed.\n\n' - 'Continued use of Yappy means acceptance of any changes..'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - }, - ), - ], - ); - } -} - // creates the hamburger menu -class HamburgerDrawer extends StatelessWidget { - const HamburgerDrawer({super.key}); - - @override - Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return SafeArea( - child: Drawer( - width: screenWidth * .45, - backgroundColor: const Color.fromARGB(255, 54, 54, 54), - child: ListView( - padding: EdgeInsets.zero, - children: [ - _buildDrawerItem('Home', context, HomePage()), - _buildDrawerItem('Restaurant', context, RestaurantPage()), - _buildDrawerItem('Vehicle Maintenance', context, MechanicalAidPage()), - _buildDrawerItem('Medical Doctor', context, MedicalDoctorPage()), - _buildDrawerItem('Medical Patient', context, MedicalPatientPage()), - _buildDrawerItem('Help', context, HelpPage()), - _buildDrawerItem('Contact', context, ContactPage()), - _buildDrawerItem('Settings', context, SettingsPage()), - ], - ), - ), - ); - } - - // Creates the individual drawer items for the hamburger menu - Widget _buildDrawerItem(String title, BuildContext context, Widget page) { - return ListTile( - contentPadding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - textColor: Colors.white, - tileColor: const Color.fromARGB(255, 54, 54, 54), - title: Text(title), - onTap: () { - Navigator.push( - context, - // Navigates to the page once the button is clicked - MaterialPageRoute(builder: (context) => page), - ); - }, - ); - } -} \ No newline at end of file diff --git a/team_b/yappy/lib/transcription_box.dart b/team_b/yappy/lib/transcription_box.dart deleted file mode 100644 index 8076f375..00000000 --- a/team_b/yappy/lib/transcription_box.dart +++ /dev/null @@ -1,78 +0,0 @@ -import 'package:flutter/material.dart'; - -class TranscriptionBox extends StatefulWidget { - final TextEditingController controller; - - const TranscriptionBox({ - required this.controller, - super.key, - }); - - @override - TranscriptionBoxState createState() => TranscriptionBoxState(); -} - -class TranscriptionBoxState extends State { - final ScrollController _scrollController = ScrollController(); - - @override - void initState() { - super.initState(); - widget.controller.addListener(_scrollToBottom); - } - - @override - void dispose() { - widget.controller.removeListener(_scrollToBottom); - _scrollController.dispose(); - super.dispose(); - } - - void _scrollToBottom() { - WidgetsBinding.instance.addPostFrameCallback((_) { - _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: Duration(milliseconds: 300), - curve: Curves.easeOut, - ); - }); - } - - @override - Widget build(BuildContext context) { - double screenHeight = MediaQuery.of(context).size.height; - - return SizedBox( - height: screenHeight * 0.4, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8.0), - color: const Color.fromARGB(255, 67, 67, 67), - ), - child: Scrollbar( - controller: _scrollController, - child: SingleChildScrollView( - controller: _scrollController, - scrollDirection: Axis.vertical, - child: TextField( - controller: widget.controller, - maxLines: null, - readOnly: true, - decoration: InputDecoration( - hintText: "Transcription will appear here...", - hintStyle: TextStyle(color: Colors.white), - border: InputBorder.none, - contentPadding: EdgeInsets.all(10), - ), - style: TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - ), - ), - ), - ); - } -} - diff --git a/team_b/yappy/lib/tutorial_page.dart b/team_b/yappy/lib/tutorial_page.dart deleted file mode 100644 index 573204a1..00000000 --- a/team_b/yappy/lib/tutorial_page.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:yappy/audiowave_widget.dart'; -import 'package:yappy/home_page.dart'; -import 'package:yappy/services/speech_state.dart'; -import 'package:yappy/tool_bar.dart'; -import 'package:yappy/industry_menu.dart'; -import 'package:yappy/transcription_box.dart'; -import 'services/model_manager.dart'; - - -class MedicalPatientApp extends StatelessWidget { - const MedicalPatientApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - home: TutorialPage(), - ); - } -} -//Creates a page for the Medical Patient industry -//The page will contain the industry menu and the transcription box -class TutorialPage extends StatelessWidget { - TutorialPage({super.key}); - final speechState = SpeechState(); - final modelManager = ModelManager(); - - @override - Widget build(BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - _showTutorialPopup(context); - }); - - return Scaffold( - backgroundColor: const Color.fromARGB(255, 0, 0, 0), - appBar: PreferredSize( - preferredSize: Size.fromHeight(140), - child: ToolBar() - ), - drawer: HamburgerDrawer(), - body: ListenableBuilder( - listenable: speechState, - builder: (context, child) { - return Column( - children: [ - IndustryMenu( - title: "Tutorial", - icon: Icons.local_pharmacy, - speechState: speechState, - modelManager: modelManager, - ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column(children: [ - AudiowaveWidget(speechState: speechState), - TranscriptionBox( - controller: speechState.controller, - ), - ],) - - ), - ), - ], - ); - } - ), - ); - } - - void _showTutorialPopup(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("The button of the left is the Record button that allows you to record conversations and get a transcript in return."), - ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - _showSecondPopup(context); - }, - child: Text("Next"), - ), - ], - ), - ); - }, - ); - } - - void _showSecondPopup(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("The second button will show you the days transcripts with broken down into details."), - ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - _showThirdPopup(context); - }, - child: Text("Next"), - ), - ], - ), - ); - }, - ); - } - - void _showThirdPopup(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("The third button will show you all transcripts and allow you to search, share, upload, download, and delete."), - ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - _showFourthPopup(context); - }, - child: Text("Next"), - ), - ], - ), - ); - }, - ); - } - - void _showFourthPopup(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("The fourth button will bring you to a chatbot that can search your transcripts to provide you information."), - ElevatedButton( - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pushReplacement( - - MaterialPageRoute(builder: (context) => HomePage()) - ); - }, - child: Text("Finish"), - ), - ], - ), - ); - }, - ); - } -} diff --git a/team_b/yappy/linux/.gitignore b/team_b/yappy/linux/.gitignore deleted file mode 100644 index 24ce4374..00000000 --- a/team_b/yappy/linux/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -flutter/ephemeral -flutter/generated* -**/flutter/generated* \ No newline at end of file diff --git a/team_b/yappy/linux/CMakeLists.txt b/team_b/yappy/linux/CMakeLists.txt deleted file mode 100644 index 9cddf947..00000000 --- a/team_b/yappy/linux/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "yappy") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.yappy") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/team_b/yappy/linux/flutter/CMakeLists.txt b/team_b/yappy/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd0164..00000000 --- a/team_b/yappy/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/team_b/yappy/linux/runner/CMakeLists.txt b/team_b/yappy/linux/runner/CMakeLists.txt deleted file mode 100644 index e97dabc7..00000000 --- a/team_b/yappy/linux/runner/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the application ID. -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/team_b/yappy/linux/runner/main.cc b/team_b/yappy/linux/runner/main.cc deleted file mode 100644 index e7c5c543..00000000 --- a/team_b/yappy/linux/runner/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/team_b/yappy/linux/runner/my_application.cc b/team_b/yappy/linux/runner/my_application.cc deleted file mode 100644 index ee211132..00000000 --- a/team_b/yappy/linux/runner/my_application.cc +++ /dev/null @@ -1,130 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "yappy"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "yappy"); - } - - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its - // corresponding .desktop file. This ensures better integration by allowing - // the application to be recognized beyond its binary name. - g_set_prgname(APPLICATION_ID); - - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, - "flags", G_APPLICATION_NON_UNIQUE, - nullptr)); -} diff --git a/team_b/yappy/linux/runner/my_application.h b/team_b/yappy/linux/runner/my_application.h deleted file mode 100644 index 72271d5e..00000000 --- a/team_b/yappy/linux/runner/my_application.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/team_b/yappy/macos/.gitignore b/team_b/yappy/macos/.gitignore deleted file mode 100644 index 55610ecf..00000000 --- a/team_b/yappy/macos/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ -**/Flutter/GeneratedPluginRegistrant.* -Flutter/Generated* - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/team_b/yappy/macos/Flutter/Flutter-Debug.xcconfig b/team_b/yappy/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index c2efd0b6..00000000 --- a/team_b/yappy/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/team_b/yappy/macos/Flutter/Flutter-Release.xcconfig b/team_b/yappy/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index c2efd0b6..00000000 --- a/team_b/yappy/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/team_b/yappy/macos/Runner.xcodeproj/project.pbxproj b/team_b/yappy/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 2856f6d7..00000000 --- a/team_b/yappy/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,705 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* yappy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "yappy.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* yappy.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* yappy.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/yappy.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/yappy"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/yappy.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/yappy"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yappy.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/yappy.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/yappy"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/team_b/yappy/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/team_b/yappy/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/team_b/yappy/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/team_b/yappy/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/team_b/yappy/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 3fd18668..00000000 --- a/team_b/yappy/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/team_b/yappy/macos/Runner.xcworkspace/contents.xcworkspacedata b/team_b/yappy/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16..00000000 --- a/team_b/yappy/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/team_b/yappy/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/team_b/yappy/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/team_b/yappy/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/team_b/yappy/macos/Runner/AppDelegate.swift b/team_b/yappy/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c17614..00000000 --- a/team_b/yappy/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f1..00000000 --- a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d9a33e198f5747104729e1fcef999772a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY diff --git a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eba55c6dabc3aac36f33d859266c18fa0d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5680 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 diff --git a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa40fb3d1e0710331a48de5d256da3f275d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 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 diff --git a/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/team_b/yappy/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632cfddf3d9dade342351e627a0a75609fb46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr - - - - - - - - - - - - - - - - - - - - - -