use maj::{gemini, server::Error, Response}; use rand::seq::SliceRandom; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone, Debug)] struct Card { name: String, name_short: String, #[serde(rename = "value_int")] value: u16, meaning_up: String, meaning_rev: String, meaning: Option, #[serde(rename = "type")] kind: String, #[serde(default)] upright: bool, } struct Deck { cards: Vec, } #[derive(Serialize, Deserialize, Clone, Debug)] struct Container { count: u32, cards: Vec, } impl Deck { fn new() -> Result { let ctr: Container = serde_json::from_str(include_str!("./tarot.json"))?; let mut deck = ctr.cards; deck.shuffle(&mut thread_rng()); Ok(Deck { cards: deck }) } fn draw(&mut self) -> Card { let face = thread_rng().gen::() % 2; let mut card = self.cards.pop().unwrap(); card.upright = face == 0; if !card.upright { card.name = format!("{} (reversed)", card.name); card.meaning = Some(card.meaning_rev.clone()); } else { card.meaning = Some(card.meaning_up.clone()); } card } } pub async fn character() -> Result { let mut d = Deck::new()?; let history = d.draw(); let recent = d.draw(); let current = d.draw(); let b = gemini::Builder::new() .heading(1, "RPG Character Backstory Generator") .text("Stuck coming up with a plausible backstory for a character? Try this generator out. Each of these categories lists a series of descriptors describing various stages of the character's life: their life history, some recent major event in their life and their current state/mood. This should be all you need to flesh out a believeable NPC's dialogue.") .text("") .heading(2, "Background / History") .text(format!("{}{}", history.name, history.meaning.unwrap())) .text("") .heading(2, "Recent Events") .text(format!("{}{}", recent.name, recent.meaning.unwrap())) .text("") .heading(2, "Current Situation") .text(format!("{}{}", current.name, current.meaning.unwrap())) .text("") .link( "/tools/character_gen", Some("Make a new character".to_string()), ); Ok(Response::render(b.build())) }