Sprint 2 - ISIS3510-grupo/Proyecto GitHub Wiki

1. Business Questions

Each member of the team is responsible for implementing at least one Business Question (BQ) defined during Sprint 1. For each implemented BQ, this section will include the responsible team member, its type, the implemented analysis, and a brief rationale explaining its relevance to CampusFind.

Implemented Business Questions

Team Member Business Question Type Rationale Implementation
Jhostin Which app features are used most frequently by students? Type 3 Shows which parts of the student app bring value and which ones are ignored, so the team can prioritize, improve or remove features with real usage data. The Flutter app records a featureUsageEvents event each time a student uses a feature. An hourly Cloud Function aggregates the events per feature (total, last 7 days, by platform) into analytics/featureUsage.
Camilo How does the successful ownership-verification rate differ between reports that include private identifying characteristics and those that do not? Type 3 This BQ shows staff whether asking students for private identifying details makes ownership verification more reliable. It supports deciding whether the app should encourage richer private details when a lost item is reported. The Admin App reads all claims from Firestore and compares each student's private ownership answer with the private characteristics registered for the found item, using a word-overlap matcher. A verification is successful when the match score is at least 60% (LIKELY_MATCH). Claims are grouped by whether the lost report has a private detail document, and the screen shows the success rate of each group and the difference in percentage points.
Sofia What percentage of students review a possible match after receiving a notification? Type 3 This business question measures the effectiveness and accuracy of the app's matching system from the student's perspective. In the context of Los Andes University, it evaluates the percentage of students who, upon receiving a notification, confirm that the system's suggested match actually corresponds to the item they reported lost. This metric is essential for validating the quality of the matching algorithm between lost item reports and items logged at the lost and found office, determining how many generated notifications lead to a successful recovery. The BQ3 implementation uses an event-driven architecture to measure student response to lost-and-found match notifications. When a notification is dispatched, a notification_sent event is logged to the Firestore /analytics collection; when the student taps the notification in NotificationsScreen, a corresponding match_reviewed event is captured. MatchAnalyticsService queries these logs, utilizing Set data structures to eliminate duplicates from repeated taps and calculate the true conversion rate via set intersection, which is then rendered dynamically on the MatchAnalyticsScreen view.
Daniel What is the average response time of the app when searching for possible matches between lost and found item reports? Type 1 My Business Question measures the performance of the Smart Lost–Found Matching process from the student’s perspective. This analysis makes it possible to identify how long the application takes to search for possible matches and determine whether that response time is acceptable for the user experience. It also helps evaluate whether the matching process remains responsive as the number of lost and found item reports increases. This BQ is implemented in the Kotlin application, where the duration of each successful search for possible matches is measured from "SmartMatchingViewModel" using "SystemClock.elapsedRealtime()". The measurement starts before loading the matching configuration, querying Firestore for available found items, and executing the comparison. When the search process finishes successfully, the elapsed time is stored in milliseconds in the "performanceMetrics" collection, using the "match_search" metric and the kotlin platform. Then, "MatchSearchTimeRepository" retrieves the recorded times and calculates their average. Finally, the calculated result is presented to administrative staff as the Average match-search time KPI in the "AdminMatchSearchTimeScreen" view.
Emilio How long does the application take to register a new lost or found item report? Type 3 This BQ measures the performance of the report registration process from the moment the validated submission starts until the backend confirms that the report was successfully created. It helps identify whether registering lost or found items is taking too long and whether the experience is consistent for both types of reports The application uses a performance tracker around the complete report registration operation, including GPS retrieval and the Firestore write. For each successful registration, the system stores the report type and the elapsed time in milliseconds in perfomanceMetrics. These measurements are then aggregated and displayed in the Analytics Dashboard, showing the overall average registration time and separate averages for lost and found reports.
Alex What types of unclaimed items at the end of the semester have the potential for donation to external organizations? Type 4 This BQ helps identify unclaimed items that could be donated instead of remaining indefinitely in storage. It supports better inventory management and allows the university to make use of items that are no longer likely to be claimed. The analysis uses lost-and-found inventory data such as item category, status, date, condition, and whether the item remains unclaimed at the end of the semester. These records are processed through the analytics pipeline to identify categories of items with donation potential.

2. Analytics Pipeline

The analytics pipeline will describe how data generated by the CampusFind applications is collected, stored, processed, and used to answer the implemented Business Questions.

Analytics Pipeline Diagram

Analytics Pipeline

Figure 1. CampusFind Analytics Pipeline.

Rationale

The CampusFind analytics pipeline was designed to transform operational data generated by both mobile applications into information that can support the Business Questions defined for Sprint 2.

The pipeline is divided into five stages: Data Sources, Ingestion & Integration, Storage, Computation, and Presentation. This separation allows the system to collect data from both the Kotlin and Flutter applications while keeping a common analytics process based on the shared Firebase backend.

The Data Sources stage includes the main events and entities generated by CampusFind, such as lost-item reports, found items, claims, status-change events, notifications, and performance metrics. These data sources provide the information required to analyze user behavior, process performance, matching results, and item outcomes.

The Ingestion & Integration stage uses Firebase services and the shared Firestore data model to receive and persist information generated by both applications. Authentication and security rules ensure that data is associated with authorized users and that operational and analytics information is accessed according to the corresponding roles.

In the Storage stage, Firestore collections organize the information required by the different Business Questions. Keeping these records in a shared backend allows both mobile implementations to contribute data to the same analytics pipeline.

The Computation stage transforms the stored information into metrics and aggregated results. The pipeline includes analyses related to application performance, process times, matching behavior, user engagement, and item outcomes. Each Business Question is answered using the subset of data and calculations relevant to its objective.

Finally, the Presentation stage exposes the computed results through visualizations and indicators, such as average processing times, report bottlenecks, reviewed matches, and donation potential by item category.

This architecture was selected because it separates operational application logic from analytics processing, while allowing the Business Questions to be answered using consistent data generated by both CampusFind applications. It also makes the pipeline extensible, since new Business Questions can reuse the same stored events and add new computations or visualizations without modifying the main mobile application flows.


Business Question Resolution Through the Analytics Pipeline

What types of unclaimed items at the end of the semester have the potential for donation to external organizations? Alex - BQ Type 4 Answer

Which app features are used most frequently by students? Jhostin - BQ Type 3 Answer

What percentage of students review a possible match after receiving a notification? Sofia - BQ Type 3

How does the successful ownership-verification rate differ between reports that include private identifying characteristics and those that do not? Camilo - BQ Type 3 Answer

What is the average response time of the app when searching for possible matches between lost and found item reports? Daniel- BQ Type 1 Answer

How long does the application take to register a new lost or found item report? Emilio- BQ Type 3 Answer


3. Architectural Design

CampusFind uses two independent mobile implementations that provide the same application functionality: one developed with Flutter/Dart and another developed as a native Android application using Kotlin. Both applications share the same Firebase backend, authentication infrastructure, database model, security rules, and persistent information.

The architectural design is divided into three parts:

  • 3.a. Architecture: overall system structure and components
  • 3.b. Architecture design: interaction and communication between components
  • 3.c. Design patterns and architectural tactics

3.a. Architecture: Overall System Structure and Components

Architectural Pattern: MVVM

CampusFind follows the Model-View-ViewModel (MVVM) architectural pattern. The project uses a shared architecture, backend, data model, and application logic organization.

MVVM separates the system into three main responsibilities:

  • View: Displays information, receives user interactions, and renders the state provided by the ViewModel. It includes the student and administrator interfaces such as authentication, reports, matching, inventory, and claims.

  • ViewModel: Manages screen state and coordinates application operations. It communicates with repositories and services and handles states such as loading, success, empty, and error.

  • Model: Contains the domain models, repositories, services, and business logic. It is responsible for accessing persistent data and executing application functionality such as authentication, report management, matching, analytics, and claim processing.

The Model communicates with the system infrastructure, which includes Firebase Authentication, Cloud Firestore, Firebase Storage, device capabilities such as camera, GPS and biometrics, and external services such as Google Maps, email, and SMS.

Overall MVVM Architecture Diagram

CampusFind MVVM Architecture

Figure 2. CampusFind overall architecture using MVVM.

Rationale

MVVM was selected to separate the user interface from application state, business logic, and data access. This separation improves maintainability and allows each component to evolve independently while keeping a clear communication flow between the interface, application logic, and shared infrastructure.

3.b. Architecture design: interaction and communication between components

Kotlin

In the Kotlin application, the user interacts with Jetpack Compose screens, which delegate actions and state management to ViewModels. The ViewModels coordinate the application logic and communicate with repositories or services responsible for accessing Firebase Authentication, Cloud Firestore, device sensors, and external services.

For data that must remain synchronized with the backend, the application uses Firestore listeners. When data changes in Firestore, the corresponding data source or service receives the update and propagates it to the ViewModel. The ViewModel updates its state, causing the Compose UI to recompose automatically.

The general interaction flow is:

  1. The user performs an action in the View.
  2. The View delegates the action to a ViewModel.
  3. The ViewModel communicates with a repository, service, or data source.
  4. The data layer interacts with Firebase or a device/external service.
  5. The result is returned or observed by the ViewModel.
  6. The ViewModel updates the UI state.
  7. Jetpack Compose renders the updated state.

This communication model is used in flows such as authentication, lost-report visualization, possible-match monitoring, notifications, and location-aware reporting

Image

Flutter

In the Flutter application, the user interacts with Flutter widgets (the View). Widgets do not access Firebase or device APIs directly: they call methods on a ViewModel, implemented as a ChangeNotifier (for example AuthViewModel, HomeViewModel, ReportLostItemController or ClaimFormController). The ViewModel holds the screen state and asks the data layer for what it needs through an interface (LostReportRepository, ClaimRepository, AuthService, the analytics repositories). Only the data layer talks to Firebase Auth, Cloud Firestore, Firebase Storage, the device APIs (camera, GPS, connectivity, biometrics, local storage) and external services such as Google Maps.

Dependencies are passed through constructors, so each ViewModel can be tested with fake repositories instead of Firebase. When a ViewModel changes its state it calls notifyListeners(), and the widget that wraps that part of the screen in a ListenableBuilder rebuilds it.

Most reads are one-time requests that return a Future; screens that must show fresh data (login role check and the feature usage BQ) read with Source.server. The notifications screen uses a Firestore snapshots() stream to update in real time. Two processes run outside the screens: PendingReportSync, started in main.dart, sends the reports saved offline when the connection returns, and the Cloud Functions (aggregateFeatureUsage, every hour, and sendPossibleMatchEmail) react to data written in Firestore without being called by the app.

The general interaction flow is:

  1. The user performs an action in a widget.
  2. The widget calls a method of its ViewModel.
  3. The ViewModel requests data or an operation through a repository or service interface.
  4. The data layer interacts with Firebase, a device API or an external service.
  5. The result returns to the ViewModel as a Future (or a Stream for real-time data).
  6. The ViewModel updates its state and calls notifyListeners().
  7. ListenableBuilder rebuilds the affected part of the screen.
Flutter interaction flow
Flow View ViewModel Data layer Source
Report lost item ReportLostItemScreen ReportLostItemController LostReportRepository Firestore, Storage, local offline queue
Sign in LoginScreen AuthViewModel AuthService Firebase Auth, Firestore role, biometrics
Home and possible match HomeScreen, MatchAlertScreen HomeViewModel report repositories, MatchingService Firestore
Report with location ReportItemScreen ItemViewModel ItemDao Firestore, GPS
Claim a match ClaimFormScreen ClaimFormController ClaimRepository Firestore (claims, claimPrivate)
Analytics dashboard AnalyticsDashboardScreen one ViewModel per BQ panel analytics repositories Firestore (analytics/*)

The following sequence diagram applies this flow to a concrete case, reporting a lost item, and shows both paths: when the device is online and when the report is saved offline to be sent later.

Report lost item sequence

Figure. Sequence of the report lost item flow in Flutter.

Rationale. Keeping widgets free of data access means a screen can change without touching Firebase code, and the data source can change (online, offline queue, cache) without touching the screen. Passing interfaces to the ViewModels lets each flow be tested in isolation, and ListenableBuilder rebuilds only the part of the screen that changed.

3.c. Design Patterns and Architectural Tactics

Strategy Pattern – Emilio Zea

The full explanation, diagram, participating classes, and rationale are on Emilio Zea

Repository Pattern – Jhostin Sánchez

Implemented in the Flutter lost report feature: the screen and its ViewModel depend only on the LostReportRepository interface, while LostReportRepositoryImpl decides whether a report goes to Firestore, Firebase Storage or the offline queue. The diagram, the participating classes and the rationale are on Jhostin's page.

Observer Pattern – Alex Pérez

The full explanation, diagram, participating classes, and rationale are on Alex - Observer

Factory Pattern – Camilo Puerto

The full explanation, diagram, participating classes, and rationale are on Camilo - Factory

Data Access Object (DAO) - Sofia Losada

Complete explanation and diagram are on individual page

Adapter Pattern - Daniel Rivera

The full explanation, diagram, participating classes, and rationale are on Daniel- Adapter

4. Features

App Implemented feature Responsible
Kotlin Biometric identity verification Daniel
Kotlin Smart Lost–Found Matching Daniel
Kotlin Report Bottleneck analytics visualization Daniel
Kotlin Drop-off Instructions screen (S12) Daniel
Kotlin Directions to the Lost & Found location through Google Maps (External Service) Daniel
Kotlin Average Match-Search Time analytics visualization (Individual BQ) Daniel
Flutter Student sign-in and session access Emilio Zea
Flutter Biometric session verification Emilio Zea
Flutter Active lost report and possible match display on the Home screen Emilio Zea
Flutter Smart Lost–Found Matching Emilio Zea
Flutter Possible Match Alert screen (S08) Emilio Zea
Flutter Staff access to the Analytics Dashboard Emilio Zea
Flutter Report Bottleneck analytics visualization Emilio Zea
Flutter Drop-off Instructions screen (S12) Emilio Zea
Flutter Directions to the Lost & Found location through Google Maps Emilio Zea
Flutter Report Registration Time analytics visualization Emilio Zea
Kotlin Student authentication with Uniandes email validation Alex
Kotlin GPS-based location acquisition for lost-item reporting Alex
Kotlin Context-aware campus location suggestion Alex
Kotlin Possible match count per lost report (Type 2 BQ) Alex
Kotlin Android notification when a new possible match is detected Alex
Backend / External Service/ Kotlin Email notification infrastructure using Firebase Functions and Resend Alex
Flutter GPS-based location acquisition for lost-item reporting Sofia
Flutter Context-aware campus location suggestion Sofia
Flutter Student authentication with Uniandes email validation Sofia
Flutter Possible match count per lost report (Type 2 BQ) Sofia
Flutter Android notification when a new possible match is detected Sofia
Backend / External Service/ Flutter Email notification infrastructure using Firebase Functions and Resend Sofia
Flutter Report lost item with optional private verification detail Jhostin
Flutter Camera photo of the lost item (Sensor) Jhostin
Flutter Connectivity-aware submission with offline queue (Context-aware) Jhostin
Flutter / Backend Feature usage events and hourly aggregation (Type 3 BQ) Jhostin
Kotlin Admin authentication with role validation against Firestore Camilo
Kotlin Photo capture when registering a found item, uploaded to Firebase Storage and saved as photoPath Camilo
Kotlin Connectivity-aware registration: found items are saved on the device when offline and sent when the connection returns, without duplicates Camilo
Kotlin Average time from reported to found, grouped by category (Type 2 BQ) Camilo
Kotlin Smart claim verification: compares the student's answer with the item's private characteristics Camilo
Kotlin Private ownership detail stored separately from the public found item Camilo
Kotlin Ownership verification rate with and without private characteristics (individual BQ) Camilo
Backend / External Service / Kotlin SMS notification with Twilio, sent by a Cloud Function when a possible match is created (trial account, fixed template) Camilo

5. Ethics Video

Ethics Video – Sprint 2

⚠️ **GitHub.com Fallback** ⚠️