1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 07:39:09 -05:00

Add lesson time left display (#550)

This commit is contained in:
Dominik Korsa 2020-05-20 16:06:24 +02:00 committed by GitHub
parent 29226dd93e
commit b95b529015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 309 additions and 33 deletions

View File

@ -75,6 +75,9 @@ class PreferencesRepository @Inject constructor(
val showWholeClassPlan: String
get() = getString(R.string.pref_key_timetable_show_whole_class, R.string.pref_default_timetable_show_whole_class)
val showTimetableTimers: Boolean
get() = getBoolean(R.string.pref_key_timetable_show_timers, R.bool.pref_default_timetable_show_timers)
private fun getString(id: Int, default: Int) = getString(context.getString(id), default)
private fun getString(id: String, default: Int) = sharedPref.getString(id, context.getString(default)) ?: context.getString(default)

View File

@ -179,6 +179,8 @@ class LoginRecoverFragment :
loadDataWithBaseURL(url, html, "text/html", "UTF-8", null)
addJavascriptInterface(object {
@Suppress("UNUSED")
@JavascriptInterface
fun captchaCallback(reCaptchaResponse: String) {
activity?.runOnUiThread {

View File

@ -2,6 +2,8 @@ package io.github.wulkanowy.ui.modules.timetable
import android.graphics.Paint
import android.view.LayoutInflater
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
@ -10,8 +12,16 @@ import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.databinding.ItemTimetableBinding
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.isJustFinished
import io.github.wulkanowy.utils.isShowTimeUntil
import io.github.wulkanowy.utils.left
import io.github.wulkanowy.utils.toFormattedString
import io.github.wulkanowy.utils.until
import org.threeten.bp.LocalDateTime
import timber.log.Timber
import java.util.Timer
import javax.inject.Inject
import kotlin.concurrent.timer
class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
@ -20,12 +30,28 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
ITEM_SMALL(2)
}
var items = emptyList<Timetable>()
var items = mutableListOf<Timetable>()
set(value) {
field = value
resetTimers()
}
var onClickListener: (Timetable) -> Unit = {}
var showWholeClassPlan: String = "no"
var showTimers: Boolean = false
private val timers = mutableMapOf<Int, Timer>()
private fun resetTimers() {
Timber.d("Timetable timers reset")
with(timers) {
forEach { (_, timer) -> timer.cancel() }
clear()
}
}
override fun getItemCount() = items.size
override fun getItemViewType(position: Int) = when {
@ -43,11 +69,16 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
}
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.onDetachedFromRecyclerView(recyclerView)
resetTimers()
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val lesson = items[position]
when (holder) {
is ItemViewHolder -> bindNormalView(holder.binding, lesson)
is ItemViewHolder -> bindNormalView(holder.binding, lesson, position)
is SmallItemViewHolder -> bindSmallView(holder.binding, lesson)
}
}
@ -68,7 +99,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
}
}
private fun bindNormalView(binding: ItemTimetableBinding, lesson: Timetable) {
private fun bindNormalView(binding: ItemTimetableBinding, lesson: Timetable, position: Int) {
with(binding) {
timetableItemNumber.text = lesson.number.toString()
timetableItemSubject.text = lesson.subject
@ -81,10 +112,74 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
bindNormalDescription(binding, lesson)
bindNormalColors(binding, lesson)
if (lesson.isStudentPlan && showTimers) timers[position] = timer(period = 1000) {
root.post { updateTimeLeft(binding, lesson, position) }
} else {
// reset item on set changed
timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = GONE
}
root.setOnClickListener { onClickListener(lesson) }
}
}
private fun getPreviousLesson(position: Int): LocalDateTime? {
return items.filter { it.isStudentPlan }.getOrNull(position - 1 - items.filterIndexed { i, item -> i < position && !item.isStudentPlan }.size)?.let {
if (!it.canceled && it.isStudentPlan) it.end
else null
}
}
private fun updateTimeLeft(binding: ItemTimetableBinding, lesson: Timetable, position: Int) {
with(binding) {
when {
// before lesson
lesson.isShowTimeUntil(getPreviousLesson(position)) -> {
Timber.d("Show time until lesson: $position")
timetableItemTimeLeft.visibility = GONE
with(timetableItemTimeUntil) {
visibility = VISIBLE
text = context.getString(R.string.timetable_time_until,
if (lesson.until.seconds <= 60) {
context.getString(R.string.timetable_seconds, lesson.until.seconds.toString(10))
} else {
context.getString(R.string.timetable_minutes, lesson.until.toMinutes().toString(10))
}
)
}
}
// after lesson start
lesson.left != null -> {
Timber.d("Show time left lesson: $position")
timetableItemTimeUntil.visibility = GONE
with(timetableItemTimeLeft) {
visibility = VISIBLE
text = context.getString(
R.string.timetable_time_left,
if (lesson.left!!.seconds < 60) {
context.getString(R.string.timetable_seconds, lesson.left?.seconds?.toString(10))
} else {
context.getString(R.string.timetable_minutes, lesson.left?.toMinutes()?.toString(10))
}
)
}
}
// right after lesson finish
lesson.isJustFinished -> {
Timber.d("Show just finished lesson: $position")
timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = VISIBLE
timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished)
}
else -> {
timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = GONE
}
}
}
}
private fun bindSubjectStyle(subjectView: TextView, lesson: Timetable) {
subjectView.paintFlags = if (lesson.canceled) subjectView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else subjectView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
@ -93,20 +188,20 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
private fun bindSmallDescription(binding: ItemTimetableSmallBinding, lesson: Timetable) {
with(binding) {
if (lesson.info.isNotBlank() && !lesson.changes) {
timetableSmallItemDescription.visibility = android.view.View.VISIBLE
timetableSmallItemDescription.visibility = VISIBLE
timetableSmallItemDescription.text = lesson.info
timetableSmallItemRoom.visibility = android.view.View.GONE
timetableSmallItemTeacher.visibility = android.view.View.GONE
timetableSmallItemRoom.visibility = GONE
timetableSmallItemTeacher.visibility = GONE
timetableSmallItemDescription.setTextColor(root.context.getThemeAttrColor(
if (lesson.canceled) R.attr.colorPrimary
else R.attr.colorTimetableChange
))
} else {
timetableSmallItemDescription.visibility = android.view.View.GONE
timetableSmallItemRoom.visibility = android.view.View.VISIBLE
timetableSmallItemTeacher.visibility = android.view.View.VISIBLE
timetableSmallItemDescription.visibility = GONE
timetableSmallItemRoom.visibility = VISIBLE
timetableSmallItemTeacher.visibility = VISIBLE
}
}
}
@ -114,20 +209,20 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
private fun bindNormalDescription(binding: ItemTimetableBinding, lesson: Timetable) {
with(binding) {
if (lesson.info.isNotBlank() && !lesson.changes) {
timetableItemDescription.visibility = android.view.View.VISIBLE
timetableItemDescription.visibility = VISIBLE
timetableItemDescription.text = lesson.info
timetableItemRoom.visibility = android.view.View.GONE
timetableItemTeacher.visibility = android.view.View.GONE
timetableItemRoom.visibility = GONE
timetableItemTeacher.visibility = GONE
timetableItemDescription.setTextColor(root.context.getThemeAttrColor(
if (lesson.canceled) R.attr.colorPrimary
else R.attr.colorTimetableChange
))
} else {
timetableItemDescription.visibility = android.view.View.GONE
timetableItemRoom.visibility = android.view.View.VISIBLE
timetableItemTeacher.visibility = android.view.View.VISIBLE
timetableItemDescription.visibility = GONE
timetableItemRoom.visibility = VISIBLE
timetableItemTeacher.visibility = VISIBLE
}
}
}

View File

@ -86,9 +86,10 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
else false
}
override fun updateData(data: List<Timetable>, showWholeClassPlanType: String) {
override fun updateData(data: List<Timetable>, showWholeClassPlanType: String, showTimetableTimers: Boolean) {
with(timetableAdapter) {
items = data
items = data.toMutableList()
showTimers = showTimetableTimers
showWholeClassPlan = showWholeClassPlanType
notifyDataSetChanged()
}
@ -96,7 +97,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
override fun clearData() {
with(timetableAdapter) {
items = emptyList()
items = mutableListOf()
notifyDataSetChanged()
}
}

View File

@ -149,7 +149,7 @@ class TimetablePresenter @Inject constructor(
.subscribe({
Timber.i("Loading timetable result: Success")
view?.apply {
updateData(it, prefRepository.showWholeClassPlan)
updateData(it, prefRepository.showWholeClassPlan, prefRepository.showTimetableTimers)
showEmpty(it.isEmpty())
showErrorView(false)
showContent(it.isNotEmpty())

View File

@ -12,7 +12,7 @@ interface TimetableView : BaseView {
fun initView()
fun updateData(data: List<Timetable>, showWholeClassPlanType: String)
fun updateData(data: List<Timetable>, showWholeClassPlanType: String, showTimetableTimers: Boolean)
fun updateNavigationDay(date: String)

View File

@ -0,0 +1,29 @@
package io.github.wulkanowy.utils
import io.github.wulkanowy.data.db.entities.Timetable
import org.threeten.bp.Duration
import org.threeten.bp.Duration.between
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalDateTime.now
fun Timetable.isShowTimeUntil(previousLessonEnd: LocalDateTime?) = when {
!isStudentPlan -> false
canceled -> false
now().isAfter(start) -> false
previousLessonEnd != null && now().isBefore(previousLessonEnd) -> false
else -> between(now(), start) <= Duration.ofMinutes(60)
}
inline val Timetable.left: Duration?
get() = when {
canceled -> null
!isStudentPlan -> null
end.isAfter(now()) && start.isBefore(now()) -> between(now(), end)
else -> null
}
inline val Timetable.until: Duration
get() = between(now(), start)
inline val Timetable.isJustFinished: Boolean
get() = end.isBefore(now()) && end.plusSeconds(15).isAfter(now()) && !canceled

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?colorPrimary"/>
<corners android:radius="3dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

View File

@ -29,12 +29,12 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="40dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@id/timetableItemTimeBarrier"
app:layout_constraintStart_toEndOf="@+id/timetableItemTimeStart"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem" />
@ -106,4 +106,56 @@
tools:text="Lekcja odwołana: uczniowie zwolnieni do domu"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/timetableItemTimeBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="timetableItemTimeUntil,timetableItemTimeLeft" />
<TextView
android:id="@+id/timetableItemTimeUntil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/timetableItemSubject"
android:layout_alignBottom="@id/timetableItemSubject"
android:layout_alignParentEnd="true"
android:layout_marginStart="4dp"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="?colorPrimary"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="za 15 min"
tools:visibility="gone" />
<TextView
android:id="@+id/timetableItemTimeLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/timetableItemSubject"
android:layout_alignBottom="@id/timetableItemSubject"
android:layout_alignParentEnd="true"
android:layout_marginStart="4dp"
android:background="@drawable/background_timetable_time_left"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:includeFontPadding="false"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:textColor="?colorOnPrimary"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="jeszcze 15 min"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -121,6 +121,11 @@
<string name="timetable_time">Godziny</string>
<string name="timetable_changes">Zmiany</string>
<string name="timetable_no_items">Brak lekcji w tym dniu</string>
<string name="timetable_minutes">%s min</string>
<string name="timetable_seconds">%s sek</string>
<string name="timetable_time_left">jeszcze %1$s</string>
<string name="timetable_time_until">za %1$s</string>
<string name="timetable_finished">Zakończona</string>
<string name="timetable_now">Teraz: %s</string>
<string name="timetable_next">Za chwilę: %s</string>
<string name="timetable_later">Później: %s</string>
@ -317,6 +322,7 @@
<string name="pref_view_app_theme">Motyw aplikacji</string>
<string name="pref_view_expand_grade">Rozwiń oceny</string>
<string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string>
<string name="pref_view_timetable_show_timers">Oznaczaj bieżącą lekcję na planie</string>
<string name="pref_view_timetable_show_whole_class">Pokazuj lekcje całej klasy</string>
<string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>
<string name="pref_view_app_language">Język aplikacji</string>

View File

@ -19,4 +19,5 @@
<string name="pref_default_grade_modifier_minus">0.33</string>
<bool name="pref_default_fill_message_content">true</bool>
<string name="pref_default_timetable_show_whole_class">no</string>
<bool name="pref_default_timetable_show_timers">false</bool>
</resources>

View File

@ -20,4 +20,5 @@
<string name="pref_key_grade_modifier_minus">grade_modifier_minus</string>
<string name="pref_key_fill_message_content">fill_message_content</string>
<string name="pref_key_timetable_show_whole_class">show_whole_class_plan</string>
<string name="pref_key_timetable_show_timers">timetable_show_timers</string>
</resources>

View File

@ -130,6 +130,11 @@
<string name="timetable_time">Hours</string>
<string name="timetable_changes">Changes</string>
<string name="timetable_no_items">No lessons this day</string>
<string name="timetable_minutes">%s min</string>
<string name="timetable_seconds">%s sec</string>
<string name="timetable_time_left">%1$s left</string>
<string name="timetable_time_until">in %1$s</string>
<string name="timetable_finished">Finished</string>
<string name="timetable_now">Now: %s</string>
<string name="timetable_next">Next: %s</string>
<string name="timetable_later">Later: %s</string>
@ -352,6 +357,7 @@
<string name="pref_view_present">Show presence in attendance</string>
<string name="pref_view_app_theme">Application theme</string>
<string name="pref_view_expand_grade">Expand grades</string>
<string name="pref_view_timetable_show_timers">Mark current lesson in timetable</string>
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
<string name="pref_view_timetable_show_whole_class">Show whole class lessons</string>
<string name="pref_view_grade_color_scheme">Grades color scheme</string>

View File

@ -29,6 +29,11 @@
app:iconSpaceReserved="false"
app:key="@string/pref_key_expand_grade"
app:title="@string/pref_view_expand_grade" />
<SwitchPreferenceCompat
app:defaultValue="@bool/pref_default_timetable_show_timers"
app:iconSpaceReserved="false"
app:title="@string/pref_view_timetable_show_timers"
app:key="@string/pref_key_timetable_show_timers" />
<SwitchPreferenceCompat
app:defaultValue="@bool/pref_default_grade_statistics_list"
app:iconSpaceReserved="false"

View File

@ -1,9 +1,11 @@
package io.github.wulkanowy.data.repositories
package io.github.wulkanowy
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.sdk.Sdk
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.LocalDateTime.now
fun createSemesterEntity(diaryId: Int, semesterId: Int, start: LocalDate, end: LocalDate, semesterName: Int = 1): Semester {
@ -45,3 +47,28 @@ fun getStudentEntity(mode: Sdk.Mode = Sdk.Mode.API): Student {
userLoginId = 0
)
}
fun getTimetableEntity(
isStudentPlan: Boolean = false,
canceled: Boolean = false,
start: LocalDateTime = now(),
end: LocalDateTime = now()
) = Timetable(
studentId = 0,
subject = "",
number = 0,
diaryId = 0,
canceled = canceled,
changes = false,
date = LocalDate.now(),
end = end,
group = "",
info = "",
isStudentPlan = isStudentPlan,
room = "",
roomOld = "",
start = start,
subjectOld = "",
teacher = "",
teacherOld = ""
)

View File

@ -1,8 +1,7 @@
package io.github.wulkanowy.data.repositories.attendance
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Attendance
import io.github.wulkanowy.utils.init

View File

@ -1,7 +1,7 @@
package io.github.wulkanowy.data.repositories.completedlessons
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.CompletedLesson
import io.github.wulkanowy.utils.init

View File

@ -1,7 +1,7 @@
package io.github.wulkanowy.data.repositories.exam
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Exam
import io.github.wulkanowy.utils.init

View File

@ -1,7 +1,7 @@
package io.github.wulkanowy.data.repositories.gradestatistics
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.GradePointsStatistics
import io.github.wulkanowy.sdk.pojo.GradeStatistics

View File

@ -1,6 +1,6 @@
package io.github.wulkanowy.data.repositories.luckynumber
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.init
import io.mockk.MockKAnnotations

View File

@ -4,7 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.db.entities.MobileDevice
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.reactivex.Maybe
import io.reactivex.Single
import org.junit.Before

View File

@ -4,7 +4,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.Inter
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.UnitTestInternetObservingStrategy
import io.github.wulkanowy.data.repositories.createSemesterEntity
import io.github.wulkanowy.createSemesterEntity
import io.reactivex.Maybe
import io.reactivex.Single
import org.junit.Assert.assertEquals

View File

@ -1,7 +1,7 @@
package io.github.wulkanowy.data.repositories.timetable
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.repositories.getStudentEntity
import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Timetable
import io.mockk.MockKAnnotations

View File

@ -3,9 +3,9 @@ package io.github.wulkanowy.ui.modules.grade
import io.github.wulkanowy.data.db.entities.Grade
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.createSemesterEntity
import io.github.wulkanowy.data.repositories.grade.GradeRepository
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
import io.github.wulkanowy.createSemesterEntity
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
import io.github.wulkanowy.sdk.Sdk
import io.reactivex.Single

View File

@ -0,0 +1,43 @@
package io.github.wulkanowy.utils
import io.github.wulkanowy.getTimetableEntity
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.threeten.bp.LocalDateTime.now
class TimetableExtensionTest {
@Test
fun isShowTimeUntil() {
assertFalse(getTimetableEntity().isShowTimeUntil(null))
assertFalse(getTimetableEntity(isStudentPlan = false).isShowTimeUntil(null))
assertFalse(getTimetableEntity(isStudentPlan = true, canceled = true).isShowTimeUntil(null))
assertFalse(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().minusSeconds(1)).isShowTimeUntil(null))
assertFalse(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().plusMinutes(5)).isShowTimeUntil(now().plusMinutes(5)))
assertFalse(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().plusMinutes(61)).isShowTimeUntil(now().minusMinutes(5)))
assertTrue(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().plusMinutes(60)).isShowTimeUntil(now().minusMinutes(5)))
assertTrue(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().plusMinutes(60)).isShowTimeUntil(null))
assertFalse(getTimetableEntity(isStudentPlan = true, canceled = false, start = now().minusSeconds(1)).isShowTimeUntil(null))
}
@Test
fun getLeft() {
assertEquals(null, getTimetableEntity(canceled = true).left)
assertEquals(null, getTimetableEntity(start = now().plusMinutes(5), end = now().plusMinutes(50)).left)
assertEquals(null, getTimetableEntity(start = now().minusMinutes(1), end = now().plusMinutes(44), isStudentPlan = false).left)
assertNotEquals(null, getTimetableEntity(start = now().minusMinutes(1), end = now().plusMinutes(44), isStudentPlan = true).left)
}
@Test
fun isJustFinished() {
assertFalse(getTimetableEntity(end = now().minusSeconds(16)).isJustFinished)
assertTrue(getTimetableEntity(end = now().minusSeconds(14)).isJustFinished)
assertTrue(getTimetableEntity(end = now().minusSeconds(1)).isJustFinished)
assertFalse(getTimetableEntity(end = now().plusSeconds(1)).isJustFinished)
}
}