diff --git a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt index c1a3ea2..04b4914 100644 --- a/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt +++ b/app/src/main/java/be/ugent/sel/studeez/StudeezApp.kt @@ -26,6 +26,7 @@ import be.ugent.sel.studeez.screens.profile.ProfileScreen import be.ugent.sel.studeez.screens.sign_up.SignUpScreen import be.ugent.sel.studeez.screens.splash.SplashScreen import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewScreen +import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionScreen import be.ugent.sel.studeez.ui.theme.StudeezTheme import kotlinx.coroutines.CoroutineScope @@ -130,4 +131,8 @@ fun NavGraphBuilder.studeezGraph(appState: StudeezAppstate) { composable(StudeezDestinations.EDIT_PROFILE_SCREEN) { EditProfileScreen(goBack, openAndPopUp) } + + composable(StudeezDestinations.TIMER_SELECTION_SCREEN) { + TimerSelectionScreen(open, openAndPopUp) + } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt b/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt new file mode 100644 index 0000000..f8fcebd --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/data/SelectedTimerState.kt @@ -0,0 +1,14 @@ +package be.ugent.sel.studeez.data + +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Used to communicate the SelectedTimer from the selection screen to the session screen. + * Because this is a singleton-class the view-models of both screens observe the same data. + */ +@Singleton +class SelectedTimerState @Inject constructor(){ + var selectedTimer: FunctionalTimer? = null +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/User.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/User.kt index 412100a..2fba2ce 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/User.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/User.kt @@ -1,3 +1,3 @@ package be.ugent.sel.studeez.data.local.models -data class User(val id: String = "", val isAnonymous: Boolean = true) +data class User(val id: String = "") diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt index 7cae544..5c5f396 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalCustomTimer.kt @@ -1,16 +1,16 @@ package be.ugent.sel.studeez.data.local.models.timer_functional -class FunctionalCustomTimer(studyTime: Int): FunctionalTimer(studyTime) { +class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) { override fun tick() { - if (time.getTime() == 0) { - view = "Done!" + if (time.time == 0) { + view = StudyState.DONE } else { time.minOne() } } override fun hasEnded(): Boolean { - return time.getTime() == 0 + return time.time == 0 } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt index 45eecda..1c055b5 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalEndlessTimer.kt @@ -1,6 +1,6 @@ package be.ugent.sel.studeez.data.local.models.timer_functional -class FunctionalEndlessTimer() : FunctionalTimer(0){ +class FunctionalEndlessTimer() : FunctionalTimer(0) { override fun hasEnded(): Boolean { return false diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt index ef0bf03..f18d824 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalPomodoroTimer.kt @@ -3,25 +3,25 @@ package be.ugent.sel.studeez.data.local.models.timer_functional class FunctionalPomodoroTimer( private var studyTime: Int, private var breakTime: Int, repeats: Int -): FunctionalTimer(studyTime) { +) : FunctionalTimer(studyTime) { - private var breaksRemaining = repeats - private var isInBreak = false + var breaksRemaining = repeats + var isInBreak = false override fun tick() { - if (time.getTime() == 0 && breaksRemaining == 0){ - view = "Done!" + if (time.time == 0 && breaksRemaining == 0) { + view = StudyState.DONE return } - if (time.getTime() == 0) { + if (time.time == 0) { if (isInBreak) { breaksRemaining-- - view = "Focus! ($breaksRemaining breaks remaining)" - time.setTime(studyTime) + view = StudyState.FOCUS_REMAINING + time.time = studyTime } else { - view = "Take a break!" - time.setTime(breakTime) + view = StudyState.BREAK + time.time = breakTime } isInBreak = !isInBreak } @@ -29,6 +29,6 @@ class FunctionalPomodoroTimer( } override fun hasEnded(): Boolean { - return breaksRemaining == 0 && time.getTime() == 0 + return breaksRemaining == 0 && time.time == 0 } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt index 84fc8fa..264c621 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/FunctionalTimer.kt @@ -1,17 +1,13 @@ package be.ugent.sel.studeez.data.local.models.timer_functional abstract class FunctionalTimer(initialValue: Int) { - protected val time: Time = Time(initialValue) - protected var view: String = "Focus" + val time: Time = Time(initialValue) + var view: StudyState = StudyState.FOCUS fun getHoursMinutesSeconds(): HoursMinutesSeconds { return time.getAsHMS() } - fun getViewString(): String { - return view - } - abstract fun tick() abstract fun hasEnded(): Boolean @@ -19,4 +15,9 @@ abstract class FunctionalTimer(initialValue: Int) { fun hasCurrentCountdownEnded(): Boolean { return time.getTime() == 0 } + + enum class StudyState { + FOCUS, DONE, BREAK, FOCUS_REMAINING + } + } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt index ff89516..ec7702d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_functional/Time.kt @@ -2,7 +2,7 @@ package be.ugent.sel.studeez.data.local.models.timer_functional class Time(initialTime: Int) { - private var time = initialTime + var time = initialTime fun minOne() { time-- @@ -12,14 +12,6 @@ class Time(initialTime: Int) { time++ } - fun setTime(newTime: Int) { - time = newTime - } - - fun getTime(): Int { - return time - } - fun getAsHMS(): HoursMinutesSeconds { val hours: Int = time / (60 * 60) val minutes: Int = (time / (60)) % 60 diff --git a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/BreakTimerInfo.kt b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt similarity index 97% rename from app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/BreakTimerInfo.kt rename to app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt index 735f917..18bcea6 100644 --- a/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/BreakTimerInfo.kt +++ b/app/src/main/java/be/ugent/sel/studeez/data/local/models/timer_info/PomodoroTimerInfo.kt @@ -3,7 +3,7 @@ package be.ugent.sel.studeez.data.local.models.timer_info import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer -class BreakTimerInfo( +class PomodoroTimerInfo( name: String, description: String, private val studyTime: Int, diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseAccountDAO.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseAccountDAO.kt index 434f3ce..4a490fe 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseAccountDAO.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/FirebaseAccountDAO.kt @@ -39,7 +39,7 @@ class FirebaseAccountDAO @Inject constructor( get() = callbackFlow { val listener = FirebaseAuth.AuthStateListener { auth -> - this.trySend(auth.currentUser?.let { User(it.uid, it.isAnonymous) } ?: User()) + this.trySend(auth.currentUser?.let { User(it.uid) } ?: User()) } auth.addAuthStateListener(listener) awaitClose { auth.removeAuthStateListener(listener) } diff --git a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/ToTimerConverter.kt b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/ToTimerConverter.kt index 021f9a0..ea06747 100644 --- a/app/src/main/java/be/ugent/sel/studeez/domain/implementation/ToTimerConverter.kt +++ b/app/src/main/java/be/ugent/sel/studeez/domain/implementation/ToTimerConverter.kt @@ -30,7 +30,7 @@ class ToTimerConverter { it.studyTime, it.id ) }, - TimerType.BREAK to TimerFactory { BreakTimerInfo( + TimerType.BREAK to TimerFactory { PomodoroTimerInfo( it.name, it.description, it.studyTime, diff --git a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt index a6c8290..760c814 100644 --- a/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt +++ b/app/src/main/java/be/ugent/sel/studeez/navigation/StudeezDestinations.kt @@ -5,8 +5,9 @@ object StudeezDestinations { const val SIGN_UP_SCREEN = "signup" const val LOGIN_SCREEN = "login" - const val HOME_SCREEN = "home" + const val HOME_SCREEN = "home" const val TIMER_OVERVIEW_SCREEN = "timer_overview" + const val TIMER_SELECTION_SCREEN = "timer_selection" const val SESSION_SCREEN = "session" // const val TASKS_SCREEN = "tasks" // const val SESSIONS_SCREEN = "sessions" diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt index f0f7b64..7db6f8d 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/home/HomeViewModel.kt @@ -15,14 +15,7 @@ class HomeViewModel @Inject constructor( logService: LogService ) : StudeezViewModel(logService) { - fun onStartSessionClick(openAndPopUp: (String) -> Unit) { - openAndPopUp(StudeezDestinations.SESSION_SCREEN) - } - - fun onLogoutClick(openAndPopup: (String, String) -> Unit) { - launchCatching { - accountDAO.signOut() - openAndPopup(LOGIN_SCREEN, HOME_SCREEN) - } + fun onStartSessionClick(open: (String) -> Unit) { + open(StudeezDestinations.TIMER_SELECTION_SCREEN) } } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionScreen.kt index 5077157..a458156 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionScreen.kt @@ -14,16 +14,28 @@ import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Alignment +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import be.ugent.sel.studeez.navigation.StudeezDestinations import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import be.ugent.sel.studeez.navigation.StudeezDestinations +import be.ugent.sel.studeez.R +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer.StudyState +import be.ugent.sel.studeez.resources import kotlinx.coroutines.delay +import kotlin.time.Duration.Companion.seconds var timerEnd = false @@ -31,7 +43,6 @@ var timerEnd = false fun SessionScreen( open: (String) -> Unit, openAndPopUp: (String, String) -> Unit, - viewModel: SessionViewModel = hiltViewModel() ) { val context = LocalContext.current val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) @@ -86,9 +97,9 @@ fun SessionScreen( private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: MediaPlayer) { var tikker by remember { mutableStateOf(false) } LaunchedEffect(tikker) { - delay(1000) + delay(1.seconds) viewModel.getTimer().tick() - tikker = !tikker + ticker = !ticker } if (viewModel.getTimer().hasCurrentCountdownEnded() && !viewModel.getTimer().hasEnded()) { @@ -111,8 +122,18 @@ private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: Me fontWeight = FontWeight.Bold, fontSize = 40.sp, ) + val stateString: String = when (viewModel.getTimer().view) { + StudyState.DONE -> resources().getString(R.string.state_done) + StudyState.FOCUS -> resources().getString(R.string.state_focus) + StudyState.BREAK -> resources().getString(R.string.state_take_a_break) + StudyState.FOCUS_REMAINING -> + (viewModel.getTimer() as FunctionalPomodoroTimer?)?.breaksRemaining?.let { + resources().getQuantityString(R.plurals.state_focus_remaining, it, it) + }.toString() + } + Text( - text = viewModel.getTimer().getViewString(), + text = stateString, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, fontWeight = FontWeight.Light, @@ -142,4 +163,6 @@ private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: Me } } } + + } \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt index e58f031..0e8960a 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/session/SessionViewModel.kt @@ -1,14 +1,15 @@ package be.ugent.sel.studeez.screens.session -import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.screens.StudeezViewModel +import be.ugent.sel.studeez.data.SelectedTimerState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel class SessionViewModel @Inject constructor( + private val selectedTimerState: SelectedTimerState, logService: LogService ) : StudeezViewModel(logService) { @@ -16,7 +17,7 @@ class SessionViewModel @Inject constructor( private val task : String = "No task selected" // placeholder for tasks implementation fun getTimer() : FunctionalTimer { - return timer + return selectedTimerState.selectedTimer!! } fun getTask(): String { diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt index fccbc66..66ddfad 100644 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_overview/TimerOverviewScreen.kt @@ -1,5 +1,6 @@ package be.ugent.sel.studeez.screens.timer_overview +import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -46,12 +47,12 @@ fun TimerOverviewScreen( ) { // Default Timers, cannot be edited items(viewModel.getDefaultTimers()) { - TimerEntry(timerInfo = it, canEdit = false) + TimerEntry(timerInfo = it, canDisplay = false) } // User timers, can be edited items(timers.value) { - TimerEntry(timerInfo = it, true) { timerInfo -> + TimerEntry(timerInfo = it, true, R.string.edit) { timerInfo -> viewModel.update(timerInfo) } } @@ -65,7 +66,12 @@ fun TimerOverviewScreen( } @Composable -fun TimerEntry(timerInfo: TimerInfo, canEdit: Boolean, update: (TimerInfo) -> Unit = {}) { +fun TimerEntry( + timerInfo: TimerInfo, + canDisplay: Boolean, + @StringRes buttonName: Int = -1, + buttonFunction: (TimerInfo) -> Unit = {} +) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth(), @@ -83,9 +89,9 @@ fun TimerEntry(timerInfo: TimerInfo, canEdit: Boolean, update: (TimerInfo) -> Un fontSize = 15.sp ) } - if (canEdit) { - BasicButton(R.string.edit, Modifier.card()) { - // TODO + if (canDisplay) { + BasicButton(buttonName, Modifier.card()) { + buttonFunction(timerInfo) } } diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt new file mode 100644 index 0000000..8e8df37 --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionScreen.kt @@ -0,0 +1,44 @@ +package be.ugent.sel.studeez.screens.timer_selection + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.* +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import be.ugent.sel.studeez.R +import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate +import be.ugent.sel.studeez.resources +import be.ugent.sel.studeez.screens.timer_overview.TimerEntry + +@Composable +fun TimerSelectionScreen( + open: (String) -> Unit, + openAndPopUp: (String, String) -> Unit, + viewModel: TimerSelectionViewModel = hiltViewModel() +) { + + val timers = viewModel.getAllTimers().collectAsState(initial = emptyList()) + + PrimaryScreenTemplate( + title = resources().getString(R.string.timers), + open = open, + openAndPopUp = openAndPopUp, + ) { + + LazyColumn(verticalArrangement = Arrangement.spacedBy(7.dp)) { + + // All timers + items(timers.value) { + TimerEntry( + timerInfo = it, + canDisplay = true, + buttonName = R.string.start + ) { timerInfo -> + viewModel.startSession(open, timerInfo) + } + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt new file mode 100644 index 0000000..c555bfa --- /dev/null +++ b/app/src/main/java/be/ugent/sel/studeez/screens/timer_selection/TimerSelectionViewModel.kt @@ -0,0 +1,28 @@ +package be.ugent.sel.studeez.screens.timer_selection + +import be.ugent.sel.studeez.data.SelectedTimerState +import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo +import be.ugent.sel.studeez.domain.LogService +import be.ugent.sel.studeez.domain.TimerDAO +import be.ugent.sel.studeez.navigation.StudeezDestinations +import be.ugent.sel.studeez.screens.StudeezViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +@HiltViewModel +class TimerSelectionViewModel @Inject constructor( + private val timerDAO: TimerDAO, + private val selectedTimerState: SelectedTimerState, + logService: LogService +) : StudeezViewModel(logService) { + + fun getAllTimers() : Flow> { + return timerDAO.getAllTimers() + } + + fun startSession(open: (String) -> Unit, timerInfo: TimerInfo) { + selectedTimerState.selectedTimer = timerInfo.getFunctionalTimer() + open(StudeezDestinations.SESSION_SCREEN) + } +} \ No newline at end of file diff --git a/app/src/main/java/be/ugent/sel/studeez/screens/timers/TimerScreen.kt b/app/src/main/java/be/ugent/sel/studeez/screens/timers/TimerScreen.kt deleted file mode 100644 index b7ca484..0000000 --- a/app/src/main/java/be/ugent/sel/studeez/screens/timers/TimerScreen.kt +++ /dev/null @@ -1,4 +0,0 @@ -package be.ugent.sel.studeez.screens.timers - -class TimerScreen { -} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b48d7f8..39abda6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,6 +13,7 @@ Cancel Go back Next + Start Success! @@ -63,6 +64,14 @@ Timers Edit Add timer + Focus! + + Focus one more time! + Focus! (%d break remaining) + Focus! (%d breaks remaining) + + Done! + Take a break! Settings diff --git a/app/src/test/java/be/ugent/sel/studeez/ExampleUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/ExampleUnitTest.kt deleted file mode 100644 index 4ff9e1c..0000000 --- a/app/src/test/java/be/ugent/sel/studeez/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package be.ugent.sel.studeez - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalCustomTimerUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalCustomTimerUnitTest.kt new file mode 100644 index 0000000..2daa61e --- /dev/null +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalCustomTimerUnitTest.kt @@ -0,0 +1,44 @@ +package be.ugent.sel.studeez.timer_functional + +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import org.junit.Assert +import org.junit.Test + +class FunctionalCustomTimerUnitTest : FunctionalTimerUnitTest() { + override fun setTimer() { + timer = FunctionalCustomTimer(time) + } + + @Test + override fun testOneTick() { + timer.tick() + Assert.assertEquals( + time - 1, + timer.time.time, + ) + } + + @Test + override fun multipleTicks() { + val n = 10 + for (i in 1..n) { + timer.tick() + } + Assert.assertEquals( + time - n, + timer.time.time, + ) + } + + @Test + override fun testEnded() { + timer = FunctionalCustomTimer(0) + timer.tick() + Assert.assertTrue(timer.hasEnded()) + Assert.assertEquals( + FunctionalTimer.StudyState.DONE, + timer.view + ) + } +} \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalEndlessTimerUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalEndlessTimerUnitTest.kt new file mode 100644 index 0000000..b83d436 --- /dev/null +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalEndlessTimerUnitTest.kt @@ -0,0 +1,46 @@ +package be.ugent.sel.studeez.timer_functional + +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import org.junit.Assert +import org.junit.Test + +class FunctionalEndlessTimerUnitTest : FunctionalTimerUnitTest() { + override fun setTimer() { + timer = FunctionalEndlessTimer() + } + + @Test + override fun testOneTick() { + timer.tick() + Assert.assertEquals( + 1, + timer.time.time + ) + } + + @Test + override fun multipleTicks() { + val n = 10 + for (i in 1..n) { + timer.tick() + } + Assert.assertEquals( + n, + timer.time.time + ) + } + + @Test + override fun testEnded() { + val n = 1000 + for (i in 1..n) { + timer.tick() + Assert.assertFalse(timer.hasEnded()) + Assert.assertEquals( + FunctionalTimer.StudyState.FOCUS, + timer.view + ) + } + } +} \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt new file mode 100644 index 0000000..a49d2f7 --- /dev/null +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalPomodoroTimerUnitTest.kt @@ -0,0 +1,98 @@ +package be.ugent.sel.studeez.timer_functional + +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import org.junit.Assert +import org.junit.Test + +class FunctionalPomodoroTimerUnitTest : FunctionalTimerUnitTest() { + private val breakTime = 10 + private val breaks = 2 + override val hours = 0 + override val minutes = 0 + override val seconds = 10 + private lateinit var pomodoroTimer: FunctionalPomodoroTimer + + override fun setTimer() { + pomodoroTimer = FunctionalPomodoroTimer(time, breakTime, breaks) + } + + @Test + override fun testOneTick() { + pomodoroTimer.tick() + Assert.assertEquals( + time - 1, + pomodoroTimer.time.time, + ) + Assert.assertFalse(pomodoroTimer.isInBreak) + Assert.assertEquals( + breaks, + pomodoroTimer.breaksRemaining, + ) + Assert.assertEquals( + FunctionalTimer.StudyState.FOCUS, + pomodoroTimer.view, + ) + } + + @Test + override fun multipleTicks() { + val n = 10 + for (i in 1..n) { + pomodoroTimer.tick() + } + Assert.assertEquals( + time - n, + pomodoroTimer.time.time + ) + } + + @Test + override fun testEnded() { + pomodoroTimer = FunctionalPomodoroTimer(0, 0, 0) + pomodoroTimer.tick() + Assert.assertTrue(pomodoroTimer.hasEnded()) + Assert.assertEquals( + FunctionalTimer.StudyState.DONE, + pomodoroTimer.view, + ) + } + + @Test + fun switchToBreak() { + for (i in 0..10) { + pomodoroTimer.tick() + } + Assert.assertFalse(pomodoroTimer.hasEnded()) + Assert.assertTrue(pomodoroTimer.isInBreak) + Assert.assertEquals( + FunctionalTimer.StudyState.BREAK, + pomodoroTimer.view + ) + } + + @Test + fun switchToStudying() { + for (i in 0..time) { + pomodoroTimer.tick() + } + Assert.assertTrue(pomodoroTimer.isInBreak) + Assert.assertEquals( + FunctionalTimer.StudyState.BREAK, + pomodoroTimer.view + ) + for (i in 0..breakTime) { + pomodoroTimer.tick() + } + Assert.assertFalse(pomodoroTimer.isInBreak) + val breaksRemaining = breaks - 1 + Assert.assertEquals( + breaksRemaining, + pomodoroTimer.breaksRemaining + ) + Assert.assertEquals( + FunctionalTimer.StudyState.FOCUS_REMAINING, + pomodoroTimer.view + ) + } +} \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalTimerUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalTimerUnitTest.kt new file mode 100644 index 0000000..4d26d06 --- /dev/null +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/FunctionalTimerUnitTest.kt @@ -0,0 +1,33 @@ +package be.ugent.sel.studeez.timer_functional + +import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer +import org.junit.Before +import org.junit.Test + +abstract class FunctionalTimerUnitTest { + protected lateinit var timer: FunctionalTimer + protected open val hours = 4 + protected open val minutes = 20 + protected open val seconds = 39 + protected var time: Int = 0 + + @Before + fun setup() { + time = seconds + minutes * 60 + hours * 60 * 60 + setTimer() + } + + /** + * The timer-property should be set to the right implementation in this method. + */ + abstract fun setTimer() + + @Test + abstract fun testOneTick() + + @Test + abstract fun multipleTicks() + + @Test + abstract fun testEnded() +} \ No newline at end of file diff --git a/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt b/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt new file mode 100644 index 0000000..86fdce8 --- /dev/null +++ b/app/src/test/java/be/ugent/sel/studeez/timer_functional/TimeUnitTest.kt @@ -0,0 +1,81 @@ +package be.ugent.sel.studeez.timer_functional + +import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds +import be.ugent.sel.studeez.data.local.models.timer_functional.Time +import org.junit.Assert +import org.junit.Before +import org.junit.Test + +class TimeUnitTest { + private val hours = 4 + private val minutes = 20 + private val seconds = 39 + private val time: Time = Time(seconds + minutes * 60 + hours * 60 * 60) + + @Before + fun setup() { + + } + + @Test + fun formatTime() { + Assert.assertEquals( + HoursMinutesSeconds( + hours.toString().padStart(2, '0'), + minutes.toString().padStart(2, '0'), + seconds.toString().padStart(2, '0'), + ), + time.getAsHMS(), + ) + } + + @Test + fun getTime() { + Assert.assertEquals( + seconds + minutes * 60 + hours * 60 * 60, + time.time, + ) + } + + @Test + fun minOne() { + time.minOne() + Assert.assertEquals( + (seconds + minutes * 60 + hours * 60 * 60) - 1, + time.time, + ) + } + + @Test + fun plusOne() { + time.plusOne() + Assert.assertEquals( + (seconds + minutes * 60 + hours * 60 * 60) + 1, + time.time, + ) + } + + @Test + fun minMultiple() { + val n = 10 + for (i in 1 .. n) { + time.minOne() + } + Assert.assertEquals( + (seconds + minutes * 60 + hours * 60 * 60) - n, + time.time, + ) + } + + @Test + fun plusMultiple() { + val n = 10 + for (i in 1 .. n) { + time.plusOne() + } + Assert.assertEquals( + (seconds + minutes * 60 + hours * 60 * 60) + n, + time.time, + ) + } +} \ No newline at end of file