maj/site/src/server/tarot.rs

83 lines
2.4 KiB
Rust

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<String>,
#[serde(rename = "type")]
kind: String,
#[serde(default)]
upright: bool,
}
struct Deck {
cards: Vec<Card>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
struct Container {
count: u32,
cards: Vec<Card>,
}
impl Deck {
fn new() -> Result<Self, serde_json::Error> {
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::<u8>() % 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<Response, Error> {
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()))
}