-
-
Notifications
You must be signed in to change notification settings - Fork 142
Add coin flip/random number/die skill #386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package org.stypox.dicio.skills.random | ||
|
|
||
| import android.content.Context | ||
| import androidx.compose.material.icons.Icons | ||
| import androidx.compose.material.icons.filled.Casino | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.graphics.vector.rememberVectorPainter | ||
| import org.dicio.skill.context.SkillContext | ||
| import org.dicio.skill.skill.Skill | ||
| import org.dicio.skill.skill.SkillInfo | ||
| import org.stypox.dicio.R | ||
| import org.stypox.dicio.sentences.Sentences | ||
|
|
||
| object RandomInfo : SkillInfo("random") { | ||
| override fun name(context: Context) = | ||
| context.getString(R.string.skill_name_random) | ||
|
|
||
| override fun sentenceExample(context: Context) = | ||
| context.getString(R.string.skill_sentence_example_random) | ||
|
|
||
| @Composable | ||
| override fun icon() = | ||
| rememberVectorPainter(Icons.Default.Casino) | ||
|
|
||
| override fun isAvailable(ctx: SkillContext): Boolean { | ||
| return Sentences.Random[ctx.sentencesLanguage] != null | ||
| } | ||
|
|
||
| override fun build(ctx: SkillContext): Skill<*> { | ||
| return RandomSkill(RandomInfo, Sentences.Random[ctx.sentencesLanguage]!!) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||||||||||||||||||
| package org.stypox.dicio.skills.random | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import androidx.compose.foundation.layout.Arrangement | ||||||||||||||||||||||
| import androidx.compose.foundation.layout.Column | ||||||||||||||||||||||
| import androidx.compose.runtime.Composable | ||||||||||||||||||||||
| import androidx.compose.ui.unit.dp | ||||||||||||||||||||||
| import org.dicio.skill.context.SkillContext | ||||||||||||||||||||||
| import org.dicio.skill.skill.SkillOutput | ||||||||||||||||||||||
| import org.stypox.dicio.R | ||||||||||||||||||||||
| import org.stypox.dicio.io.graphical.Body | ||||||||||||||||||||||
| import org.stypox.dicio.io.graphical.Headline | ||||||||||||||||||||||
| import org.stypox.dicio.io.graphical.Subtitle | ||||||||||||||||||||||
| import org.stypox.dicio.util.getString | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| sealed interface RandomOutput : SkillOutput { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data class CoinFlip(private val result: String) : RandomOutput { | ||||||||||||||||||||||
| override fun getSpeechOutput(ctx: SkillContext): String = | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_coin_flip, result) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @Composable | ||||||||||||||||||||||
| override fun GraphicalOutput(ctx: SkillContext) { | ||||||||||||||||||||||
| Headline(text = result.uppercase()) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data class DiceRoll(private val results: List<Int>, private val sides: Int) : RandomOutput { | ||||||||||||||||||||||
| override fun getSpeechOutput(ctx: SkillContext): String { | ||||||||||||||||||||||
| val total = results.sum() | ||||||||||||||||||||||
| return if (results.size == 1) { | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_dice_roll, results[0], sides) | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_dice_roll_multiple, total, results.size, sides) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @Composable | ||||||||||||||||||||||
| override fun GraphicalOutput(ctx: SkillContext) { | ||||||||||||||||||||||
| Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { | ||||||||||||||||||||||
| Headline( | ||||||||||||||||||||||
| text = if (results.size == 1) results[0].toString() else results.sum().toString() | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| if (results.size == 1) { | ||||||||||||||||||||||
| Subtitle(text = ctx.getString(R.string.skill_random_dice_sides, sides)) | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| Subtitle(text = ctx.getString(R.string.skill_random_dice_sides, sides)) | ||||||||||||||||||||||
| Body(text = results.joinToString(" + ") + " = ${results.sum()}") | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+43
to
+48
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data class RandomNumber( | ||||||||||||||||||||||
| private val result: Int, | ||||||||||||||||||||||
| private val min: Int, | ||||||||||||||||||||||
| private val max: Int | ||||||||||||||||||||||
| ) : RandomOutput { | ||||||||||||||||||||||
| override fun getSpeechOutput(ctx: SkillContext): String = | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_random_number, result, min, max) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @Composable | ||||||||||||||||||||||
| override fun GraphicalOutput(ctx: SkillContext) { | ||||||||||||||||||||||
| Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { | ||||||||||||||||||||||
| Headline(text = result.toString()) | ||||||||||||||||||||||
| Subtitle(text = ctx.getString(R.string.skill_random_range, min, max)) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data object InvalidRange : RandomOutput { | ||||||||||||||||||||||
| override fun getSpeechOutput(ctx: SkillContext): String = | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_invalid_range) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @Composable | ||||||||||||||||||||||
| override fun GraphicalOutput(ctx: SkillContext) { | ||||||||||||||||||||||
| Headline(text = ctx.getString(R.string.skill_random_invalid_range)) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,65 @@ | ||||||||||||||||||||||
| package org.stypox.dicio.skills.random | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import org.dicio.numbers.unit.Number | ||||||||||||||||||||||
| import org.dicio.skill.context.SkillContext | ||||||||||||||||||||||
| import org.dicio.skill.skill.SkillInfo | ||||||||||||||||||||||
| import org.dicio.skill.skill.SkillOutput | ||||||||||||||||||||||
| import org.dicio.skill.standard.StandardRecognizerData | ||||||||||||||||||||||
| import org.dicio.skill.standard.StandardRecognizerSkill | ||||||||||||||||||||||
| import org.stypox.dicio.R | ||||||||||||||||||||||
| import org.stypox.dicio.sentences.Sentences.Random | ||||||||||||||||||||||
| import org.stypox.dicio.util.getString | ||||||||||||||||||||||
| import kotlin.random.Random as KotlinRandom | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a randomly-seeded RNG, or does it always have the same seed? |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class RandomSkill( | ||||||||||||||||||||||
| correspondingSkillInfo: SkillInfo, | ||||||||||||||||||||||
| data: StandardRecognizerData<Random> | ||||||||||||||||||||||
| ) : StandardRecognizerSkill<Random>(correspondingSkillInfo, data) { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private fun extractNumber(ctx: SkillContext, text: String?): Int? { | ||||||||||||||||||||||
| return text?.let { | ||||||||||||||||||||||
| ctx.parserFormatter?.extractNumber(it)?.mixedWithText | ||||||||||||||||||||||
| ?.filterIsInstance<Number>() | ||||||||||||||||||||||
| ?.firstOrNull() | ||||||||||||||||||||||
| ?.integerValue() | ||||||||||||||||||||||
| ?.toInt() | ||||||||||||||||||||||
|
Comment on lines
+21
to
+25
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Suggested change
Since this appeared often recently, maybe you could change the |
||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| override suspend fun generateOutput(ctx: SkillContext, inputData: Random): SkillOutput { | ||||||||||||||||||||||
| return when (inputData) { | ||||||||||||||||||||||
| is Random.CoinFlip -> { | ||||||||||||||||||||||
| val result = if (KotlinRandom.nextBoolean()) { | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_heads) | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| ctx.getString(R.string.skill_random_tails) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| RandomOutput.CoinFlip(result) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| is Random.DiceRoll -> { | ||||||||||||||||||||||
| val sides = extractNumber(ctx, inputData.sides) ?: 6 | ||||||||||||||||||||||
| val amount = extractNumber(ctx, inputData.amount) ?: 1 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (sides <= 0 || amount <= 0 || amount > 100) { | ||||||||||||||||||||||
| return RandomOutput.InvalidRange | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| val results = List(amount) { KotlinRandom.nextInt(1, sides + 1) } | ||||||||||||||||||||||
| RandomOutput.DiceRoll(results, sides) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| is Random.RandomNumber -> { | ||||||||||||||||||||||
| val min = extractNumber(ctx, inputData.min) ?: 1 | ||||||||||||||||||||||
| val max = extractNumber(ctx, inputData.max) ?: 100 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (min > max) { | ||||||||||||||||||||||
| return RandomOutput.InvalidRange | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| val result = KotlinRandom.nextInt(min, max + 1) | ||||||||||||||||||||||
| RandomOutput.RandomNumber(result, min, max) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -152,6 +152,8 @@ | |
| <string name="skill_sentence_example_timer">Set a timer for five minutes</string> | ||
| <string name="skill_name_current_time">Current time</string> | ||
| <string name="skill_sentence_example_current_time">What time is it?</string> | ||
| <string name="skill_name_random">Random</string> | ||
| <string name="skill_sentence_example_random">Roll a 20-sided die</string> | ||
| <string name="skill_fallback_name_text">Text message</string> | ||
| <string name="skill_search_here_is_what_i_found">Here is what I found</string> | ||
| <string name="skill_search_no_results">The search returned no results, try telling me again what you want to search for</string> | ||
|
|
@@ -246,4 +248,13 @@ | |
| <string name="failed_to_copy">Failed to copy to clipboard</string> | ||
| <string name="skill_translation_auto">Auto</string> | ||
| <string name="skill_search_duckduckgo_recaptcha">DuckDuckGo did not provide results, asking for a Captcha to be solved</string> | ||
| <string name="skill_random_coin_flip">The coin landed on %1$s</string> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather have two |
||
| <string name="skill_random_dice_roll">You rolled a %1$d on a %2$d-sided die</string> | ||
| <string name="skill_random_dice_roll_multiple">You rolled %1$d total on %2$d %3$d-sided dice</string> | ||
| <string name="skill_random_dice_sides">%1$d-sided die</string> | ||
| <string name="skill_random_random_number">Your random number is %1$d</string> | ||
| <string name="skill_random_range">Range: %1$d to %2$d</string> | ||
| <string name="skill_random_invalid_range">Invalid range, please specify valid numbers</string> | ||
| <string name="skill_random_heads">heads</string> | ||
| <string name="skill_random_tails">tails</string> | ||
| </resources> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #384 (comment) also applies here: you could separate |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| coin_flip: | ||
| - flip (a|the) coin<s?> | ||
| - heads or tails | ||
|
|
||
| dice_roll: | ||
| # Simple dice roll (defaults to 6 sides) | ||
| - roll (a|the|some)? (die|dice) | ||
| - throw (a|the|some)? (die|dice) | ||
|
|
||
| # Dice with specific sides | ||
| - (roll|throw) (a|an)? .sides. sided? (die|dice) | ||
| - (roll|throw) a? d .sides. | ||
|
|
||
| # RPG notation: "roll 1 d 20", "roll 4 d 10", etc | ||
| - (roll|throw) .amount. d .sides. | ||
|
|
||
| random_number: | ||
| # Generic random number (no range specified) | ||
| - (give me|pick|choose|select|generate|get) (a|any)? random? number | ||
| - random number | ||
|
|
||
| # Random number with specific range | ||
| - pick (a|any)? number (from|between)? .min. (to|and|through) .max. | ||
| - random number (from|between)? .min. (to|and|through) .max. | ||
| - (choose|select|give me|generate|get) (a|any)? random? number (from|between)? .min. (to|and|through) .max. |
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probablt a leftover and should be removed |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| coin_flip: | ||
| - flip (a|the) coin<s?> | ||
| - heads or tails | ||
|
|
||
| dice_roll: | ||
| # Simple dice roll (defaults to 6 sides) | ||
| - roll (a|the|some)? (die|dice) | ||
| - throw (a|the|some)? (die|dice) | ||
|
|
||
| # Dice with specific sides | ||
| - (roll|throw) (a|an)? .sides. sided? (die|dice) | ||
| - (roll|throw) a? d .sides. | ||
|
|
||
| # RPG notation: "roll 1 d 20", "roll 4 d 10", etc | ||
| - (roll|throw) .amount. d .sides. | ||
|
|
||
| random_number: | ||
| # Generic random number (no range specified) | ||
| - (give me|pick|choose|select|generate|get) (a|any)? random? number | ||
| - random number | ||
|
|
||
| # Random number with specific range | ||
| - pick (a|any)? number (from|between)? .min. (to|and|through) .max. | ||
| - random number (from|between)? .min. (to|and|through) .max. | ||
| - (choose|select|give me|generate|get) (a|any)? random? number (from|between)? .min. (to|and|through) .max. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.