No description
Find a file
bairon 950cb7a7d3
Replace demo video placeholder with link
Updated demo section with a link to the demo video.
2026-10-15 16:56:09 -04:00
.github/workflows ci: post a commit status on every verified commit 2026-09-25 15:24:29 -04:00
app1/bucketlist-phu3za docs: update the App 1 README notes and remove the unused demo video 2026-09-26 03:37:33 -04:00
app2/footballscores-phu3za feat(app2): add scores screen with week selector and division toggle 2026-10-15 16:39:45 -04:00
hw0/helloworld-phu3za feat: add HW0 Android app and homework CI workflow 2026-09-08 17:12:47 -04:00
specs docs: add App 2 specification, grader notes, and AI usage 2026-10-15 16:45:49 -04:00
.gitignore feat: add HW0 Android app and homework CI workflow 2026-09-08 17:12:47 -04:00
README.md Replace demo video placeholder with link 2026-10-15 16:56:09 -04:00

CS 4720

Bairon Alejandro Recinos Monjaras, computing ID phu3za.

This README is updated with each homework submission.

HW0: Hello World

Project hw0/helloworld-phu3za/, package edu.virginia.cs4720.phu3za.

This is a single-activity Kotlin and Jetpack Compose app with no ViewModel or third-party libraries. Open hw0/helloworld-phu3za/ in Android Studio, or run ./gradlew assembleDebug from that directory.

Notes for the grader

All of the UI is in MainActivity.kt. The message label is the first element in the column, the name field sits below it, and the salutation radio group is below that. The salutations are Hello, Hi There, and Bonjour, and the initial message reads "Hello, Your name here!".

The two pieces of state use rememberSaveable from the Compose state guide linked in the assignment, so the message survives a rotation rather than resetting. No ViewModel is involved. Everything else is the standard Empty Activity template.

AI usage

I used my agent in a terminal-based workflow to scaffold the Gradle project and draft MainActivity.kt, then controlled an API 34 Android emulator headlessly through ADB. I reviewed every file and directed revisions until the app used only standard AndroidX and Jetpack Compose APIs, two local state values, and one single-select radio group. I ran the Gradle build and lint, then used accessibility dumps to verify the initial greeting, live name update, and Bonjour selection.

App 1: UVA Bucket List

Project app1/bucketlist-phu3za/, package edu.virginia.cs4720.phu3za.bucketlist. Open it in Android Studio, or run ./gradlew assembleDebug from that directory.

Notes for the grader

  • List, Create, and Detail are separate Activities, each with its own ViewModel from viewModel() that holds its state in mutableStateOf.
  • BucketItem is an immutable data class updated with copy(). Checking an item sets its completed date to today, and unchecking clears it.
  • All three screens share BucketRepository, a Kotlin object, so saves show in the list right away. Detail gets only the item id as an intent extra and edits a copy, so Cancel changes nothing.
  • The list starts with five sample items. Nothing is saved to disk.
  • The due date uses the Material 3 DatePicker, and Save stays disabled until the item has a name and a date.
  • The theme uses UVA navy and orange with a dark palette, set in Libre Franklin and Libre Caslon Text, the free matches for UVA's brand fonts. Font credits are in fonts/.

Demo

https://github.com/user-attachments/assets/92b133f7-147d-4c0d-bb04-0fa548aa5974

AI usage

I used my agent in a terminal-based workflow to draft the data layer, the three Activities and ViewModels, the theme, and the unit tests. I reviewed each file and directed the design, including the shared repository, immutable updates through copy(), and a draft copy in Detail so Cancel never touches the list, then had it simplify the architecture after the first pass. I verified it with the Gradle build, lint, and unit tests, and by driving an API 34 emulator through ADB to add, check, edit, cancel, and rotate, watching the list re-sort after each change.

App 2: College Football Scores

Project app2/footballscores-phu3za/, package edu.virginia.cs4720.phu3za.footballscores. Open it in Android Studio, or run ./gradlew assembleDebug from that directory.

Notes for the grader

  • ScoresActivity shows one screen driven by ScoresViewModel, created with viewModel(). The selected division and week and a sealed ScoresUiState (Loading, Success, Error) live in mutableStateOf, so rotation keeps them and starts no fetch.
  • Screen open, week change, division toggle, Refresh and Retry all call one load(). It fetches the week with Retrofit and upserts it into Room, and the screen reads only Room, through a Flow.
  • Game is both the Room row and the UI model, keyed by (division, id) because a game can appear in both feeds. @Upsert overwrites a stored game with its newest state, so no stale scores or duplicates.
  • With no network, saved weeks stay browsable under an "Offline" line. A week with nothing saved shows an error with Retry, and a week with no games shows "No games this week".
  • The current week is mapped from today's date: weeks run Tuesday to Monday and week 1 ends on Labor Day (starting Sep 1 in 2026). The selector covers weeks 1 to 14.
  • The feed marks overtime finals in currentPeriod ("FINAL (2OT)"), not finalMessage. Start times are Eastern, as the feed reports them.

Demo

https://github.com/user-attachments/assets/908820c3-b375-45b1-a19a-672705749400

AI usage

I used my agent in a terminal-based workflow to explore the API and draft the data layer, the ViewModel and screen, and the unit tests. I directed it to the smallest design that meets the spec (one class as the Room row and the UI model, one load() for every trigger) and dropped extras such as pull-to-refresh and instrumented tests. I verified it with the Gradle build, lint and unit tests, and on an API 34 emulator through ADB: week and division changes, offline and empty states, rotation, and the database file, where I rewrote a stored game as a stale live score and confirmed a refresh overwrote it with no duplicate.