83 lines
2.4 KiB
Rust
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()))
|
||
|
}
|