From: TheSaminator Date: Tue, 8 Feb 2022 00:02:10 +0000 (-0500) Subject: Add random name generation X-Git-Url: https://gitweb.starshipfights.net/?a=commitdiff_plain;h=9ea18c8f7773496c54aefae9e62c21022d2c1165;p=starship-fights Add random name generation --- diff --git a/src/jvmMain/kotlin/starshipfights/auth/providers.kt b/src/jvmMain/kotlin/starshipfights/auth/providers.kt index beb12b7..cfce085 100644 --- a/src/jvmMain/kotlin/starshipfights/auth/providers.kt +++ b/src/jvmMain/kotlin/starshipfights/auth/providers.kt @@ -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 index 0000000..20387bf --- /dev/null +++ b/src/jvmMain/kotlin/starshipfights/data/admiralty/admiral_names.kt @@ -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> = 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> = 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> = 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 + } +} diff --git a/src/jvmMain/kotlin/starshipfights/info/endpoints_info.kt b/src/jvmMain/kotlin/starshipfights/info/endpoints_info.kt index 31b476b..55ea72c 100644 --- a/src/jvmMain/kotlin/starshipfights/info/endpoints_info.kt +++ b/src/jvmMain/kotlin/starshipfights/info/endpoints_info.kt @@ -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) + } } diff --git a/src/jvmMain/kotlin/starshipfights/info/views_user.kt b/src/jvmMain/kotlin/starshipfights/info/views_user.kt index 7e171b4..2cc41ec 100644 --- a/src/jvmMain/kotlin/starshipfights/info/views_user.kt +++ b/src/jvmMain/kotlin/starshipfights/info/views_user.kt @@ -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 } } } diff --git a/src/jvmMain/resources/static/init.js b/src/jvmMain/resources/static/init.js index 86cc438..fc5834c 100644 --- a/src/jvmMain/resources/static/init.js +++ b/src/jvmMain/resources/static/init.js @@ -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(); + })(); + }; + } +});