Crit C
Crit C
Overview
This approach ensures loose coupling between the database schema and the
application logic. If I need to change or add new attributes in the future, I can
do so without breaking other parts of the code.
1.2 UserModel
class UserModel {
final String uid;
final String email;
final String role; // "teacher" or "student"
final String displayName;
UserModel({
required this.uid,
required this.email,
Crit C : Development 1
required this.role,
required this.displayName,
});
Explanation
1.3 ClassModel
Crit C : Development 2
class ClassModel {
final String classId;
final String className;
final String teacherId;
final List<String> studentIds;
ClassModel({
required this.classId,
required this.className,
required this.teacherId,
required this.studentIds,
});
Explanation
Crit C : Development 3
which class.
Relavance
• This structure simplifies queries. For example, if I need to find all classes
for a student, I only need to check if the student’s ID is in studentIds. This is an
efficient way to store many-to-one relationships (many students to one class).
1.4 AssignmentModel
class AssignmentModel {
final String assignmentId;
final String classId;
final String title;
final String description;
final DateTime dueDate;
AssignmentModel({
required this.assignmentId,
required this.classId,
required this.title,
required this.description,
required this.dueDate,
});
Crit C : Development 4
'description': description,
'dueDate': dueDate,
};
}
}
Explanation
• title and description: Let teachers provide details about what students
must do.
Justification
• Assignments are a core object in the system. By separating them from the
class, teachers can reuse or reorder assignments, or even link them to multiple
classes if the app expands.
1.5 SubmissionModel
class SubmissionModel {
final String submissionId;
final String assignmentId;
final String studentId;
final String fileUrl;
final double grade; // -1 means ungraded
final String feedback; // For teacher feedback
SubmissionModel({
required this.submissionId,
required this.assignmentId,
required this.studentId,
required this.fileUrl,
required this.grade,
required this.feedback,
});
Crit C : Development 5
cId) {
return SubmissionModel(
submissionId: docId,
assignmentId: data['assignmentId'],
studentId: data['studentId'],
fileUrl: data['fileUrl'],
grade: data['grade'].toDouble(),
feedback: data['feedback'] ?? '',
);
}
Explanation
• assignmentId: Links the submission to the correct assignment for grading.
Crit C : Development 6
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
Explanation
if (userDoc.exists) {
String role = userDoc.get('role');
if (role == 'teacher') {
// Navigate to teacher dashboard
} else {
// Navigate to student dashboard
}
Crit C : Development 7
}
}
Explanation
1. signInWithEmailAndPassword(email, password): Authenticates the user
using Firebase’s built-in email/password method.
2. uid = userCredential.user!.uid: We retrieve a unique User ID from
FirebaseAuth.
3. We fetch the Firestore document for that uid to determine the user’s role.
4. Depending on the role, the app navigates to either the teacher or student
dashboard.
Justification
• Using email/password is a straightforward choice for educational
applications.
• Having the role in Firestore is more flexible than relying solely on Auth
claims. It allows dynamic updates to user roles and easy references in the app.
if (image != null) {
// Upload the image to Firebase Storage
String url = await uploadToFirebaseStorage(image.path);
Explanation
Crit C : Development 8
• ImagePicker: A popular Flutter plugin to capture or pick images from the
device camera or gallery.
textRecognizer.close();
return extractedText;
}
Explanation
Crit C : Development 9
• Automating text extraction is a crucial feature. By hooking into a
recognized library (google_ml_vision), we ensure a decently accurate OCR
pipeline without implementing the low-level computer vision logic ourselves.
correctAnswers.forEach((question, answer) {
// Simple matching logic
if (extractedText.contains(answer)) {
score += 1;
}
});
Explanation
• Using .contains(...) is a first iteration: it’s easy to implement but might not
account for variations or typos.
• This can be extended with fuzzy matching (e.g., Levenshtein distance) for
partial-credit logic or AI-based text similarity.
4. Teacher-Side Implementation
Crit C : Development 10
Future<void> createClass(String className) async {
String classId = FirebaseFirestore.instance.collection('classes').doc().id;
await FirebaseFirestore.instance
.collection('classes')
.doc(classId)
.set(newClass.toMap());
}
Explanation
• This centralizes the creation logic, so if future changes are needed (e.g.,
auto-enrollment or generating class codes), it is straightforward to add them
here.
Crit C : Development 11
classId: classId,
title: title,
description: description,
dueDate: dueDate,
);
await FirebaseFirestore.instance
.collection('assignments')
.doc(assignmentId)
.set(newAssignment.toMap());
}
Explanation
• Teachers can directly link the newly created assignment to a specific
classId.
• dueDate allows the teacher to set a clear deadline, which can be displayed
in the UI or used in notifications.
Justification
Explanation
Crit C : Development 12
• This function updates an existing submission document with a final grade
and textual feedback.
• A teacher might call this after reviewing OCR results to confirm or override
the automatically generated score.
Justification
• Maintaining separate logic for grading vs. creating submissions keeps the
code modular. If the grading algorithm changes, only this function (and related
code) needs updating.
5. Student-Side Implementation
5.1 Viewing Assignments
Explanation
• A Firebase query that uses .where('classId', whereIn: studentClassIds),
returns only assignments matching any of the classes the student is enrolled in.
• snapshots() creates a real-time data stream, so the UI updates whenever
an assignment is added or changed.
Justification
• Keeping the UI in sync with Firestore is a major strength of
Flutter+Firebase. Students see updates instantly, which improves engagement
and transparency.
Crit C : Development 13
Future<void> createSubmission(String fileUrl, String assignmentId) async {
String submissionId = FirebaseFirestore.instance.collection('submission
s').doc().id;
await FirebaseFirestore.instance
.collection('submissions')
.doc(submissionId)
.set(newSubmission.toMap());
}
Explanation
• The student picks an assignment (by assignmentId) and attaches a file
reference (fileUrl).
• A fresh submissionId is generated, and the record is written to the
submissions collection.
Justification
• Defining grade = -1 as a default indicates to both the teacher and the
system that the submission has not been reviewed yet. This prevents confusion
over whether a submission is missing or just ungraded.
Crit C : Development 14
return SubmissionModel.fromMap(doc.data() as Map<String, dynamic
>, doc.id);
});
}
Explanation
if (userDoc.exists) {
_currentUser = UserModel.fromMap(userDoc.data() as Map<String,dyn
amic>, userDoc.id);
notifyListeners();
}
}
}
Explanation
Crit C : Development 15
• The UserProvider is a class that extends ChangeNotifier, meaning it can
notify any widgets listening to it when user data changes.
• The loadUserData method populates _currentUser from Firestore, then
calls notifyListeners() to force a UI rebuild if needed.
Justification
Explanation
• Unit tests focus on isolated functions, such as gradeSubmission.
• Verifies that 100% of answers matched returns a score of 100.0.
Justification
• By verifying the function’s correctness, I catch logical errors before
shipping the product.
7.2 Integration Testing
• Simulated teacher and student flows in a staging environment:
1. Teacher logs in → creates a class → creates an assignment.
Crit C : Development 16
Why this matters
• Ensures all components work together. A single unit test passing doesn’t
guarantee that multiple pieces integrated together function correctly.
7.3 Debugging OCR Inaccuracies
• Issue: In low light or with poor handwriting, the OCR results were
incomplete.
Crit C : Development 17
3. Role-Based Security
• Simple logic (if role == 'teacher' ... else) ensures the same codebase can
handle multiple user types.
4. OCR Integration
• Incorporating text recognition into a student submission process is an
innovative feature for an educational app, streamlining grading and providing a
unique aspect to the project.
Crit C : Development 18