Add validation to cluster generation testing
authorTheSaminator <thesaminator@users.noreply.github.com>
Wed, 6 Jul 2022 17:04:05 +0000 (13:04 -0400)
committerTheSaminator <thesaminator@users.noreply.github.com>
Wed, 6 Jul 2022 17:04:05 +0000 (13:04 -0400)
src/commonMain/kotlin/net/starshipfights/campaign/cluster_params.kt
src/jvmMain/kotlin/net/starshipfights/campaign/endpoints_campaign.kt
src/jvmMain/kotlin/net/starshipfights/labs/endpoints_labs.kt

index 5c91d8fa72efcebb7e874574fa67686caa271db9..3769fbfe0370fe9b55bb0c8a59d4196f55010c17 100644 (file)
@@ -59,6 +59,10 @@ enum class ClusterFactionMode {
 @JvmInline
 @Serializable
 value class ClusterFactions private constructor(private val factions: Map<FactionFlavor, ClusterFactionMode>) {
+       init {
+               require(factions.values.any { it != ClusterFactionMode.EXCLUDE }) { "Excluding all factions is a bad idea!" }
+       }
+       
        operator fun get(factionFlavor: FactionFlavor) = factions[factionFlavor] ?: ClusterFactionMode.ALLOW
        
        operator fun plus(other: ClusterFactions) = ClusterFactions(factions + other.factions)
index 86c9ba5a2fe88c341393d5ce400f94e78696184f..58f7a9a8bd44464604779ef59c145d9eeeb7612a 100644 (file)
@@ -7,10 +7,13 @@ import io.ktor.request.*
 import io.ktor.routing.*
 import io.ktor.util.*
 import kotlinx.html.*
+import net.starshipfights.auth.withErrorMessage
 import net.starshipfights.data.Id
 import net.starshipfights.game.*
 import net.starshipfights.labs.lab
 import net.starshipfights.labs.labPost
+import net.starshipfights.labs.labUrl
+import net.starshipfights.redirect
 
 fun Routing.installCampaign() {
        lab("cluster", "Star Clusters") {
@@ -187,15 +190,21 @@ fun Routing.installCampaign() {
        labPost("cluster") {
                val parameters = call.receiveParameters()
                
-               val color = StarClusterBackground.valueOf(parameters.getOrFail("color"))
-               val size = ClusterSize.valueOf(parameters.getOrFail("size"))
-               val density = ClusterLaneDensity.valueOf(parameters.getOrFail("density"))
-               val planets = ClusterPlanetDensity.valueOf(parameters.getOrFail("planets"))
-               val corruption = ClusterCorruption.valueOf(parameters.getOrFail("corruption"))
-               val contention = ClusterContention.valueOf(parameters.getOrFail("contention"))
-               val factions = ClusterFactions(FactionFlavor.values().mapNotNull { faction ->
-                       parameters["factions[${faction.toUrlSlug()}]"]?.let { faction to ClusterFactionMode.valueOf(it) }
-               }.toMap())
+               val color = StarClusterBackground.values().valueOfOrRedirect(parameters.getOrFail("color")) { "Invalid value chosen for background color" }
+               val size = ClusterSize.values().valueOfOrRedirect(parameters.getOrFail("size")) { "Invalid value chosen for cluster size" }
+               val density = ClusterLaneDensity.values().valueOfOrRedirect(parameters.getOrFail("density")) { "Invalid value chosen for warp lane density" }
+               val planets = ClusterPlanetDensity.values().valueOfOrRedirect(parameters.getOrFail("planets")) { "Invalid value chosen for planet density" }
+               val corruption = ClusterCorruption.values().valueOfOrRedirect(parameters.getOrFail("corruption")) { "Invalid value chosen for eldritch corruption" }
+               val contention = ClusterContention.values().valueOfOrRedirect(parameters.getOrFail("contention")) { "Invalid value chosen for factional contention" }
+               val factions = try {
+                       ClusterFactions(FactionFlavor.values().mapNotNull { faction ->
+                               parameters["factions[${faction.toUrlSlug()}]"]
+                                       ?.let { ClusterFactionMode.values().valueOfOrNull(it) }
+                                       ?.let { faction to it }
+                       }.toMap())
+               } catch (ex: IllegalArgumentException) {
+                       redirect(labUrl("cluster") + withErrorMessage("Invalid values chosen for faction modes"))
+               }
                
                val cluster = ClusterGenerator(
                        ClusterGenerationSettings(color, size, density, planets, corruption, factions, contention)
@@ -211,3 +220,7 @@ fun Routing.installCampaign() {
                call.respondHtml(HttpStatusCode.OK, clientMode.view())
        }
 }
+
+private fun <T : Enum<T>> Array<T>.valueOfOrNull(param: String?) = singleOrNull { it.name == param }
+
+private fun <T : Enum<T>> Array<T>.valueOfOrRedirect(param: String?, message: () -> String) = valueOfOrNull(param) ?: redirect(labUrl("cluster") + withErrorMessage(message()))
index 13af78ef143ba9bb0fd9cc501e4042413726e01c..c19cf2c4a3aae79018a7c4accc298b31ba506003 100644 (file)
@@ -12,14 +12,16 @@ private val labs = mutableMapOf<String, String>()
 private val labsSidebar: Sidebar
        get() = PageNavSidebar(
                listOf(NavHead("Other Labs")) + labs.map { (slug, title) ->
-                       NavLink("/labs/$slug", title)
+                       NavLink(labUrl(slug), title)
                }
        )
 
+fun labUrl(slug: String) = "/labs/$slug"
+
 fun Routing.lab(slug: String, title: String, pageBody: SECTIONS.() -> Unit) {
        labs[slug] = title
        
-       get("/labs/$slug") {
+       get(labUrl(slug)) {
                call.respondHtml(
                        block = call.page(
                                title,
@@ -32,7 +34,7 @@ fun Routing.lab(slug: String, title: String, pageBody: SECTIONS.() -> Unit) {
 }
 
 fun Routing.labPost(slug: String, action: PipelineInterceptor<Unit, ApplicationCall>) {
-       post("/labs/$slug", action)
+       post(labUrl(slug), action)
 }
 
 fun Routing.installLabs() {
@@ -52,7 +54,7 @@ fun Routing.installLabs() {
                                                ul {
                                                        for ((slug, title) in labs) {
                                                                li {
-                                                                       a(href = "/labs/$slug") { +title }
+                                                                       a(href = labUrl(slug)) { +title }
                                                                }
                                                        }
                                                }