Add random name generation
authorTheSaminator <TheSaminator@users.noreply.github.com>
Tue, 8 Feb 2022 00:02:10 +0000 (19:02 -0500)
committerTheSaminator <TheSaminator@users.noreply.github.com>
Tue, 8 Feb 2022 00:02:10 +0000 (19:02 -0500)
src/jvmMain/kotlin/starshipfights/auth/providers.kt
src/jvmMain/kotlin/starshipfights/data/admiralty/admiral_names.kt [new file with mode: 0644]
src/jvmMain/kotlin/starshipfights/info/endpoints_info.kt
src/jvmMain/kotlin/starshipfights/info/views_user.kt
src/jvmMain/resources/static/init.js

index beb12b7d750b7c338be47b62d6dad6328308dcbd..cfce085fe66f04451900262e6331e2edded74b6e 100644 (file)
@@ -116,7 +116,7 @@ interface AuthProvider {
                                        
                                        val newAdmiral = Admiral(
                                                owningUser = currentUser,
-                                               name = form.getOrFail("name"),
+                                               name = form["name"]?.takeIf { it.isNotBlank() } ?: throw MissingRequestParameterException("name"),
                                                isFemale = form.getOrFail("sex") == "female",
                                                faction = Faction.valueOf(form.getOrFail("faction")),
                                                // TODO change to Rear Admiral
@@ -151,7 +151,7 @@ interface AuthProvider {
                                        
                                        val form = call.receiveParameters()
                                        val newAdmiral = admiral.copy(
-                                               name = form["name"] ?: admiral.name,
+                                               name = form["name"]?.takeIf { it.isNotBlank() } ?: admiral.name,
                                                isFemale = form["sex"] == "female"
                                        )
                                        
diff --git a/src/jvmMain/kotlin/starshipfights/data/admiralty/admiral_names.kt b/src/jvmMain/kotlin/starshipfights/data/admiralty/admiral_names.kt
new file mode 100644 (file)
index 0000000..20387bf
--- /dev/null
@@ -0,0 +1,291 @@
+package starshipfights.data.admiralty
+
+enum class AdmiralNameFlavor {
+       MECHYRDIA, TYLA, CALIBOR, // Mechyrdia-aligned
+       DIADOCHI, // Masra Draetsen-aligned
+       FULKREYKK, // Isarnareykk-aligned
+       AMERICAN, HISPANIC_AMERICAN; // Vestigium-aligned
+       
+       val displayName: String
+               get() = when (this) {
+                       MECHYRDIA -> "Mechyrdian"
+                       TYLA -> "Tylan"
+                       CALIBOR -> "Caliborese"
+                       DIADOCHI -> "Diadochi"
+                       FULKREYKK -> "Thedish"
+                       AMERICAN -> "American"
+                       HISPANIC_AMERICAN -> "Hispanic-American"
+               }
+}
+
+object AdmiralNames {
+       // PERSONAL NAME to PATRONYMIC
+       private val mechyrdianMaleNames: List<Pair<String, String>> = listOf(
+               "Marc" to "Marcówič",
+               "Anton" to "Antonówič",
+               "Bjarnarð" to "Bjarnarðówič",
+               "Carl" to "Carlówič",
+               "Þjutarix" to "Þjutarigówič",
+               "Friðurix" to "Friþurigówič",
+               "Iwan" to "Iwanówič",
+               "Wladimer" to "Wladimerówič",
+               "Giulius" to "Giuliówič",
+               "Nicólei" to "Nicóleiówič",
+               "Þjódor" to "Þjóderówič",
+               "Sigismund" to "Sigismundówič",
+               "Stefan" to "Stefanówič",
+               "Wilhelm" to "Wilhelmówič",
+               "Giórgj" to "Giórgiówič"
+       )
+       
+       // PERSONAL NAME to MATRONYMIC
+       private val mechyrdianFemaleNames: List<Pair<String, String>> = listOf(
+               "Octavia" to "Octaviówca",
+               "Annica" to "Annicówca",
+               "Astrið" to "Astriðówca",
+               "Caþarin" to "Caþarinówca",
+               "Signi" to "Signówca",
+               "Erica" to "Ericówca",
+               "Fréja" to "Fréjówca",
+               "Hilda" to "Hildówca",
+               "Žanna" to "Žannówca",
+               "Xenia" to "Xeniówca",
+               "Carina" to "Carinówca",
+               "Giadwiga" to "Giadwigówca",
+               "Ženia" to "Ženiówca"
+       )
+       
+       private val mechyrdianFamilyNames: List<Pair<String, String>> = listOf(
+               "Alexandrów",
+               "Antonów",
+               "Pogdanów",
+               "Hrusčjów",
+               "Caísarów",
+               "Carolów",
+               "Sócolów",
+               "Romanów",
+               "Nemeciów",
+               "Pjótrów",
+               "Brutów",
+               "Augustów",
+               "Calašniców",
+               "Anželów",
+               "Sigmarów",
+               "Dróganów",
+               "Coroljów",
+               "Wlasów"
+       ).map { it to "${it}a" }
+       
+       private fun randomMechyrdianName(isFemale: Boolean) = if (isFemale)
+               mechyrdianFemaleNames.random().first + " " + mechyrdianFemaleNames.random().second + " " + mechyrdianFamilyNames.random().second
+       else
+               mechyrdianMaleNames.random().first + " " + mechyrdianMaleNames.random().second + " " + mechyrdianFamilyNames.random().first
+       
+       private val tylanMaleNames = listOf(
+               "Althanar" to "Althanas",
+               "Aurans" to "Aurantes",
+               "Bochra" to "Bochranes",
+               "Chshaejar" to "Chshaejas",
+               "Hjofvachi" to "Hjovachines",
+               "Koldimar" to "Koldimas",
+               "Kor" to "Kores",
+               "Ljomas" to "Ljomates",
+               "Shajel" to "Shajel",
+               "Shokar" to "Shokas",
+               "Tolavajel" to "Tolavajel",
+               "Voskar" to "Voskas",
+       )
+       
+       private val tylanFemaleNames = listOf(
+               "Althe" to "Althenes",
+               "Anaseil" to "Anaseil",
+               "Asetbur" to "Asetbus",
+               "Atautha" to "Atauthas",
+               "Aurantia" to "Aurantias",
+               "Ilasheva" to "Ilashevas",
+               "Kalora" to "Kaloras",
+               "Kotolva" to "Kotolvas",
+               "Psekna" to "Pseknas",
+               "Shenera" to "Sheneras",
+               "Reoka" to "Reokas",
+               "Velga" to "Velgas",
+       )
+       
+       private fun randomTylanName(isFemale: Boolean) = if (isFemale)
+               tylanFemaleNames.random().first + " " + tylanFemaleNames.random().second + "-Nahra"
+       else
+               tylanMaleNames.random().first + " " + tylanMaleNames.random().second + "-Nensar"
+       
+       private val caliboreseNames = listOf(
+               "Jathee",
+               "Muly",
+               "Simoh",
+               "Laka",
+               "Foryn",
+               "Duxio",
+               "Xirio",
+               "Surmy",
+               "Datarme",
+               "Cloren",
+               "Tared",
+               "Quiliot",
+               "Attiol",
+               "Quarree",
+               "Guil",
+               "Miro",
+               "Yryys",
+               "Zarx",
+               "Karm",
+               "Mreek",
+               "Dulyy",
+               "Quorqui",
+               "Dreminor",
+               "Samitu",
+               "Lurmak",
+               "Quashi",
+               "Barsyn",
+               "Rymyo",
+               "Soli",
+               "Ickart",
+               "Woom",
+               "Qurquy",
+               "Ymiro",
+               "Rosiliq",
+               "Xant",
+               "Xateen",
+               "Mssly",
+               "Vixie",
+               "Quelynn",
+               "Plly",
+               "Tessy",
+               "Veekah",
+               "Quett",
+               "Xezeez",
+               "Xyph",
+               "Jixi",
+               "Jeekie",
+               "Meelen",
+               "Rasah",
+               "Reteeshy",
+               "Xinchie",
+               "Zae",
+               "Ziggy",
+               "Wurikah",
+               "Loppie",
+               "Tymma",
+               "Reely",
+               "Yjutee",
+               "Len",
+               "Vixirat",
+               "Xumie",
+               "Xilly",
+               "Liwwy",
+               "Gancee",
+               "Pamah",
+               "Zeryll",
+               "Luteet",
+               "Qusseet",
+               "Alixika",
+               "Sepirah",
+               "Luttrah",
+               "Aramynn",
+               "Laxerynn",
+               "Murylyt",
+               "Quarapyt",
+               "Tormiray",
+               "Daromynn",
+               "Zuleerynn",
+               "Quarimat",
+               "Dormaquazi",
+               "Tullequazi",
+               "Aleeray",
+               "Eppiquit",
+               "Wittirynn",
+               "Semiokolipan",
+               "Sosopurr",
+               "Quamixit",
+               "Croffet",
+               "Xaalit",
+               "Xemiolyt"
+       )
+       
+       private val caliboreseVowels = "aeiouy".toSet()
+       private fun randomCaliboreseName(isFemale: Boolean) = caliboreseNames.filter {
+               it.length < 8 && (if (isFemale) it.last() in caliboreseVowels else it.last() !in caliboreseVowels)
+       }.random() + " " + caliboreseNames.filter { it.length > 7 }.random()
+       
+       private val diadochiMaleNames = listOf(
+               "Oqatai",
+               "Amogus",
+               "Nerokhan",
+               "Choghor",
+               "Aghonei",
+               "Martaq",
+               "Qaran",
+               "Khargh",
+               "Qolkhu",
+               "Ghauran",
+               "Woriv",
+               "Vorcha",
+               "Chagatai",
+               "Neghvar",
+               "Kitinga",
+               "Jimpaq",
+               "Bivat",
+               "Durash",
+               "Elifas"
+       )
+       
+       private val diadochiFemaleNames = listOf(
+               "Lursha",
+               "Jamoqena",
+               "Hikari",
+               "Iekuna",
+               "Shara",
+               "Etugen",
+               "Maral",
+               "Temuln",
+               "Akhensari",
+               "Khadagan",
+               "Gherelma",
+               "Shechen",
+               "Althani",
+               "Tzyrina",
+               "Daghasi",
+       )
+       
+       private val diadochiEpithetParts = listOf(
+               "Skull",
+               "Blood",
+               "Death",
+               "Doom",
+               "Dread",
+               "Soul",
+               "Spirit",
+               "Hell",
+               "Dread",
+               "Bale",
+               "Fire",
+               "Fist",
+               "Bear",
+               "Pyre",
+               "Dark",
+               "Vile",
+               "Heart",
+               "Murder",
+               "Gore",
+               "Daemon"
+       )
+       
+       private fun randomDiadochiName(isFemale: Boolean) = (if (isFemale) diadochiMaleNames else diadochiFemaleNames).random() + " " + diadochiEpithetParts.random() + diadochiEpithetParts.random().lowercase()
+       
+       fun randomName(flavor: AdmiralNameFlavor, isFemale: Boolean) = when (flavor) {
+               AdmiralNameFlavor.MECHYRDIA -> randomMechyrdianName(isFemale)
+               AdmiralNameFlavor.TYLA -> randomTylanName(isFemale)
+               AdmiralNameFlavor.CALIBOR -> randomCaliboreseName(isFemale)
+               AdmiralNameFlavor.DIADOCHI -> randomDiadochiName(isFemale)
+               AdmiralNameFlavor.FULKREYKK -> "TODO NOT IMPLEMENTED" // TODO implement
+               AdmiralNameFlavor.AMERICAN -> "TODO NOT IMPLEMENTED" // TODO implement
+               AdmiralNameFlavor.HISPANIC_AMERICAN -> "TODO NOT IMPLEMENTED" // TODO implement
+       }
+}
index 31b476b95756568c5356ba31eaeec9661d8b925f..55ea72ced8aa8083e47f709e1a272ba5d7cbecaa 100644 (file)
@@ -3,7 +3,10 @@ package starshipfights.info
 import io.ktor.application.*
 import io.ktor.html.*
 import io.ktor.http.*
+import io.ktor.response.*
 import io.ktor.routing.*
+import starshipfights.data.admiralty.AdmiralNameFlavor
+import starshipfights.data.admiralty.AdmiralNames
 import starshipfights.game.ShipType
 import starshipfights.game.toUrlSlug
 
@@ -24,4 +27,12 @@ fun Routing.installPages() {
        get("/about") {
                call.respondHtml(HttpStatusCode.OK, call.aboutPage())
        }
+       
+       // Random name generation
+       get("/generate-name/{flavor}/{gender}") {
+               val flavor = call.parameters["flavor"]?.let { flavor -> AdmiralNameFlavor.values().singleOrNull { it.toUrlSlug() == flavor.lowercase() } }!!
+               val isFemale = call.parameters["gender"]?.lowercase()?.startsWith('f') ?: false
+               
+               call.respondText(AdmiralNames.randomName(flavor, isFemale), ContentType.Text.Plain)
+       }
 }
index 7e171b4862b990321a16bc42b9ad2fda28babc9f..2cc41ec72688e2902be30a6c13020d0df48d927b 100644 (file)
@@ -11,10 +11,7 @@ import org.litote.kmongo.or
 import starshipfights.auth.getUser
 import starshipfights.auth.getUserSession
 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.admiralty.*
 import starshipfights.data.auth.User
 import starshipfights.data.auth.UserSession
 import starshipfights.data.auth.usernameRegexStr
@@ -189,6 +186,30 @@ suspend fun ApplicationCall.createAdmiralPage(): HTML.() -> Unit {
                section {
                        h1 { +"Creating Admiral" }
                        form(method = FormMethod.post, action = "/admiral/new") {
+                               h3 {
+                                       label {
+                                               htmlFor = "faction"
+                                               +"Faction"
+                                       }
+                               }
+                               p {
+                                       Faction.values().forEach { faction ->
+                                               val factionId = "faction-${faction.toUrlSlug()}"
+                                               label {
+                                                       htmlFor = factionId
+                                                       radioInput(name = "faction") {
+                                                               id = factionId
+                                                               value = faction.name
+                                                               required = true
+                                                       }
+                                                       img(src = faction.flagUrl) {
+                                                               style = "height:0.75em;width:1.2em"
+                                                       }
+                                                       +Entities.nbsp
+                                                       +faction.shortName
+                                               }
+                                       }
+                               }
                                h3 {
                                        label {
                                                htmlFor = "name"
@@ -196,9 +217,11 @@ suspend fun ApplicationCall.createAdmiralPage(): HTML.() -> Unit {
                                        }
                                }
                                textInput(name = "name") {
+                                       id = "name"
+                                       autoComplete = false
                                        required = true
-                                       minLength = "4"
-                                       maxLength = "24"
+                                       minLength = "2"
+                                       maxLength = "32"
                                }
                                p {
                                        label {
@@ -220,27 +243,14 @@ suspend fun ApplicationCall.createAdmiralPage(): HTML.() -> Unit {
                                                +"Female"
                                        }
                                }
-                               h3 {
-                                       label {
-                                               htmlFor = "faction"
-                                               +"Faction"
-                                       }
-                               }
+                               h3 { +"Generate Random Name" }
                                p {
-                                       Faction.values().forEach { faction ->
-                                               val factionId = "faction-${faction.toUrlSlug()}"
-                                               label {
-                                                       htmlFor = factionId
-                                                       radioInput(name = "faction") {
-                                                               id = factionId
-                                                               value = faction.name
-                                                               required = true
-                                                       }
-                                                       img(src = faction.flagUrl) {
-                                                               style = "height:0.75em;width:1.2em"
-                                                       }
-                                                       +Entities.nbsp
-                                                       +faction.shortName
+                                       AdmiralNameFlavor.values().forEachIndexed { i, flavor ->
+                                               if (i != 0)
+                                                       br
+                                               a(href = "#", classes = "generate-admiral-name") {
+                                                       attributes["data-flavor"] = flavor.toUrlSlug()
+                                                       +flavor.displayName
                                                }
                                        }
                                }
index 86cc4383876ead884516634fb3b98a8b4b256035..fc5834c55de0614cd3242b863c70ef520de0f53b 100644 (file)
@@ -72,3 +72,20 @@ window.addEventListener("load", function () {
                moment.style.display = "inline";
        }
 });
+
+window.addEventListener("load", function () {
+       const nameBox = document.getElementById("name");
+       const isFemaleButton = document.getElementById("sex-female");
+       const generators = document.getElementsByClassName("generate-admiral-name");
+       for (let generator of generators) {
+               const flavor = generator.getAttribute("data-flavor");
+               generator.onclick = (e) => {
+                       e.preventDefault();
+                       (async () => {
+                               nameBox.value = await (await fetch({
+                                       url: "/generate-name/" + flavor + "/" + (isFemaleButton.checked ? "female" : "male")
+                               })).text();
+                       })();
+               };
+       }
+});