1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.egg.landroid
18 
19 import android.content.res.Resources
20 import com.android.egg.R
21 import kotlin.random.Random
22 
23 const val SUFFIX_PROB = 0.75f
24 const val LETTER_PROB = 0.3f
25 const val NUMBER_PROB = 0.3f
26 const val RARE_PROB = 0.05f
27 
28 class Namer(resources: Resources) {
29     private val planetDescriptors = Bag(resources.getStringArray(R.array.planet_descriptors))
30     private val lifeDescriptors = Bag(resources.getStringArray(R.array.life_descriptors))
31     private val anyDescriptors = Bag(resources.getStringArray(R.array.any_descriptors))
32     private val atmoDescriptors = Bag(resources.getStringArray(R.array.atmo_descriptors))
33 
34     private val planetTypes = Bag(resources.getStringArray(R.array.planet_types))
35     private val constellations = Bag(resources.getStringArray(R.array.constellations))
36     private val constellationsRare = Bag(resources.getStringArray(R.array.constellations_rare))
37     private val suffixes = Bag(resources.getStringArray(R.array.star_suffixes))
38     private val suffixesRare = Bag(resources.getStringArray(R.array.star_suffixes_rare))
39 
40     private val planetTable = RandomTable(0.75f to planetDescriptors, 0.25f to anyDescriptors)
41 
42     private var lifeTable = RandomTable(0.75f to lifeDescriptors, 0.25f to anyDescriptors)
43 
44     private var constellationsTable =
45         RandomTable(RARE_PROB to constellationsRare, 1f - RARE_PROB to constellations)
46 
47     private var suffixesTable = RandomTable(RARE_PROB to suffixesRare, 1f - RARE_PROB to suffixes)
48 
49     private var atmoTable = RandomTable(0.75f to atmoDescriptors, 0.25f to anyDescriptors)
50 
51     private var delimiterTable =
52         RandomTable(
53             15f to " ",
54             3f to "-",
55             1f to "_",
56             1f to "/",
57             1f to ".",
58             1f to "*",
59             1f to "^",
60             1f to "#",
61             0.1f to "(^*!%@##!!"
62         )
63 
64     private var activities = Bag(resources.getStringArray(R.array.activities))
65     private var floraGenericPlurals = Bag(resources.getStringArray(R.array.flora_generic_plurals))
66     private var faunaGenericPlurals = Bag(resources.getStringArray(R.array.fauna_generic_plurals))
67     private var atmoGenericPlurals = Bag(resources.getStringArray(R.array.atmo_generic_plurals))
68 
describePlanetnull69     fun describePlanet(rng: Random): String {
70         return planetTable.roll(rng).pull(rng) + " " + planetTypes.pull(rng)
71     }
72 
describeLifenull73     fun describeLife(rng: Random): String {
74         return lifeTable.roll(rng).pull(rng)
75     }
76 
nameSystemnull77     fun nameSystem(rng: Random): String {
78         val parts = StringBuilder()
79         parts.append(constellationsTable.roll(rng).pull(rng))
80         if (rng.nextFloat() <= SUFFIX_PROB) {
81             parts.append(delimiterTable.roll(rng))
82             parts.append(suffixesTable.roll(rng).pull(rng))
83             if (rng.nextFloat() <= RARE_PROB) parts.append(' ').append(suffixesRare.pull(rng))
84         }
85         if (rng.nextFloat() <= LETTER_PROB) {
86             parts.append(delimiterTable.roll(rng))
87             parts.append('A' + rng.nextInt(0, 26))
88             if (rng.nextFloat() <= RARE_PROB) parts.append(delimiterTable.roll(rng))
89         }
90         if (rng.nextFloat() <= NUMBER_PROB) {
91             parts.append(delimiterTable.roll(rng))
92             parts.append(rng.nextInt(2, 5039))
93         }
94         return parts.toString()
95     }
96 
describeAtmonull97     fun describeAtmo(rng: Random): String {
98         return atmoTable.roll(rng).pull(rng)
99     }
100 
floraPluralnull101     fun floraPlural(rng: Random): String {
102         return floraGenericPlurals.pull(rng)
103     }
faunaPluralnull104     fun faunaPlural(rng: Random): String {
105         return faunaGenericPlurals.pull(rng)
106     }
atmoPluralnull107     fun atmoPlural(rng: Random): String {
108         return atmoGenericPlurals.pull(rng)
109     }
110 
111     val TEMPLATE_REGEX = Regex("""\{(flora|fauna|planet|atmo)\}""")
describeActivitynull112     fun describeActivity(rng: Random, target: Planet?): String {
113         return activities
114             .pull(rng)
115             .replace(TEMPLATE_REGEX) {
116                 when (it.groupValues[1]) {
117                     "flora" -> (target?.flora ?: "SOME") + " " + floraPlural(rng)
118                     "fauna" -> (target?.fauna ?: "SOME") + " " + faunaPlural(rng)
119                     "atmo" -> (target?.atmosphere ?: "SOME") + " " + atmoPlural(rng)
120                     "planet" -> (target?.description ?: "SOME BODY") // once told me
121                     else -> "unknown template tag: ${it.groupValues[0]}"
122                 }
123             }
124             .toUpperCase()
125     }
126 }
127