- Kotlin 100%
|
|
||
|---|---|---|
| .github/workflows | ||
| app1/bucketlist-phu3za | ||
| app2/footballscores-phu3za | ||
| hw0/helloworld-phu3za | ||
| specs | ||
| .gitignore | ||
| README.md | ||
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 inmutableStateOf. BucketItemis an immutable data class updated withcopy(). Checking an item sets its completed date to today, and unchecking clears it.- All three screens share
BucketRepository, a Kotlinobject, 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
ScoresActivityshows one screen driven byScoresViewModel, created withviewModel(). The selected division and week and a sealedScoresUiState(Loading, Success, Error) live inmutableStateOf, 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. Gameis both the Room row and the UI model, keyed by(division, id)because a game can appear in both feeds.@Upsertoverwrites 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)"), notfinalMessage. 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.