S3: Final Deliverable - ISIS3510-202510-T14/Documentation GitHub Wiki
Some considerations before going into the review of the sprint activities: We would like to highlight that the APK for the mobile application was shared with the TAs via Microsoft Teams. Therefore, we expect any source code to mainly rely on static analysis of the code.
If the TAs wish to perform dynamic analysis (running the app and interacting with the backend services), we kindly ask them to reach out to one of the team members. We will provide the necessary instructions to properly set up and test the mobile app along with the associated infrastructure.
Thank you for your time and support throughout the project!
- 1. Features Delivered
- 2. Business Questions (BQs)
- 3. Eventual Connectivity Strategy
- 4. Local Storage Strategy
- 5. Multi-threading Strategy
- 6. Caching Strategy
- 7. New Functionalities
- 8. Ethics Video
This section lists the work distribution for all features delivered in this sprint. For reference on tasks delivered for Sprint 2 visit this link.
- NA
- Business Question C - Analytics on Events Attention
- Business Question B - Endpoint for Logging API Response Times
- Business Question A - New Relic Error Logging
- Bet History Screen
- Local Storage for Bets done by User
- Thread Optimization with Isolate
- EC Strategy for Place Bet Screen (Use of Local Storage)
- Bookmark Filter on MatchesScreen
- Bookmarks Screen
- Connectivity Notifier Utility
- Caching Strategy for Team Images
- Local Storage for Matches
- Local Storage for Bookmarked Matches by User
- Business Question C - Logging on each call to Backend
- EC Strategy for Login View
- Local Storage for Recommended Bets
- Local Storage for User Email
- Firebase Credentials Persistence
These were the business questions addressed in this sprint:
Type | Question |
---|---|
Type 1 | A. How many times have connection errors occurred across all endpoints in the last week? |
B. What is the average response time for key API endpoints over the last week, and are there any noticeable slowdowns? [1] | |
Type 3 | C. What sports events series gather the least attention from our users? |
Campus Picks funnels runtime errors to New Relic Logs through an offline-first batched pipeline. It works and looks on the way presented below:
Layer | Code location | When it fires | Example call |
---|---|---|---|
HTTP failures | BackendApi, BetViewModel, MatchesViewModel, … | catch on any REST call | logError('/api/bets', 'BadStatus500') |
Connectivity | ConnectivityNotifier | ConnectivityResult.none | logError('connectivity_change', 'none') |
Background isolate | IsolateManager._sendDraft() | Failed draft POST | logError('isolate_sync', 'Timeout') |
SQLite issues | Any catch(DatabaseException) | Schema mismatch / I/O errors | logError('local_db_bets', 'MissingColumn') |
A "API Metrics Dashboard" dashboard that displays the average response times for different API endpoints. It includes a filter form at the top, allowing users to specify a start and end date as well as minimum and maximum response times to refine the displayed data. The table below the form dynamically lists each endpoint and its corresponding average response time, pulling the data from the backend logs database. If no data matches the filters, the table shows a message indicating that no data is available. The overall design is simple, clean, and user-friendly, making it easy to monitor API performance.
You can visit this dashboard on the /analytics/metrics-dashboard/
backend endpoint.
A new feature has been introduced to the analytics dashboard that visualizes betting activity by sport through a bar chart. This enhancement involves backend changes, including the addition of a get_bet_count_by_sport
function in views.py
that maps events to sports and counts associated bets using Counter
, returning the data as a dictionary. The dashboard_view
function was also updated to include this data in the context as sport_bet_counts
. On the frontend, the dashboard now features a new "Sports attention" section containing a bar chart rendered with Chart.js, which dynamically displays data from the backend-provided sport_bet_counts
variable.
Scenario ID | Event Description | System Response | Image |
---|---|---|---|
1 | The user attempts to place a bet without an internet connection. | The application notifies the user that the bet could not be processed due to connectivity issues and stores the bet amount along with the selected team. When the user returns, the information will be pre-loaded so they can manually retry the bet. | ![]() |
2 | The user accesses the list of matches without an internet connection. | The application attempts to fetch the latest data from the backend to display up-to-date information. Since there is no connection, it falls back to the most recent cached version, prioritizing the latest matches. The user is notified that offline content is being displayed. | ![]() |
3 | The app is started for the first time (no user has logged in so far) without an internet connection. | The application, which is on the LoginScreen, blocks the Log In and Sign Up buttons, shows offline banner and snackbar for as long as user remains offline. | ![]() |
4 | The user opens the application offline after having previously logged in. | The application securely retrieves the stored credentials and allows offline access with limited functionality, displaying a notice about the restrictions. | ![]() |
5 | The user accesses the Recommended Bets section without an Internet connection. | The app tries to fetch the latest recommendations from the backend; if no network is available, it shows the cached recommendations and notifies the user of offline mode. When connectivity is restored, it syncs in the background and refreshes the view. | ![]() |
6 | The user accesses the Matches section without an Internet connection. | The app tries to fetch the latest recommendations from the backend; if no network is available, it shows the cached matches and notifies the user of offline mode. When connectivity is restored, it syncs in the background and refreshes the view. | ![]() |
On lib/presentation/screens/login_screen.dart
we implemented a functionality in LoginScreen
to save the user's email to local storage using shared_preferences
upon successful login and load it when the screen initializes.
Added MatchRepository
to handle database operations for matches, including fetching, adding, updating, and removing match records. See (lib/data/repositories/match_repository.dart
)
Added RecommendedBetRepository
for managing RecommendedBet
entities, with methods for CRUD operations. See (lib/data/repositories/recommended_bet_repository.dart
)
Added BetRepository
to abstract database operations for BetModel
, including methods for insertion, retrieval, updating, and deletion of bets. See (lib/data/repositories/bet_repository.dart
)
BetModel
Updates: Added isDraft
and syncedAt
fields to track offline drafts and their sync status. Updated JSON serialization/deserialization to handle these fields (These are written into a local sql db).
To ensure that resource-intensive tasks such as draft synchronization do not block the main UI thread, we adopted a multi-threading strategy using Dart's Isolate
system. This approach enables true parallelism by offloading heavy operations to a background isolate, ensuring the app remains responsive and performant even during background tasks.
This strategy was critical for improving user experience, particularly in scenarios where users work offline or generate multiple drafts that require later synchronization with the backend. By decoupling synchronization from the main thread, we minimized UI freezes, enhanced reliability, and laid the groundwork for future background processing tasks.
-
Added
IsolateManager
inlib/data/services/isolate_manager.dart
, a singleton that manages a background isolate for running tasks such as draft synchronization. It includes methods for initializing the isolate, enqueuing tasks, and handling inter-isolate communication. -
Created
BackgroundSyncService
inlib/data/services/background_sync_service.dart
as a façade for enqueuing draft synchronization tasks to the background isolate.
- Refactored
DraftSyncService
inlib/data/services/draft_sync_service.dart
to delegate draft synchronization to the background isolate viaBackgroundSyncService
. Removed the inline HTTP POST logic and replaced the_syncPendingDrafts
method with_scheduleSync
, which now serializes drafts and sends them to the isolate.
- Updated
main.dart
to initialize the background isolate at app startup by callingIsolateManager().initialize()
in themain
function.
To improve user experience and performance when displaying team logos in match cards, we implemented an image caching strategy using the cached_network_image
package. This approach leverages network-level caching with disk persistence, meaning that once an image is fetched, it is stored locally and reused for subsequent loads—eliminating the need to repeatedly download the same image.
These changes were crucial for optimizing app performance, especially in environments with limited connectivity or frequent match updates. By replacing static Image.asset
calls with CachedNetworkImage
, we enabled smoother UI rendering, added placeholder and error image handling, and significantly reduced the app’s bandwidth usage during image loading.
-
lib/data/models/match_model.dart
: AddedlogoTeamA
andlogoTeamB
fields to theMatchModel
class, defaulting to specific URLs or fallback images if not provided. -
lib/presentation/widgets/finished_match_card.dart
,lib/presentation/widgets/live_match_card.dart
,lib/presentation/widgets/match_card.dart
: ReplacedImage.asset
withCachedNetworkImage
for team logos, enabling smooth loading with placeholders and error handling. -
pubspec.yaml
Added thecached_network_image
dependency to support the new image loading mechanism.
-
lib/data/repositories/favorite_repository.dart
: Added mapping ofhome_logo
andaway_logo
fields tomutableRow
to support the new logo structure. -
lib/presentation/viewmodels/matches_view_model.dart
: Updated fallback logos for demo matches to use URLs instead of local assets.
We will explain some of the new functionalities developed in this sprint that have been so far not thoroughly covered above.
In the Matches Screen:
- Each match card has a star icon at the top.
- Tapping the star bookmarks the match (highlighting the star).
- The AppBar has a star button too; tapping it filters the list to show only bookmarked matches.
This lets users easily track and access their favorite or important games without scrolling through all matches.

This is the "My Bets" screen of our mobile app. It lists the user's placed bets, each bet is marked as "PLACED" with a purple label on a card showing:
- The match (e.g., Santo Andre W vs Sao Jose W),
- The team the user bet on,
- The odds,
- The stake amount,
- And the placement date and time.
