From: TheSaminator Date: Tue, 1 Mar 2022 21:57:11 +0000 (-0500) Subject: Change ship status to simple Instant when ship becomes ready X-Git-Url: https://gitweb.starshipfights.net/?a=commitdiff_plain;h=b2d6d58db4202fd0c4e97f260ef68cc502d8d540;p=starship-fights Change ship status to simple Instant when ship becomes ready --- diff --git a/src/jvmMain/kotlin/starshipfights/auth/providers.kt b/src/jvmMain/kotlin/starshipfights/auth/providers.kt index a075e70..67cac6c 100644 --- a/src/jvmMain/kotlin/starshipfights/auth/providers.kt +++ b/src/jvmMain/kotlin/starshipfights/auth/providers.kt @@ -223,7 +223,7 @@ interface AuthProvider { if (admiral.owningUser != currentUser) forbid() if (ship.owningAdmiral != admiralId) forbid() - if (ship.status != DrydockStatus.Ready) redirect("/admiral/${admiralId}/manage") + if (ship.readyAt > Instant.now()) redirect("/admiral/${admiralId}/manage") if (ship.shipType.weightClass.isUnique) redirect("/admiral/${admiralId}/manage") coroutineScope { @@ -269,7 +269,7 @@ interface AuthProvider { val newShip = ShipInDrydock( name = newShipName, shipType = shipType, - status = DrydockStatus.Ready, + readyAt = Instant.now().plus(6, ChronoUnit.HOURS), owningAdmiral = admiralId ) diff --git a/src/jvmMain/kotlin/starshipfights/data/admiralty/admirals.kt b/src/jvmMain/kotlin/starshipfights/data/admiralty/admirals.kt index 1828ea9..ca797d5 100644 --- a/src/jvmMain/kotlin/starshipfights/data/admiralty/admirals.kt +++ b/src/jvmMain/kotlin/starshipfights/data/admiralty/admirals.kt @@ -6,10 +6,7 @@ import kotlinx.serialization.Contextual import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import org.bson.conversions.Bson -import org.litote.kmongo.and -import org.litote.kmongo.eq -import org.litote.kmongo.gte -import org.litote.kmongo.lt +import org.litote.kmongo.* import starshipfights.data.DataDocument import starshipfights.data.DocumentTable import starshipfights.data.Id @@ -52,27 +49,15 @@ infix fun AdmiralRank.Companion.eq(rank: AdmiralRank): Bson = when (rank.ordinal ) } -@Serializable -sealed class DrydockStatus { - @Serializable - object Ready : DrydockStatus() - - @Serializable - data class InRepair(val until: @Contextual Instant) : DrydockStatus() -} - @Serializable data class ShipInDrydock( @SerialName("_id") override val id: Id = Id(), val name: String, val shipType: ShipType, - val status: DrydockStatus, + val readyAt: @Contextual Instant, val owningAdmiral: Id ) : DataDocument { - val isReady: Boolean - get() = status == DrydockStatus.Ready - val shipData: Ship get() = Ship(id.reinterpret(), name, shipType) @@ -105,11 +90,14 @@ suspend fun getInGameAdmiral(admiralId: Id) = Admiral.get(admiral } } -suspend fun getAdmiralsShips(admiralId: Id) = ShipInDrydock - .filter(ShipInDrydock::owningAdmiral eq admiralId) - .toList() - .filter { it.isReady } - .associate { it.shipData.id to it.shipData } +suspend fun getAdmiralsShips(admiralId: Id): Map, Ship> { + val now = Instant.now() + + return ShipInDrydock + .filter(and(ShipInDrydock::owningAdmiral eq admiralId, ShipInDrydock::readyAt lte now)) + .toList() + .associate { it.shipData.id to it.shipData } +} fun generateFleet(admiral: Admiral): List = ShipWeightClass.values() .flatMap { swc -> @@ -125,6 +113,8 @@ fun generateFleet(admiral: Admiral): List = ShipWeightClass.value } } .let { shipTypes -> + val now = Instant.now().minusMillis(100L) + val shipNames = mutableSetOf() shipTypes.mapNotNull { st -> newShipName(st.faction, st.weightClass, shipNames)?.let { name -> @@ -132,7 +122,7 @@ fun generateFleet(admiral: Admiral): List = ShipWeightClass.value id = Id(), name = name, shipType = st, - status = DrydockStatus.Ready, + readyAt = now, owningAdmiral = admiral.id ) } diff --git a/src/jvmMain/kotlin/starshipfights/data/data_routines.kt b/src/jvmMain/kotlin/starshipfights/data/data_routines.kt index 4c0d3ac..08a157e 100644 --- a/src/jvmMain/kotlin/starshipfights/data/data_routines.kt +++ b/src/jvmMain/kotlin/starshipfights/data/data_routines.kt @@ -1,11 +1,11 @@ package starshipfights.data import kotlinx.coroutines.* -import org.litote.kmongo.div import org.litote.kmongo.inc -import org.litote.kmongo.lt -import org.litote.kmongo.setValue -import starshipfights.data.admiralty.* +import starshipfights.data.admiralty.Admiral +import starshipfights.data.admiralty.BattleRecord +import starshipfights.data.admiralty.ShipInDrydock +import starshipfights.data.admiralty.eq import starshipfights.data.auth.User import starshipfights.data.auth.UserSession import starshipfights.game.AdmiralRank @@ -30,17 +30,6 @@ object DataRoutines { UserSession.initialize() return scope.launch { - // Repair ships - launch { - while (currentCoroutineContext().isActive) { - launch { - val now = Instant.now() - ShipInDrydock.update(ShipInDrydock::status / DrydockStatus.InRepair::until lt now, setValue(ShipInDrydock::status, DrydockStatus.Ready)) - } - delay(300_000) - } - } - // Pay admirals launch { var prevTime = Instant.now().atZone(ZoneId.systemDefault()) diff --git a/src/jvmMain/kotlin/starshipfights/game/server_game.kt b/src/jvmMain/kotlin/starshipfights/game/server_game.kt index 40d9a15..4e24990 100644 --- a/src/jvmMain/kotlin/starshipfights/game/server_game.kt +++ b/src/jvmMain/kotlin/starshipfights/game/server_game.kt @@ -15,7 +15,6 @@ import starshipfights.data.DocumentTable import starshipfights.data.Id import starshipfights.data.admiralty.Admiral import starshipfights.data.admiralty.BattleRecord -import starshipfights.data.admiralty.DrydockStatus import starshipfights.data.admiralty.ShipInDrydock import starshipfights.data.auth.User import starshipfights.data.createToken @@ -124,6 +123,8 @@ class GameSession(gameState: GameState) { errorMessageChannel(player).send(result.message) } is GameEvent.GameEnd -> { + if (_gameStart.isActive) + _gameStart.cancel() _gameEnd.complete(result) } } @@ -190,10 +191,10 @@ suspend fun DefaultWebSocketServerSession.gameEndpoint(user: User, token: String private const val SHIP_POINTS_PER_ACUMEN = 5 private suspend fun onGameEnd(gameState: GameState, gameEnd: GameEvent.GameEnd, startedAt: Instant, endedAt: Instant) { - val destroyedShipStatus = DrydockStatus.InRepair(endedAt.plus(12, ChronoUnit.HOURS)) - val damagedShipStatus = DrydockStatus.InRepair(endedAt.plus(8, ChronoUnit.HOURS)) - val intactShipStatus = DrydockStatus.InRepair(endedAt.plus(4, ChronoUnit.HOURS)) - val escapedShipStatus = DrydockStatus.InRepair(endedAt.plus(4, ChronoUnit.HOURS)) + val destroyedShipReadyAt = endedAt.plus(12, ChronoUnit.HOURS) + val damagedShipReadyAt = endedAt.plus(9, ChronoUnit.HOURS) + val intactShipReadyAt = endedAt.plus(3, ChronoUnit.HOURS) + val escapedShipReadyAt = endedAt.plus(3, ChronoUnit.HOURS) val shipWrecks = gameState.destroyedShips val ships = gameState.ships @@ -227,16 +228,16 @@ private suspend fun onGameEnd(gameState: GameState, gameEnd: GameEvent.GameEnd, coroutineScope { launch { - ShipInDrydock.update(ShipInDrydock::id `in` destroyedShips, setValue(ShipInDrydock::status, destroyedShipStatus)) + ShipInDrydock.update(ShipInDrydock::id `in` destroyedShips, setValue(ShipInDrydock::readyAt, destroyedShipReadyAt)) } launch { - ShipInDrydock.update(ShipInDrydock::id `in` damagedShips, setValue(ShipInDrydock::status, damagedShipStatus)) + ShipInDrydock.update(ShipInDrydock::id `in` damagedShips, setValue(ShipInDrydock::readyAt, damagedShipReadyAt)) } launch { - ShipInDrydock.update(ShipInDrydock::id `in` intactShips, setValue(ShipInDrydock::status, intactShipStatus)) + ShipInDrydock.update(ShipInDrydock::id `in` intactShips, setValue(ShipInDrydock::readyAt, intactShipReadyAt)) } launch { - ShipInDrydock.update(ShipInDrydock::id `in` escapedShips, setValue(ShipInDrydock::status, escapedShipStatus)) + ShipInDrydock.update(ShipInDrydock::id `in` escapedShips, setValue(ShipInDrydock::readyAt, escapedShipReadyAt)) } launch { diff --git a/src/jvmMain/kotlin/starshipfights/info/html_utils.kt b/src/jvmMain/kotlin/starshipfights/info/html_utils.kt index 17f6d6f..3b67f55 100644 --- a/src/jvmMain/kotlin/starshipfights/info/html_utils.kt +++ b/src/jvmMain/kotlin/starshipfights/info/html_utils.kt @@ -22,17 +22,3 @@ fun FORM.csrfToken(cookie: Id) = hiddenInput { name = CsrfProtector.csrfInputName value = CsrfProtector.newNonce(cookie, this@csrfToken.action) } - -var META.property: String? - get() = attributes["property"] - set(value) { - if (value != null) - attributes["property"] = value - else - attributes.remove("property") - } - -fun HEAD.metaOG(property: String, content: String) = meta { - this.property = property - this.content = content -} diff --git a/src/jvmMain/kotlin/starshipfights/info/views_user.kt b/src/jvmMain/kotlin/starshipfights/info/views_user.kt index beb926e..d018ba4 100644 --- a/src/jvmMain/kotlin/starshipfights/info/views_user.kt +++ b/src/jvmMain/kotlin/starshipfights/info/views_user.kt @@ -461,6 +461,8 @@ suspend fun ApplicationCall.admiralPage(): HTML.() -> Unit { th { +"Ship Class" } th { +"Ship Status" } } + + val now = Instant.now() ships.sortedBy { it.name }.sortedBy { it.shipType.weightClass.rank }.forEach { ship -> tr { td { +ship.shipData.fullName } @@ -470,16 +472,21 @@ suspend fun ApplicationCall.admiralPage(): HTML.() -> Unit { } } td { - when (ship.status) { - DrydockStatus.Ready -> +"Ready" - is DrydockStatus.InRepair -> { - +"Repairing" - br - +"Will be ready at " - span(classes = "moment") { - style = "display:none" - +ship.status.until.toEpochMilli().toString() - } + val shipReadyAt = ship.readyAt + if (shipReadyAt <= now) { + +"Ready" + br + +"(since " + span(classes = "moment") { + style = "display:none" + +shipReadyAt.toEpochMilli().toString() + } + +")" + } else { + +"Will be ready at " + span(classes = "moment") { + style = "display:none" + +shipReadyAt.toEpochMilli().toString() } } } @@ -675,6 +682,8 @@ suspend fun ApplicationCall.manageAdmiralPage(): HTML.() -> Unit { th { +"Ship Status" } th { +"Ship Value" } } + + val now = Instant.now() ownedShips.sortedBy { it.name }.sortedBy { it.shipType.weightClass.rank }.forEach { ship -> tr { td { @@ -688,16 +697,21 @@ suspend fun ApplicationCall.manageAdmiralPage(): HTML.() -> Unit { } } td { - when (ship.status) { - DrydockStatus.Ready -> +"Ready" - is DrydockStatus.InRepair -> { - +"Repairing" - br - +"Will be ready at " - span(classes = "moment") { - style = "display:none" - +ship.status.until.toEpochMilli().toString() - } + val shipReadyAt = ship.readyAt + if (shipReadyAt <= now) { + +"Ready" + br + +"(since " + span(classes = "moment") { + style = "display:none" + +shipReadyAt.toEpochMilli().toString() + } + +")" + } else { + +"Will be ready at " + span(classes = "moment") { + style = "display:none" + +shipReadyAt.toEpochMilli().toString() } } } @@ -705,7 +719,7 @@ suspend fun ApplicationCall.manageAdmiralPage(): HTML.() -> Unit { +ship.shipType.weightClass.sellPrice.toString() +" " +admiral.faction.currencyName - if (ship.status == DrydockStatus.Ready && !ship.shipType.weightClass.isUnique) { + if (ship.readyAt <= now && !ship.shipType.weightClass.isUnique) { br a(href = "/admiral/${admiralId}/sell/${ship.id}") { +"Sell" } } @@ -804,7 +818,7 @@ suspend fun ApplicationCall.sellShipConfirmPage(): HTML.() -> Unit { if (admiral.owningUser != currentUser) forbid() if (ship.owningAdmiral != admiralId) forbid() - if (ship.status != DrydockStatus.Ready) redirect("/admiral/${admiralId}/manage") + if (ship.readyAt > Instant.now()) redirect("/admiral/${admiralId}/manage") if (ship.shipType.weightClass.isUnique) redirect("/admiral/${admiralId}/manage") return page( diff --git a/src/jvmMain/resources/static/images/flag/isarnareykk.inkscape.svg b/src/jvmMain/resources/static/images/flag/isarnareykk.inkscape.svg index 4749400..2ef496c 100644 --- a/src/jvmMain/resources/static/images/flag/isarnareykk.inkscape.svg +++ b/src/jvmMain/resources/static/images/flag/isarnareykk.inkscape.svg @@ -2,242 +2,243 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128mm" + height="80mm" + viewBox="0 0 128 80" + version="1.1" + id="svg8" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="isarnareykk.inkscape.svg"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/jvmMain/resources/static/images/flag/isarnareykk.svg b/src/jvmMain/resources/static/images/flag/isarnareykk.svg index 675e8b0..775f9a6 100644 --- a/src/jvmMain/resources/static/images/flag/isarnareykk.svg +++ b/src/jvmMain/resources/static/images/flag/isarnareykk.svg @@ -29,7 +29,7 @@ transform="matrix(0.26666666,0,0,0.26666666,1.32e-6,217)" id="g1032">