diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 33742b9..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" @@ -121,6 +121,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/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..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 @@ -37,10 +38,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 +187,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 +195,6 @@ class GameDetailRepository( if (result.data != null) { if (result.data != GameConstantsStore.constants) { - // clear all data db.transaction { db.taskQueries.clearAllTasks() @@ -233,20 +230,16 @@ 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: CancellationException) { + // rethrow so the coroutine cancels + throw e } 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/data/repository/TeamNameRepository.kt b/app/src/main/java/com/team695/scoutifyapp/data/repository/TeamNameRepository.kt index 9691ec6..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 @@ -27,11 +27,11 @@ class TeamNameRepository ( ) } - Result.success(Unit) + return@withContext Result.success(Unit) } catch (e: Exception) { Log.d("TeamNames", "Error when trying to fetch team names: $e") - Result.failure(e) + return@withContext Result.failure(e) } } } 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( 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/CommentViewModel.kt b/app/src/main/java/com/team695/scoutifyapp/ui/viewModels/CommentViewModel.kt index 48b4a0a..85efa10 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() 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, 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" }