use core::ops::RangeInclusive;
use crate::PlayerKey;
use crate::i18n::{Language, Texts};
use crate::world::Player;
use super::sheet::ArgView;
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub enum Value {
Player {
key: PlayerKey,
name: String,
},
Choice(usize),
Number(f64),
Toggle(bool),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Arg {
pub(super) kind: u8,
pub(super) label: String,
pub(super) choices: Vec<(String, String)>,
pub(super) range: (f64, f64),
pub(super) step: f64,
}
impl Arg {
fn new(kind: u8, label: &str) -> Self {
Self {
kind,
label: label.to_owned(),
choices: Vec::new(),
range: (0.0, 0.0),
step: 0.0,
}
}
#[must_use]
pub fn player(label: &str) -> Self {
Self::new(ArgView::PLAYER, label)
}
#[must_use]
pub fn choice(label: &str, choices: &[(&str, &str)]) -> Self {
let mut arg = Self::new(ArgView::CHOICE, label);
arg.choices = choices
.iter()
.map(|(word, label)| ((*word).to_owned(), (*label).to_owned()))
.collect();
arg
}
#[must_use]
pub fn number(label: &str, range: RangeInclusive<f64>, step: f64) -> Self {
let (start, end) = range.into_inner();
let mut arg = Self::new(ArgView::NUMBER, label);
arg.range = (start.min(end), start.max(end));
arg.step = if step.is_finite() { step.abs() } else { 0.0 };
arg
}
#[must_use]
pub fn toggle(label: &str) -> Self {
Self::new(ArgView::TOGGLE, label)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Subject {
pub id: u64,
pub label: String,
}
impl Subject {
#[must_use]
pub fn new(id: u64, label: impl Into<String>) -> Self {
Self {
id,
label: label.into(),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Ask<'a> {
pub player: &'a Player,
pub language: Language,
pub(super) texts: &'a Texts,
}
impl Ask<'_> {
#[must_use]
pub fn say(&self, key: &str, values: &[(&str, &str)]) -> String {
self.texts.fill(key, self.language, values)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Via {
Interface,
Console,
}
#[derive(Debug)]
pub struct Request<'a> {
pub player: &'a Player,
pub subject: Option<&'a Subject>,
pub args: &'a [Value],
pub language: Language,
pub via: Via,
pub(super) texts: &'a Texts,
}
impl Request<'_> {
#[must_use]
pub fn say(&self, key: &str, values: &[(&str, &str)]) -> String {
self.texts.fill(key, self.language, values)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Outcome {
pub(super) done: bool,
pub(super) text: String,
}
impl Outcome {
#[must_use]
pub fn done(text: impl Into<String>) -> Self {
Self {
done: true,
text: text.into(),
}
}
#[must_use]
pub fn refused(text: impl Into<String>) -> Self {
Self {
done: false,
text: text.into(),
}
}
#[must_use]
pub const fn is_done(&self) -> bool {
self.done
}
#[must_use]
pub fn text(&self) -> &str {
&self.text
}
}
impl From<String> for Outcome {
fn from(text: String) -> Self {
Self::done(text)
}
}
impl From<&str> for Outcome {
fn from(text: &str) -> Self {
Self::done(text)
}
}