Add initial card info structs and dataframe library

This commit is contained in:
2024-04-24 00:07:36 -04:00
parent 0f9ac3627f
commit 8007aca7ff
10 changed files with 151 additions and 5 deletions

View File

@@ -13,12 +13,23 @@ sycamore = { version = "0.8.2", features = [
] } ] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
env_logger = "0.10.0" env_logger = "0.11.3"
log = "0.4.20" log = "0.4.20"
once_cell = "1.18.0" once_cell = "1.18.0"
web-sys = "0.3.64" web-sys = "0.3.64"
cfg-if = "1.0.0" cfg-if = "1.0.0"
chrono = { version = "0.4.31", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
strum = "0.26.2"
strum_macros = "0.26.2"
polars = { version = "0.39.2", default-features = false, features = [
"fmt_no_tty",
"rows",
"lazy",
"concat_str",
"strings",
"csv",
"json",
] }
[target.'cfg(engine)'.dev-dependencies] [target.'cfg(engine)'.dev-dependencies]
fantoccini = "0.19" fantoccini = "0.19"

View File

@@ -45,6 +45,19 @@ To build CSS run:
To build the project for testing, run To build the project for testing, run
`perseus serve --verbose` `perseus serve --verbose`
For server logging:
Windows:
`$Env:RUST_LOG = "info"`
Linux:
`export RUST_LOG=info`
For printing polars tables:
See https://docs.rs/polars/latest/polars/#config-with-env-vars
# Deploying the project # Deploying the project
First run First run

View File

@@ -22,6 +22,7 @@ if not os.path.exists("cards"):
# Download all cards that don't have art # Download all cards that don't have art
FULL_DL_ENDPOINT = "https://images.ygoprodeck.com/images/cards/{}.jpg" FULL_DL_ENDPOINT = "https://images.ygoprodeck.com/images/cards/{}.jpg"
SMALL_DL_ENDPOINT = "https://images.ygoprodeck.com/images/cards_small/{}.jpg" SMALL_DL_ENDPOINT = "https://images.ygoprodeck.com/images/cards_small/{}.jpg"
INNER_ART_ENDPOINT = "https://images.ygoprodeck.com/images/cards_cropped/{}.jpg"
for card_json in card_data["data"]: for card_json in card_data["data"]:
print(f"Downloading {card_json['name']}") print(f"Downloading {card_json['name']}")
@@ -38,10 +39,13 @@ for card_json in card_data["data"]:
try: try:
full_img = requests.get(FULL_DL_ENDPOINT.format(image_to_download)).content full_img = requests.get(FULL_DL_ENDPOINT.format(image_to_download)).content
smol_img = requests.get(SMALL_DL_ENDPOINT.format(image_to_download)).content smol_img = requests.get(SMALL_DL_ENDPOINT.format(image_to_download)).content
inner_img = requests.get(INNER_ART_ENDPOINT.format(image_to_download)).content
with open(f"cards/{image_to_download}/full.jpg", "wb") as file: with open(f"cards/{image_to_download}/full.jpg", "wb") as file:
file.write(full_img) file.write(full_img)
with open(f"cards/{image_to_download}/small.jpg", "wb") as file: with open(f"cards/{image_to_download}/small.jpg", "wb") as file:
file.write(smol_img) file.write(smol_img)
with open(f"cards/{image_to_download}/inner.jpg", "wb") as file:
file.write(inner_img)
except Exception as e: except Exception as e:
shutil.rmtree('cards/{image_to_download}', ignore_errors=True) shutil.rmtree('cards/{image_to_download}', ignore_errors=True)
print(f"ERROR: Failed to download {image_to_download}. {str(e)}") print(f"ERROR: Failed to download {image_to_download}. {str(e)}")

View File

@@ -11,6 +11,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"tailwindcss": "^3.3.3" "tailwindcss": "^3.4.1"
} }
} }

View File

@@ -27,6 +27,9 @@ pub fn Layout<'a, G: Html>(
a(href = "inventory", a(href = "inventory",
class = "mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0" class = "mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0"
) { "Inventory" } ) { "Inventory" }
a(href = "tournaments",
class = "mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0"
) { "Tournaments" }
} }
} }
} }

102
src/data/card.rs Normal file
View File

@@ -0,0 +1,102 @@
use once_cell::sync::Lazy;
use polars::prelude::*;
use serde::{Deserialize, Serialize};
use std::io::Cursor;
use std::{collections::HashMap, hash::Hash};
#[cfg(engine)]
use std::fs;
#[cfg(engine)]
use std::path::Path;
enum CartType {
NormalMonster,
EffectMonster,
SpellCard,
TrapCard,
Unknown { name: String },
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CardSet {
pub id: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ArchetypeInfo {
pub name: String,
pub num_cards: u32,
pub cards: Vec<u32>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CardInfo {
pub id: u32,
pub name: String,
pub card_sets: Vec<CardSet>,
pub archetype: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CardInstance {
card_id: u32,
set_id: String,
}
pub struct CardTable {
pub cards: HashMap<u32, CardInfo>,
pub sets: HashMap<u32, CardSet>,
pub archetypes: HashMap<String, ArchetypeInfo>,
pub df: DataFrame,
}
impl CardTable {
#[cfg(engine)]
pub fn new_from_server_json(path: &Path) -> Self {
// First load json into initial dataframe
// TODO list all required files
let raw_df = JsonReader::new(std::fs::File::open("./data/cardinfo.json").unwrap())
.finish()
.unwrap();
let raw_df = raw_df
.lazy()
.select(&[col("data")])
.explode(vec!["data"])
.unnest(vec!["data"])
.collect()
.unwrap();
log::info!("{:?}", &raw_df);
let id_col = UInt32Chunked::new("id_row", &[1]).into_series();
let cards = HashMap::new();
let sets = HashMap::new();
let archetypes = HashMap::new();
let df = DataFrame::new(vec![id_col]).unwrap();
Self {
cards,
sets,
archetypes,
df,
}
}
#[cfg(client)]
pub fn new_from_client_json() -> Self {
let id_col = UInt32Chunked::new("id_row", &[1]).into_series();
let cards = HashMap::new();
let sets = HashMap::new();
let archetypes = HashMap::new();
let df = DataFrame::new(vec![id_col]).unwrap();
Self {
cards,
sets,
archetypes,
df,
}
}
}

View File

@@ -1,4 +1,5 @@
pub mod user; pub mod user;
pub mod card;
#[cfg(engine)] #[cfg(engine)]
pub mod store; pub mod store;

View File

@@ -6,9 +6,16 @@ mod error_views;
mod server; mod server;
mod templates; mod templates;
use std::path::Path;
use data::card::CardTable;
use perseus::prelude::*; use perseus::prelude::*;
use sycamore::prelude::view; use sycamore::prelude::view;
extern crate strum;
#[macro_use]
extern crate strum_macros;
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(engine)] { if #[cfg(engine)] {
use std::net::SocketAddr; use std::net::SocketAddr;
@@ -35,6 +42,9 @@ pub async fn dflt_server<M: MutableStore + 'static, T: TranslationsManager + 'st
app = register_routes(app); app = register_routes(app);
// TODO move to server global
CardTable::new_from_server_json(Path::new("./data/cardinfo.json"));
axum::Server::bind(&addr) axum::Server::bind(&addr)
.serve(app.into_make_service()) .serve(app.into_make_service())
.await .await

View File

@@ -13,7 +13,9 @@ cfg_if::cfg_if! {
#[derive(Serialize, Deserialize, ReactiveState, Clone)] #[derive(Serialize, Deserialize, ReactiveState, Clone)]
#[rx(alias = "AppStateRx")] #[rx(alias = "AppStateRx")]
pub struct AppState {} pub struct AppState {
}
pub fn get_global_state_creator() -> GlobalStateCreator { pub fn get_global_state_creator() -> GlobalStateCreator {
GlobalStateCreator::new() GlobalStateCreator::new()

View File

@@ -1,3 +1,3 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind variants; @tailwind utilities;