use std::collections::HashSet;
use serde::Deserialize;
use strum::{EnumIter, IntoEnumIterator, EnumProperty, EnumIs};
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RawStamp {
id: usize,
seq: usize,
name: String,
description: Option<String>,
stamp_type: String,
assetbundle_name: String,
balloon_assetbundle_name: String,
// ignored by us, used in sekai-viewer UI
archive_published_at: usize,
// ignored by us, used in sekai-viewer UI
archive_display_type: Option<String>,
character_id_1: Option<Character>,
character_id_2: Option<Character>,
game_character_unit_id: Option<Character>
}
impl RawStamp {
pub fn to_stamp(self) -> Stamp {
use StampCharacter::*;
let RawStamp { id, seq,
name, description, stamp_type,
assetbundle_name, balloon_assetbundle_name,
character_id_1, character_id_2, game_character_unit_id, .. } = self;
let character = match (character_id_1, character_id_2, game_character_unit_id) {
(None, None, None)
=> Nobody,
(Some(character_id), None, None)
=> Solo{character_id},
(Some(character_id_1), Some(character_id_2), None)
=> Duo{character_id_1, character_id_2},
(Some(character_id), None, Some(game_character_unit_id))
=> SoloExtra{character_id, game_character_unit_id},
(None, None, Some(game_character_unit_id))
=> GCUID{game_character_unit_id},
x => { panic!("They added a new character format: {x:?}"); }
};
Stamp { id, seq,
name, description, stamp_type,
assetbundle_name, balloon_assetbundle_name,
character }
}
}
#[derive(Clone, Debug, Default)]
pub struct Stamp {
pub id: usize,
pub seq: usize,
pub name: String,
pub description: Option<String>,
pub stamp_type: String,
pub assetbundle_name: String,
pub balloon_assetbundle_name: String,
pub character: StampCharacter
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Hash, EnumIs)]
pub enum StampCharacter {
#[default]
Nobody,
Solo{character_id: Character},
Duo{character_id_1: Character, character_id_2: Character},
SoloExtra{character_id: Character, game_character_unit_id: Character},
GCUID{game_character_unit_id: Character},
}
impl std::fmt::Display for StampCharacter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Self::Nobody => write!(f, "text"),
Self::Solo{character_id} => write!(f, "{}", character_id.get_str("prefix").unwrap()),
Self::Duo{character_id_1, character_id_2} => write!(f, "{}_{}", character_id_1.get_str("prefix").unwrap(), character_id_2.get_str("prefix").unwrap()),
Self::SoloExtra{game_character_unit_id, ..} => write!(f, "{}", game_character_unit_id.get_str("prefix").unwrap()),
Self::GCUID{game_character_unit_id} => write!(f, "text_{}", game_character_unit_id.get_str("prefix").unwrap())
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Hash, EnumIter, EnumProperty)]
#[repr(u8)]
#[serde(from = "u8")]
pub enum Character {
// Leo / Need
#[strum(props(prefix = "ichika", name_en = "Ichika Hoshino"))]
Ichika = 1,
#[strum(props(prefix = "saki", name_en = "Saki Tenma"))]
Saki = 2,
#[strum(props(prefix = "honami", name_en = "Honami Mochizuki"))]
Honami = 3,
#[strum(props(prefix = "shiho", name_en = "Shiho Hinomori"))]
Shiho = 4,
// MORE MORE JUMP!
#[strum(props(prefix = "minori", name_en = "Minori Hanasato"))]
Minori = 5,
#[strum(props(prefix = "haruka", name_en = "Haruka Kiritani"))]
Haruka = 6,
#[strum(props(prefix = "airi", name_en = "Airi Momoi"))]
Airi = 7,
#[strum(props(prefix = "shizuku", name_en = "Shizuku Hinomori"))]
Shizuku = 8,
// Vivid BAD SQUAD
#[strum(props(prefix = "kohane", name_en = "Kohane Azusawa"))]
Kohane = 9,
#[strum(props(prefix = "an", name_en = "An Shiraishi"))]
An = 10,
#[strum(props(prefix = "akito", name_en = "Akito Shinonome"))]
Akito = 11,
#[strum(props(prefix = "toya", name_en = "Toya Aoyagi"))]
Toya = 12,
// Wonderlands x Showtime
#[strum(props(prefix = "tsukasa", name_en = "Tsukasa Tenma"))]
Tsukasa = 13,
#[strum(props(prefix = "emu", name_en = "Emu Otori"))]
Emu = 14,
#[strum(props(prefix = "nene", name_en = "Nene Kusanagi"))]
Nene = 15,
#[strum(props(prefix = "rui", name_en = "Rui Kamishiro"))]
Rui = 16,
// Nightcord at 25:00
#[strum(props(prefix = "kanade", name_en = "Kanade Yoisaki"))]
Kanade = 17,
#[strum(props(prefix = "mafuyu", name_en = "Mafuyu Asahina"))]
Mafuyu = 18,
#[strum(props(prefix = "ena", name_en = "Ena Shinonome"))]
Ena = 19,
#[strum(props(prefix = "mizuki", name_en = "Mizuki Akiyama"))]
Mizuki = 20,
// VOCALOID
#[strum(props(prefix = "miku", name_en = "Hatsune Miku"))]
Miku = 21,
#[strum(props(prefix = "rin", name_en = "Kagamine Rin"))]
Rin = 22,
#[strum(props(prefix = "len", name_en = "Kagamine Len"))]
Len = 23,
#[strum(props(prefix = "luka", name_en = "Megurine Luka"))]
Luka = 24,
#[strum(props(prefix = "meiko", name_en = "MEIKO"))]
MEIKO = 25,
#[strum(props(prefix = "kaito", name_en = "KAITO"))]
KAITO = 26,
// "Game Character Unit ID"
// Basically just, character IDs associated to a particular group
// - Miku
#[strum(props(prefix = "ln_miku", name_en = "Leo / Need Miku"))]
LnMiku = 27,
#[strum(props(prefix = "mmj_miku", name_en = "MORE MORE JUMP! Miku"))]
MmjMiku = 28,
#[strum(props(prefix = "vbs_miku", name_en = "Vivid BAD SQUAD Miku"))]
VbsMiku = 29,
#[strum(props(prefix = "wxs_miku", name_en = "Wonderlands x Showtime Miku"))]
WxsMiku = 30,
#[strum(props(prefix = "n25_miku", name_en = "Nightcord at 25:00 Miku"))]
N25Miku = 31,
// - Rin
#[strum(props(prefix = "ln_rin", name_en = "Leo / Need Rin"))]
LnRin = 32,
#[strum(props(prefix = "mmj_rin", name_en = "MORE MORE JUMP! Rin"))]
MmjRin = 33,
#[strum(props(prefix = "vbs_rin", name_en = "Vivid BAD SQUAD Rin"))]
VbsRin = 34,
#[strum(props(prefix = "wxs_rin", name_en = "Wonderlands x Showtime Rin"))]
WxsRin = 35,
#[strum(props(prefix = "n25_rin", name_en = "Nightcord at 25:00 Rin"))]
N25Rin = 36,
// - Len
#[strum(props(prefix = "ln_len", name_en = "Leo / Need Len"))]
LnLen = 37,
#[strum(props(prefix = "mmj_len", name_en = "MORE MORE JUMP! Len"))]
MmjLen = 38,
#[strum(props(prefix = "vbs_len", name_en = "Vivid BAD SQUAD Len"))]
VbsLen = 39,
#[strum(props(prefix = "wxs_len", name_en = "Wonderlands x Showtime Len"))]
WxsLen = 40,
#[strum(props(prefix = "n25_len", name_en = "Nightcord at 25:00 Len"))]
N25Len = 41,
// - Luka
#[strum(props(prefix = "ln_luka", name_en = "Leo / Need Luka"))]
LnLuka = 42,
#[strum(props(prefix = "mmj_luka", name_en = "MORE MORE JUMP! Luka"))]
MmjLuka = 43,
#[strum(props(prefix = "vbs_luka", name_en = "Vivid BAD SQUAD Luka"))]
VbsLuka = 44,
#[strum(props(prefix = "wxs_luka", name_en = "Wonderlands x Showtime Luka"))]
WxsLuka = 45,
#[strum(props(prefix = "n25_luka", name_en = "Nightcord at 25:00 Luka"))]
N25Luka = 46,
// - MEIKO
#[strum(props(prefix = "ln_meiko", name_en = "Leo / Need MEIKO"))]
LnMEIKO = 47,
#[strum(props(prefix = "mmj_meiko", name_en = "MORE MORE JUMP! MEIKO"))]
MmjMEIKO = 48,
#[strum(props(prefix = "vbs_meiko", name_en = "Vivid BAD SQUAD MEIKO"))]
VbsMEIKO = 49,
#[strum(props(prefix = "wxs_meiko", name_en = "Wonderlands x Showtime MEIKO"))]
WxsMEIKO = 50,
#[strum(props(prefix = "n25_meiko", name_en = "Nightcord at 25:00 MEIKO"))]
N25MEIKO = 51,
// - KAITO
#[strum(props(prefix = "ln_kaito", name_en = "Leo / Need KAITO"))]
LnKAITO = 52,
#[strum(props(prefix = "mmj_kaito", name_en = "MORE MORE JUMP! KAITO"))]
MmjKAITO = 53,
#[strum(props(prefix = "vbs_kaito", name_en = "Vivid BAD SQUAD KAITO"))]
VbsKAITO = 54,
#[strum(props(prefix = "wxs_kaito", name_en = "Wonderlands x Showtime KAITO"))]
WxsKAITO = 55,
#[strum(props(prefix = "n25_kaito", name_en = "Nightcord at 25:00 KAITO"))]
N25KAITO = 56,
}
impl From<u8> for Character {
fn from(val: u8) -> Self {
for var in Self::iter() {
if var as u8 == val {
return var;
}
}
panic!("Unknown Character ID: {val}");
}
}
impl std::fmt::Display for Character {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{self:?}")
}
}
impl Stamp {
}