From 1afd1fba3e7edd32cfdaa04a3cc64a51abd4ae2a Mon Sep 17 00:00:00 2001 From: TheSaminator Date: Wed, 9 Feb 2022 10:14:27 -0500 Subject: [PATCH] Make datetime storage more consistent --- .../kotlin/starshipfights/game/util.kt | 3 -- .../kotlin/starshipfights/auth/providers.kt | 18 +++++++----- .../kotlin/starshipfights/auth/utils.kt | 8 ++--- .../data/admiralty/battle_records.kt | 1 + .../starshipfights/data/auth/user_sessions.kt | 4 ++- .../kotlin/starshipfights/game/server_game.kt | 27 ++++++++++++----- .../starshipfights/game/server_matchmaking.kt | 1 - .../kotlin/starshipfights/info/views_user.kt | 29 +++++++++++++------ 8 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/commonMain/kotlin/starshipfights/game/util.kt b/src/commonMain/kotlin/starshipfights/game/util.kt index 416bf47..b43515f 100644 --- a/src/commonMain/kotlin/starshipfights/game/util.kt +++ b/src/commonMain/kotlin/starshipfights/game/util.kt @@ -5,10 +5,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow import kotlinx.coroutines.isActive import kotlinx.serialization.json.Json -import kotlin.math.abs import kotlin.math.roundToInt -import kotlin.math.sign -import kotlin.math.sqrt val jsonSerializer = Json { classDiscriminator = "\$ktClass" diff --git a/src/jvmMain/kotlin/starshipfights/auth/providers.kt b/src/jvmMain/kotlin/starshipfights/auth/providers.kt index 3810710..4bc3359 100644 --- a/src/jvmMain/kotlin/starshipfights/auth/providers.kt +++ b/src/jvmMain/kotlin/starshipfights/auth/providers.kt @@ -33,6 +33,8 @@ import starshipfights.data.createNonce import starshipfights.game.AdmiralRank import starshipfights.game.Faction import starshipfights.info.* +import java.time.Instant +import java.time.temporal.ChronoUnit interface AuthProvider { fun installApplication(app: Application) = Unit @@ -167,8 +169,8 @@ interface AuthProvider { get("/logout") { call.getUserSession()?.let { sess -> launch { - val newTime = System.currentTimeMillis() - 100 - UserSession.update(UserSession::id eq sess.id, setValue(UserSession::expirationMillis, newTime)) + val newTime = Instant.now().minusMillis(100) + UserSession.update(UserSession::id eq sess.id, setValue(UserSession::expiration, newTime)) } } @@ -180,8 +182,8 @@ interface AuthProvider { val id = Id(call.parameters.getOrFail("id")) call.getUserSession()?.let { sess -> launch { - val newTime = System.currentTimeMillis() - 100 - UserSession.update(and(UserSession::id eq id, UserSession::user eq sess.user), setValue(UserSession::expirationMillis, newTime)) + val newTime = Instant.now().minusMillis(100) + UserSession.update(and(UserSession::id eq id, UserSession::user eq sess.user), setValue(UserSession::expiration, newTime)) } } @@ -191,8 +193,8 @@ interface AuthProvider { get("/logout-all") { call.getUserSession()?.let { sess -> launch { - val newTime = System.currentTimeMillis() - 100 - UserSession.update(and(UserSession::user eq sess.user, UserSession::id ne sess.id), setValue(UserSession::expirationMillis, newTime)) + val newTime = Instant.now().minusMillis(100) + UserSession.update(and(UserSession::user eq sess.user, UserSession::id ne sess.id), setValue(UserSession::expiration, newTime)) } } @@ -239,7 +241,7 @@ object TestAuthProvider : AuthProvider { user = user.id, clientAddresses = listOf(originAddress), userAgent = userAgent, - expirationMillis = System.currentTimeMillis() + 3_600_000L + expiration = Instant.now().plus(1, ChronoUnit.DAYS) ).also { UserSession.put(it) } @@ -400,7 +402,7 @@ class ProductionAuthProvider(val discordLogin: DiscordLogin) : AuthProvider { user = user.id, clientAddresses = listOf(call.request.origin.remoteHost), userAgent = userAgent, - expirationMillis = System.currentTimeMillis() + EXPIRATION_TIME + expiration = Instant.now().plus(1, ChronoUnit.DAYS) ) launch { User.put(user) } diff --git a/src/jvmMain/kotlin/starshipfights/auth/utils.kt b/src/jvmMain/kotlin/starshipfights/auth/utils.kt index 5be91d8..35cc755 100644 --- a/src/jvmMain/kotlin/starshipfights/auth/utils.kt +++ b/src/jvmMain/kotlin/starshipfights/auth/utils.kt @@ -7,15 +7,15 @@ import io.ktor.sessions.* import starshipfights.data.Id import starshipfights.data.auth.User import starshipfights.data.auth.UserSession - -const val EXPIRATION_TIME = 86_400_000 +import java.time.Instant +import java.time.temporal.ChronoUnit suspend fun Id.resolve(userAgent: String) = UserSession.get(this)?.takeIf { session -> - session.userAgent == userAgent && session.expirationMillis > System.currentTimeMillis() + session.userAgent == userAgent && session.expiration.isAfter(Instant.now()) } suspend fun UserSession.renewed(clientAddress: String) = copy( - expirationMillis = System.currentTimeMillis() + EXPIRATION_TIME, + expiration = Instant.now().plus(1, ChronoUnit.DAYS), clientAddresses = if (clientAddresses.last() != clientAddress) clientAddresses + clientAddress else clientAddresses ).also { UserSession.put(it) } diff --git a/src/jvmMain/kotlin/starshipfights/data/admiralty/battle_records.kt b/src/jvmMain/kotlin/starshipfights/data/admiralty/battle_records.kt index f248eeb..f510b00 100644 --- a/src/jvmMain/kotlin/starshipfights/data/admiralty/battle_records.kt +++ b/src/jvmMain/kotlin/starshipfights/data/admiralty/battle_records.kt @@ -16,6 +16,7 @@ data class BattleRecord( @SerialName("_id") override val id: Id = Id(), + val whenStarted: @Contextual Instant, val whenEnded: @Contextual Instant, val hostUser: Id, diff --git a/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt b/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt index 019e1e3..2be729a 100644 --- a/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt +++ b/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt @@ -1,12 +1,14 @@ package starshipfights.data.auth import io.ktor.auth.* +import kotlinx.serialization.Contextual import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import starshipfights.data.DataDocument import starshipfights.data.DocumentTable import starshipfights.data.Id import starshipfights.data.invoke +import java.time.Instant @Serializable data class User( @@ -40,7 +42,7 @@ data class UserSession( val user: Id, val clientAddresses: List, val userAgent: String, - val expirationMillis: Long + val expiration: @Contextual Instant ) : DataDocument, Principal { companion object Table : DocumentTable by DocumentTable.create({ index(UserSession::user) diff --git a/src/jvmMain/kotlin/starshipfights/game/server_game.kt b/src/jvmMain/kotlin/starshipfights/game/server_game.kt index 86a7d61..2651825 100644 --- a/src/jvmMain/kotlin/starshipfights/game/server_game.kt +++ b/src/jvmMain/kotlin/starshipfights/game/server_game.kt @@ -33,13 +33,16 @@ object GameManager { val session = GameSession(gameState) DocumentTable.launch { + session.gameStart.join() + val startedAt = Instant.now() + val end = session.gameEnd.await() + val endedAt = Instant.now() - val now = Instant.now() - val destroyedShipStatus = DrydockStatus.InRepair(now.plus(12, ChronoUnit.HOURS)) - val damagedShipStatus = DrydockStatus.InRepair(now.plus(9, ChronoUnit.HOURS)) - val intactShipStatus = DrydockStatus.InRepair(now.plus(6, ChronoUnit.HOURS)) - val escapedShipStatus = DrydockStatus.InRepair(now.plus(3, ChronoUnit.HOURS)) + val destroyedShipStatus = DrydockStatus.InRepair(endedAt.plus(12, ChronoUnit.HOURS)) + val damagedShipStatus = DrydockStatus.InRepair(endedAt.plus(9, ChronoUnit.HOURS)) + val intactShipStatus = DrydockStatus.InRepair(endedAt.plus(6, ChronoUnit.HOURS)) + val escapedShipStatus = DrydockStatus.InRepair(endedAt.plus(3, ChronoUnit.HOURS)) val shipWrecks = session.state.value.destroyedShips val destroyedShips = shipWrecks.filterValues { !it.isEscape }.keys.map { it.reinterpret() }.toSet() @@ -61,7 +64,8 @@ object GameManager { } val battleRecord = BattleRecord( - whenEnded = now, + whenStarted = startedAt, + whenEnded = endedAt, hostUser = hostInfo.user.id.reinterpret(), guestUser = guestInfo.user.id.reinterpret(), @@ -114,7 +118,16 @@ class GameSession(gameState: GameState) { true } ?: false } - }.also { if (!it) onPacket(player.other, PlayerAction.TimeOut) } + }.also { + if (it) + _gameStart.complete() + else + onPacket(player.other, PlayerAction.TimeOut) + } + + private val _gameStart = Job() + val gameStart: Job + get() = _gameStart private val stateMutable = MutableStateFlow(gameState) private val stateMutex = Mutex() diff --git a/src/jvmMain/kotlin/starshipfights/game/server_matchmaking.kt b/src/jvmMain/kotlin/starshipfights/game/server_matchmaking.kt index 2dbfbc2..87d406f 100644 --- a/src/jvmMain/kotlin/starshipfights/game/server_matchmaking.kt +++ b/src/jvmMain/kotlin/starshipfights/game/server_matchmaking.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.ClosedSendChannelException import kotlinx.coroutines.launch -import starshipfights.auth.getUser import starshipfights.data.admiralty.getInGameAdmiral import starshipfights.data.auth.User diff --git a/src/jvmMain/kotlin/starshipfights/info/views_user.kt b/src/jvmMain/kotlin/starshipfights/info/views_user.kt index 02716bf..a9b740e 100644 --- a/src/jvmMain/kotlin/starshipfights/info/views_user.kt +++ b/src/jvmMain/kotlin/starshipfights/info/views_user.kt @@ -120,10 +120,10 @@ suspend fun ApplicationCall.manageUserPage(): HTML.() -> Unit { th { +"Client IPs" } th { +Entities.nbsp } } - val now = System.currentTimeMillis() + val now = Instant.now() val expiredSessions = mutableListOf() allUserSessions.forEach { session -> - if (session.expirationMillis < now) { + if (session.expiration.isBefore(now)) { expiredSessions += session return@forEach } @@ -164,7 +164,7 @@ suspend fun ApplicationCall.manageUserPage(): HTML.() -> Unit { +"Expired at " span(classes = "moment") { style = "display:none" - +session.expirationMillis.toString() + +session.expiration.toEpochMilli().toString() } } } @@ -303,7 +303,7 @@ suspend fun ApplicationCall.admiralPage(): HTML.() -> Unit { ) ) { section { - h1 { +admiral.fullName } + h1 { +admiral.name } p { +admiral.fullName +" is a flag officer of the " @@ -328,12 +328,16 @@ suspend fun ApplicationCall.admiralPage(): HTML.() -> Unit { } } td { - val now = Instant.now() - +when (ship.status) { - DrydockStatus.Ready -> "Ready" + when (ship.status) { + DrydockStatus.Ready -> +"Ready" is DrydockStatus.InRepair -> { - val distance = (ship.status.until.epochSecond - now.epochSecond) / 3600 + 1 - "Repairing (ready in ${distance}h)" + +"Repairing" + br + +"Will be ready at " + span(classes = "moment") { + style = "display:none" + +ship.status.until.toEpochMilli().toString() + } } } } @@ -356,6 +360,13 @@ suspend fun ApplicationCall.admiralPage(): HTML.() -> Unit { records.sortedBy { it.whenEnded }.forEach { record -> tr { td { + +"Started at " + span(classes = "moment") { + style = "display:none" + +record.whenStarted.toEpochMilli().toString() + } + br + +"Ended at " span(classes = "moment") { style = "display:none" +record.whenEnded.toEpochMilli().toString() -- 2.25.1