From be6ca974f5c06478f3033fd81784532411617924 Mon Sep 17 00:00:00 2001 From: SuperMeerkat345 Date: Sun, 22 Mar 2026 20:50:22 -0400 Subject: [PATCH 1/6] created branch for team names before testing --- .../team695/scoutifyapp/data/repository/TeamNameRepository.kt | 2 +- .../com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt index e91b630..49385fe 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt @@ -25,7 +25,7 @@ class TeamNameRepository ( ) } - Result.success(Unit) + return@withContext Result.success(Unit) } } diff --git a/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt b/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt index 6f1537e..5222a4f 100644 --- a/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt +++ b/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt @@ -88,7 +88,7 @@ class CommentsViewModel ( fun onMatchSelected(match: String) { autoSaveJob?.cancel() _selectedMatch.value = match - match.toIntOrNull()?.let { // safe check cuz it was crashing when going to home + match.toIntOrNull()?.let { fetchComments(it) } updateTeamNames() From 71480cc586975fe7edd4c26ee95a93cb1cdfc785 Mon Sep 17 00:00:00 2001 From: alexfinger21 Date: Sat, 28 Mar 2026 23:56:49 -0400 Subject: [PATCH 2/6] old tasks at the bottom --- .../scoutifyapp/data/api/NetworkMonitor.kt | 5 +- .../scoutifyapp/data/api/model/Task.kt | 2 +- .../data/repository/GameDetailRepository.kt | 17 ++---- .../data/repository/TaskRepository.kt | 1 + .../ui/screens/home/MatchSchedule.kt | 3 +- .../scoutifyapp/ui/screens/home/TasksCard.kt | 53 ++++++++++++++++--- .../ui/viewModels/HomeViewModel.kt | 2 - 7 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/team695/scoutifyapp/data/api/NetworkMonitor.kt b/app/src/main/java/com/team695/scoutifyapp/data/api/NetworkMonitor.kt index ca57ba7..7cfd6de 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/api/NetworkMonitor.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/api/NetworkMonitor.kt @@ -107,11 +107,12 @@ class NetworkMonitor( } gameDetailRepository.fetch() - gameDetailRepository.isReady.first { it } - + println("fetched, trying to push") retryFetchUntilSuccess() + gameDetailRepository.push() retryPushUntilSuccess() + delay(FETCH_INTERVAL) } } diff --git a/app/src/main/java/com/team695/scoutifyapp/data/api/model/Task.kt b/app/src/main/java/com/team695/scoutifyapp/data/api/model/Task.kt index 4cc0690..c628ca7 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/api/model/Task.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/api/model/Task.kt @@ -47,7 +47,7 @@ fun SelectAllTasksWithTime.createTaskFromDb() = createTaskFromDb( type, matchNum, teamNum, - time, + time_, progress ) diff --git a/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt index 7014d2d..c3092a1 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt @@ -37,10 +37,12 @@ class GameDetailRepository( private val appService: AppService, private val db: AppDatabase, ): Repository { - + /* val isReady: MutableStateFlow = MutableStateFlow(false) + var pulledConstants = false private set + */ override suspend fun push(): Result> { return withContext(Dispatchers.IO) { @@ -184,11 +186,6 @@ class GameDetailRepository( } override suspend fun fetch(): Result { - if (pulledConstants) - return Result.failure(Exception("already pulled game constants")) - - pulledConstants = true - return withContext(Dispatchers.IO) { try { val result: ApiResponse = gameDetailsService.getGameConstants( @@ -197,7 +194,6 @@ class GameDetailRepository( if (result.data != null) { if (result.data != GameConstantsStore.constants) { - // clear all data db.transaction { db.taskQueries.clearAllTasks() @@ -233,20 +229,13 @@ class GameDetailRepository( app_version = app_version ) - isReady.value = true - return@withContext Result.success(result.data) } else { - pulledConstants = false - return@withContext Result.failure( Exception("Game constants are empty") ) } } catch (e: Exception) { - pulledConstants = false - isReady.value = true - Log.e("Game Constants", "Error when trying to fetch gameConstants: $e") return@withContext Result.failure(e) } diff --git a/app/src/main/java/com/team695/scoutifyapp/data/repository/TaskRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/TaskRepository.kt index 5ad63f1..4a679ee 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/repository/TaskRepository.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/repository/TaskRepository.kt @@ -36,6 +36,7 @@ class TaskRepository( .mapToList(Dispatchers.IO) .map { entities -> entities.map { entity -> + println("TASK: $entity") entity.createTaskFromDb() } } diff --git a/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/MatchSchedule.kt b/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/MatchSchedule.kt index b0a0b33..369cb53 100644 --- a/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/MatchSchedule.kt +++ b/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/MatchSchedule.kt @@ -91,7 +91,6 @@ fun MatchSchedule( ) { var searchQuery: String by remember { mutableStateOf("") } val matchState by homeViewModel.matchState.collectAsStateWithLifecycle() - val readyState by homeViewModel.isReady.collectAsStateWithLifecycle() val teamState by homeViewModel.teamsState.collectAsStateWithLifecycle() val sortedMatches = remember(matchState) { @@ -274,7 +273,7 @@ fun MatchSchedule( } } } - if (matchState.isNullOrEmpty() || !readyState) { + if (matchState.isNullOrEmpty()) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/TasksCard.kt b/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/TasksCard.kt index e3bb7f0..8af3f41 100644 --- a/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/TasksCard.kt +++ b/app/src/main/java/com/team695/scoutifyapp/ui/screens/home/TasksCard.kt @@ -72,9 +72,39 @@ fun TasksCard( val tabs = arrayOf("Incomplete", "Complete") val tasksState by homeViewModel.tasksState.collectAsStateWithLifecycle() + val sortedTasks = tasksState?.sorted() + + val completeTasks = sortedTasks?.filter { it.progress >= 100 } + val incompleteTasks = sortedTasks?.filter { it.progress < 100 } + val sortedIncompleteTasks = arrayOfNulls(incompleteTasks?.size ?: 0) + + if (incompleteTasks != null && completeTasks?.size!! > 0) { + val latestCompleteTask = completeTasks[completeTasks.size - 1] + val len = sortedIncompleteTasks.size + + var missed = 0 + var idx = 0 + println("got here: ${latestCompleteTask.matchNum} ${latestCompleteTask.time}") + + for (task in incompleteTasks) { + //println(latestCompleteTask.time - task.time) + if (task.time < latestCompleteTask.time) { + ++missed + sortedIncompleteTasks[len - missed] = task + } else { + sortedIncompleteTasks[idx] = task + ++idx + } + } + } else if (incompleteTasks != null) { + var idx = 0 + + for (task in incompleteTasks) { + sortedIncompleteTasks[idx] = task + ++idx + } + } - val incompleteTasks = tasksState?.filter { it.progress != 100 }?.sorted() - val completeTasks = tasksState?.filter { it.progress >= 100 }?.sorted() Log.d("TASKS_CARD", "RE-RENDER") Box( @@ -82,7 +112,11 @@ fun TasksCard( .fillMaxHeight() .fillMaxWidth() .clip(RoundedCornerShape(8.dp)) - .border(1.dp, LightGunmetal, RoundedCornerShape(smallCornerRadius)) + .border( + 1.dp, + LightGunmetal, + RoundedCornerShape(smallCornerRadius) + ) ) { Box( modifier = Modifier.wrapContentWidth(unbounded = true) @@ -108,7 +142,11 @@ fun TasksCard( Box ( modifier = Modifier .clip(RoundedCornerShape(8.dp)) - .border(1.dp, LightGunmetal, RoundedCornerShape(smallCornerRadius)) + .border( + 1.dp, + LightGunmetal, + RoundedCornerShape(smallCornerRadius) + ) .background(Background) ) { PrimaryTabRow( @@ -162,11 +200,14 @@ fun TasksCard( } Spacer(modifier = Modifier.height(16.dp)) LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) { - val tasks = (if (tabState.selectedTab == 0) incompleteTasks else completeTasks) + val tasks = if (tabState.selectedTab == 0) + sortedIncompleteTasks.toList() + else + completeTasks if(tasks != null) { items(tasks) { task -> - TaskItem(task = task, onPress = {onPress.invoke(task.id)}) + TaskItem(task = task!!, onPress = {onPress.invoke(task.id)}) } } } diff --git a/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/HomeViewModel.kt b/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/HomeViewModel.kt index a070e7b..8c5d077 100644 --- a/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/HomeViewModel.kt +++ b/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/HomeViewModel.kt @@ -44,8 +44,6 @@ class HomeViewModel( private val _tabState = MutableStateFlow(TabState()) val tabState: StateFlow = _tabState - val isReady: StateFlow = gameDetailRepository.isReady - val teamsState = taskRepository.teams .stateIn( scope = viewModelScope, From aa40a97b954e2a42f9aa084ffc4741bf4d595897 Mon Sep 17 00:00:00 2001 From: igor024 Date: Sun, 29 Mar 2026 07:55:30 -0400 Subject: [PATCH 3/6] fix game detail repository throwing coroutine cancellation errors --- .../scoutifyapp/data/repository/GameDetailRepository.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt index c3092a1..c78fa53 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/repository/GameDetailRepository.kt @@ -29,6 +29,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext +import kotlin.coroutines.cancellation.CancellationException import kotlin.text.toLong @@ -235,6 +236,9 @@ class GameDetailRepository( Exception("Game constants are empty") ) } + } catch (e: CancellationException) { + // rethrow so the coroutine cancels + throw e } catch (e: Exception) { Log.e("Game Constants", "Error when trying to fetch gameConstants: $e") return@withContext Result.failure(e) From cb34a0a2ee283bf62a0213eff094d36367af7c39 Mon Sep 17 00:00:00 2001 From: igor024 Date: Sun, 29 Mar 2026 08:56:25 -0400 Subject: [PATCH 4/6] disable postgame button when cachedtime > 0 --- .../com/team695/scoutifyapp/ui/screens/data/EndgameDetails.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/team695/scoutifyapp/ui/screens/data/EndgameDetails.kt b/app/src/main/java/com/team695/scoutifyapp/ui/screens/data/EndgameDetails.kt index 8b8d547..6385b2e 100644 --- a/app/src/main/java/com/team695/scoutifyapp/ui/screens/data/EndgameDetails.kt +++ b/app/src/main/java/com/team695/scoutifyapp/ui/screens/data/EndgameDetails.kt @@ -64,7 +64,9 @@ fun EndgameDetails( ) val previousTimer = formState.teleopCachedMilliseconds - currentTimer val coroutineScope = rememberCoroutineScope() - val endgameCompleted = formState.gameDetails.endgameProgress == 1f && formState.gameDetails.teleopCompleted == true + val endgameCompleted = formState.gameDetails.endgameProgress == 1f && + formState.gameDetails.teleopCompleted == true && + formState.teleopCachedMilliseconds == 0 val timers = listOf( Timer( From 6e302785e1c078e499c48506b841071b87db46af Mon Sep 17 00:00:00 2001 From: SuperMeerkat345 Date: Sun, 29 Mar 2026 11:40:33 -0400 Subject: [PATCH 5/6] changes --- app/build.gradle.kts | 1 + .../data/repository/TeamNameRepository.kt | 25 ++++++++++++------- gradle/libs.versions.toml | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f40389e..b5f7115 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -120,6 +120,7 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-reflect") implementation(libs.androidx.lifecycle.process) testImplementation(libs.junit) + testImplementation(libs.junit.jupiter) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) diff --git a/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt index 49385fe..29eead6 100644 --- a/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt +++ b/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt @@ -1,5 +1,6 @@ package com.team695.scoutifyapp.data.repository +import android.util.Log import com.team695.scoutifyapp.data.api.service.TeamNameService import com.team695.scoutifyapp.db.AppDatabase import com.team695.scoutifyapp.db.TeamNamesEntity @@ -14,18 +15,24 @@ class TeamNameRepository ( override suspend fun fetch(): Result { return withContext(Dispatchers.IO) { - val teams = service.fetchTeamNames() + try { + val teams = service.fetchTeamNames() - queries.deleteAll() + queries.deleteAll() - teams.forEach { - queries.insertTeam( - team_number = it.team_number, - team_name = it.team_name - ) - } + teams.forEach { + queries.insertTeam( + team_number = it.team_number, + team_name = it.team_name + ) + } - return@withContext Result.success(Unit) + return@withContext Result.success(Unit) + } + catch (e: Exception) { + Log.d("TeamNames", "Error when trying to fetch team names: $e") + return@withContext Result.failure(e) + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e428bb0..d5cfe2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,6 +22,7 @@ datastore = "1.2.0" adaptiveNavigation = "1.2.0" webkit = "1.15.0" lifecycleProcess = "2.10.0" +junitJupiter = "5.14.0" [libraries] accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" } @@ -56,6 +57,7 @@ androidx-datastore = { group = "androidx.datastore", name = "datastore-preferenc androidx-compose-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "adaptiveNavigation" } androidx-webkit = { group = "androidx.webkit", name = "webkit", version.ref = "webkit" } androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleProcess" } +junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junitJupiter" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From e51dbd916bdc3bf39e3f44e5b27e2f64ecac9fc6 Mon Sep 17 00:00:00 2001 From: SuperMeerkat345 Date: Sun, 29 Mar 2026 13:26:02 -0400 Subject: [PATCH 6/6] changed version to 1.0.1 --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 57f166d..687b65a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,7 +28,7 @@ configure { minSdk = 34 targetSdk = 36 versionCode = 1 - versionName = "1.0.0" + versionName = "1.0.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"