From 9c3275cdba08a012c961ee7ca79776da664f16d3 Mon Sep 17 00:00:00 2001 From: Qrimpuff Date: Sat, 30 Nov 2024 19:39:56 -0500 Subject: [PATCH] include starter decks and better intro --- README.md | 4 +- index.html | 4 +- src/main.rs | 46 ++++++++++- src/sources/mod.rs | 2 + src/sources/starter_decks.rs | 156 +++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 src/sources/starter_decks.rs diff --git a/README.md b/README.md index 9122aca..945e4b1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # hololive OCG Deck Converter -Convert your hOCG deck into various formats. +Convert your hOCG deck between various formats. https://qrimpuff.github.io/hocg-deck-convert/ @@ -24,4 +24,4 @@ Run the following command in the root of the project to start the Dioxus dev ser dx serve --hot-reload ``` -- Open the browser to http://localhost:8080 \ No newline at end of file +- Open the browser to http://localhost:8080/hocg-deck-convert \ No newline at end of file diff --git a/index.html b/index.html index a48d21f..9742540 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ {app_title} + content="hololive OCG Deck Converter - Convert your hOCG deck between various formats, such as Deck Log, holoDelta, HoloDuel, or even print proxy sheets."> @@ -13,7 +13,7 @@ + content='"hololive OCG Deck Converter" allows you to convert your hOCG deck between various formats, such as Deck Log, holoDelta, HoloDuel, or even print proxy sheets.'> diff --git a/src/main.rs b/src/main.rs index 0a7bd5f..e22a1e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,7 +44,42 @@ fn App() -> Element { div { class: "container", h1 { class: "title", "hololive OCG Deck Converter" } div { class: "block", - "Convert your hOCG deck into various formats, such as Deck Log, holoDelta, HoloDuel, or even proxy sheets." + p { + "Convert your hOCG deck between various formats, such as " + a { + href: "https://decklog-en.bushiroad.com/ja/create?c=108", + target: "_blank", + "Deck Log" + } + ", " + a { + href: "https://github.com/GabeJWJ/holoDelta", + target: "_blank", + "holoDelta" + } + ", " + a { + href: "https://daktagames.itch.io/holoduel", + target: "_blank", + "HoloDuel" + } + ", or even print proxy sheets." + } + p { class: "is-hidden-mobile", + "You can also choose one of the official starter decks to get you started." + } + p { + "If you have any questions about the game, consider joining the " + a { + href: "https://discord.com/invite/GJ9RhA22nP", + target: "_blank", + span { class: "icon", + i { class: "fa-brands fa-discord" } + } + "Hololive OCG Fan Server" + } + "." + } } div { class: "columns is-tablet", div { class: "column is-two-fifths", @@ -130,6 +165,7 @@ fn Form(card_lang: Signal) -> Element { *SHOW_PRICE.write() = false; *import_format .write() = match ev.value().as_str() { + "starter_decks" => Some(DeckType::StarterDecks), "deck_log" => Some(DeckType::DeckLog), "holo_delta" => Some(DeckType::HoloDelta), "holo_duel" => Some(DeckType::HoloDuel), @@ -138,6 +174,7 @@ fn Form(card_lang: Signal) -> Element { _ => None, }; }, + option { value: "starter_decks", "Starter decks" } option { initial_selected: true, value: "deck_log", "Deck Log (Bushiroad)" } option { value: "holo_delta", "holoDelta" } option { value: "holo_duel", "HoloDuel" } @@ -149,6 +186,13 @@ fn Form(card_lang: Signal) -> Element { } div { + if *import_format.read() == Some(DeckType::StarterDecks) { + starter_decks::Import { + common_deck: COMMON_DECK.signal(), + map: CARDS_INFO.signal(), + show_price: SHOW_PRICE.signal() + } + } if *import_format.read() == Some(DeckType::DeckLog) { deck_log::Import { common_deck: COMMON_DECK.signal(), diff --git a/src/sources/mod.rs b/src/sources/mod.rs index 3a9a8bc..0267d27 100644 --- a/src/sources/mod.rs +++ b/src/sources/mod.rs @@ -16,10 +16,12 @@ pub mod holoduel; pub mod json; pub mod price_check; pub mod proxy_sheets; +pub mod starter_decks; pub mod tabletop_sim; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DeckType { + StarterDecks, DeckLog, HoloDelta, HoloDuel, diff --git a/src/sources/starter_decks.rs b/src/sources/starter_decks.rs new file mode 100644 index 0000000..d0fa22d --- /dev/null +++ b/src/sources/starter_decks.rs @@ -0,0 +1,156 @@ +use std::sync::OnceLock; + +use dioxus::prelude::*; +use dioxus_logger::tracing::debug; +use serde::Serialize; + +use crate::{track_convert_event, EventType}; + +use super::{CardsInfoMap, CommonCards, CommonDeck}; + +#[derive(Debug, Clone)] +struct DeckEntry { + deck_id: String, + display: String, + deck: CommonDeck, +} + +fn starter_decks(map: &CardsInfoMap) -> &'static Vec { + static DECKS: OnceLock> = OnceLock::new(); + DECKS.get_or_init(|| { + vec![ + // hSD01 - スタートデッキ「ときのそら&AZKi」(Sora oshi) + DeckEntry { + deck_id: "hSD01-001".into(), + display: "hSD01 - スタートデッキ「ときのそら&AZKi」 (Sora oshi)".into(), + deck: CommonDeck { + name: Some("スタートデッキ「ときのそら&AZKi」".into()), + oshi: CommonCards::from_card_number("hSD01-001".into(), 1, map), + main_deck: vec![ + CommonCards::from_card_number("hSD01-003".into(), 4, map), + CommonCards::from_card_number("hSD01-004".into(), 3, map), + CommonCards::from_card_number("hSD01-005".into(), 3, map), + CommonCards::from_card_number("hSD01-006".into(), 2, map), + CommonCards::from_card_number("hSD01-007".into(), 2, map), + CommonCards::from_card_number("hSD01-008".into(), 4, map), + CommonCards::from_card_number("hSD01-009".into(), 3, map), + CommonCards::from_card_number("hSD01-010".into(), 3, map), + CommonCards::from_card_number("hSD01-011".into(), 2, map), + CommonCards::from_card_number("hSD01-012".into(), 2, map), + CommonCards::from_card_number("hSD01-013".into(), 2, map), + CommonCards::from_card_number("hSD01-014".into(), 2, map), + CommonCards::from_card_number("hSD01-015".into(), 2, map), + CommonCards::from_card_number("hSD01-016".into(), 3, map), + CommonCards::from_card_number("hSD01-017".into(), 3, map), + CommonCards::from_card_number("hSD01-018".into(), 3, map), + CommonCards::from_card_number("hSD01-019".into(), 3, map), + CommonCards::from_card_number("hSD01-020".into(), 2, map), + CommonCards::from_card_number("hSD01-021".into(), 2, map), + ], + cheer_deck: vec![ + CommonCards::from_card_number("hY01-001".into(), 10, map), + CommonCards::from_card_number("hY02-001".into(), 10, map), + ], + }, + }, + // hSD01 - スタートデッキ「ときのそら&AZKi」(AZKi oshi) + DeckEntry { + deck_id: "hSD01-002".into(), + display: "hSD01 - スタートデッキ「ときのそら&AZKi」 (AZKi oshi)".into(), + deck: CommonDeck { + name: Some("スタートデッキ「ときのそら&AZKi」".into()), + oshi: CommonCards::from_card_number("hSD01-002".into(), 1, map), + main_deck: vec![ + CommonCards::from_card_number("hSD01-003".into(), 4, map), + CommonCards::from_card_number("hSD01-004".into(), 3, map), + CommonCards::from_card_number("hSD01-005".into(), 3, map), + CommonCards::from_card_number("hSD01-006".into(), 2, map), + CommonCards::from_card_number("hSD01-007".into(), 2, map), + CommonCards::from_card_number("hSD01-008".into(), 4, map), + CommonCards::from_card_number("hSD01-009".into(), 3, map), + CommonCards::from_card_number("hSD01-010".into(), 3, map), + CommonCards::from_card_number("hSD01-011".into(), 2, map), + CommonCards::from_card_number("hSD01-012".into(), 2, map), + CommonCards::from_card_number("hSD01-013".into(), 2, map), + CommonCards::from_card_number("hSD01-014".into(), 2, map), + CommonCards::from_card_number("hSD01-015".into(), 2, map), + CommonCards::from_card_number("hSD01-016".into(), 3, map), + CommonCards::from_card_number("hSD01-017".into(), 3, map), + CommonCards::from_card_number("hSD01-018".into(), 3, map), + CommonCards::from_card_number("hSD01-019".into(), 3, map), + CommonCards::from_card_number("hSD01-020".into(), 2, map), + CommonCards::from_card_number("hSD01-021".into(), 2, map), + ], + cheer_deck: vec![ + CommonCards::from_card_number("hY01-001".into(), 10, map), + CommonCards::from_card_number("hY02-001".into(), 10, map), + ], + }, + }, + ] + }) +} + +#[component] +pub fn Import( + mut common_deck: Signal>, + map: Signal, + show_price: Signal, +) -> Element { + #[derive(Serialize)] + struct EventData { + format: &'static str, + deck_id: String, + } + + let mut starter_deck_idx: Signal> = use_signal(|| Some(0)); + let mut loading = use_signal(|| false); + + let mut load_deck = move || { + *loading.write() = true; + + let deck = starter_deck_idx + .read() + .as_ref() + .and_then(|idx| starter_decks(&map.read()).get(*idx)); + + debug!("{:?}", deck); + if let Some(deck) = deck { + track_convert_event( + EventType::Import, + EventData { + format: "Stater deck", + deck_id: deck.deck_id.clone(), + }, + ); + } + *common_deck.write() = deck.map(|d| d.deck.clone()); + + *show_price.write() = false; + *loading.write() = false; + }; + + if common_deck.read().is_none() { + load_deck(); + } + + rsx! { + div { class: "field", + label { "for": "starter_deck", class: "label", "Starter deck" } + div { class: "control", + div { class: "select", + select { + id: "starter_deck", + oninput: move |ev| { + *starter_deck_idx.write() = ev.value().parse().ok(); + load_deck(); + }, + for (idx , deck) in starter_decks(&map.read()).iter().enumerate() { + option { value: "{idx}", "{deck.display}" } + } + } + } + } + } + } +}