1
0
card/src/models.rs
2025-06-08 06:42:03 +09:00

326 lines
7.4 KiB
Rust

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Type};
use uuid::Uuid;
use validator::Validate;
/// Card rarity enum matching Python implementation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type)]
#[sqlx(type_name = "card_rarity", rename_all = "lowercase")]
pub enum CardRarity {
#[serde(rename = "normal")]
Normal,
#[serde(rename = "rare")]
Rare,
#[serde(rename = "super_rare")]
SuperRare,
#[serde(rename = "kira")]
Kira,
#[serde(rename = "unique")]
Unique,
}
impl CardRarity {
pub fn multiplier(&self) -> f64 {
match self {
CardRarity::Normal => 1.0,
CardRarity::Rare => 1.5,
CardRarity::SuperRare => 2.0,
CardRarity::Kira => 3.0,
CardRarity::Unique => 5.0,
}
}
pub fn as_str(&self) -> &'static str {
match self {
CardRarity::Normal => "normal",
CardRarity::Rare => "rare",
CardRarity::SuperRare => "super_rare",
CardRarity::Kira => "kira",
CardRarity::Unique => "unique",
}
}
}
/// Database Models
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct User {
pub id: i32,
pub did: String,
pub handle: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct CardMaster {
pub id: i32,
pub name: String,
pub base_cp_min: i32,
pub base_cp_max: i32,
pub color: String,
pub description: String,
}
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct UserCard {
pub id: i32,
pub user_did: String,
pub card_id: i32,
pub cp: i32,
pub status: CardRarity,
pub skill: Option<String>,
pub obtained_at: DateTime<Utc>,
pub is_unique: bool,
pub unique_id: Option<Uuid>,
}
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct UniqueCardRegistry {
pub id: i32,
pub unique_id: Uuid,
pub card_id: i32,
pub owner_did: String,
pub obtained_at: DateTime<Utc>,
pub verse_skill_id: Option<String>,
}
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct DrawHistory {
pub id: i32,
pub user_did: String,
pub card_id: i32,
pub status: CardRarity,
pub cp: i32,
pub is_paid: bool,
pub drawn_at: DateTime<Utc>,
}
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
pub struct GachaPool {
pub id: i32,
pub name: String,
pub description: String,
pub is_active: bool,
pub start_at: Option<DateTime<Utc>>,
pub end_at: Option<DateTime<Utc>>,
pub pickup_card_ids: Vec<i32>,
pub rate_up_multiplier: f64,
}
/// API Request/Response Models
#[derive(Debug, Deserialize, Validate)]
pub struct LoginRequest {
#[validate(length(min = 1))]
pub identifier: String,
#[validate(length(min = 1))]
pub password: String,
}
#[derive(Debug, Serialize)]
pub struct LoginResponse {
pub access_token: String,
pub token_type: String,
pub expires_in: u64,
pub user: UserInfo,
}
#[derive(Debug, Serialize)]
pub struct UserInfo {
pub did: String,
pub handle: String,
}
#[derive(Debug, Deserialize, Validate)]
pub struct CardDrawRequest {
pub user_did: String,
#[serde(default)]
pub is_paid: bool,
pub pool_id: Option<i32>,
}
#[derive(Debug, Serialize)]
pub struct CardDrawResponse {
pub card: UserCardResponse,
pub master: CardMasterResponse,
pub is_unique: bool,
pub animation_type: String,
pub draw_history_id: i32,
}
#[derive(Debug, Serialize)]
pub struct UserCardResponse {
pub id: i32,
pub card_id: i32,
pub cp: i32,
pub status: CardRarity,
pub skill: Option<String>,
pub obtained_at: DateTime<Utc>,
pub is_unique: bool,
pub unique_id: Option<Uuid>,
}
#[derive(Debug, Serialize)]
pub struct CardMasterResponse {
pub id: i32,
pub name: String,
pub base_cp_min: i32,
pub base_cp_max: i32,
pub color: String,
pub description: String,
}
#[derive(Debug, Serialize)]
pub struct UserCardCollectionResponse {
pub user_did: String,
pub cards: Vec<UserCardWithMaster>,
pub total_count: i32,
pub unique_count: i32,
pub rarity_breakdown: RarityBreakdown,
}
#[derive(Debug, Serialize)]
pub struct UserCardWithMaster {
pub card: UserCardResponse,
pub master: CardMasterResponse,
}
/// Database query result for JOIN operations
#[derive(Debug, Clone, FromRow)]
pub struct UserCardWithMasterQuery {
// user_cards fields
pub id: i32,
pub user_did: String,
pub card_id: i32,
pub cp: i32,
pub status: String,
pub obtained_at: DateTime<Utc>,
pub is_unique: bool,
pub unique_id: Option<Uuid>,
// card_master fields
pub master_id: i32,
pub name: String,
pub base_cp_min: i32,
pub base_cp_max: i32,
pub color: String,
pub description: String,
}
/// Database query result for unique card registry
#[derive(Debug, Clone, FromRow)]
pub struct UniqueCardQuery {
pub card_id: i32,
pub card_name: String,
pub owner_did: Option<String>,
pub owner_handle: Option<String>,
pub obtained_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Serialize)]
pub struct RarityBreakdown {
pub normal: i32,
pub rare: i32,
pub super_rare: i32,
pub kira: i32,
pub unique: i32,
}
#[derive(Debug, Serialize)]
pub struct UniqueCardRegistryResponse {
pub unique_cards: Vec<UniqueCardInfo>,
pub total_unique_cards: i32,
pub available_unique_cards: i32,
}
#[derive(Debug, Serialize)]
pub struct UniqueCardInfo {
pub card_id: i32,
pub card_name: String,
pub owner_did: Option<String>,
pub owner_handle: Option<String>,
pub obtained_at: Option<DateTime<Utc>>,
pub is_available: bool,
}
#[derive(Debug, Serialize)]
pub struct GachaStatsResponse {
pub probabilities: GachaProbabilities,
pub total_draws: i32,
pub total_unique_cards: i32,
pub available_unique_cards: i32,
pub rarity_distribution: RarityBreakdown,
}
#[derive(Debug, Serialize)]
pub struct GachaProbabilities {
pub normal: f64,
pub rare: f64,
pub super_rare: f64,
pub kira: f64,
pub unique: f64,
pub paid_multiplier: f64,
}
/// External Data Models (from ai.json)
#[derive(Debug, Deserialize)]
pub struct ExternalCardData {
pub ai: AiData,
}
#[derive(Debug, Deserialize)]
pub struct AiData {
pub card: CardData,
}
#[derive(Debug, Deserialize)]
pub struct CardData {
pub cards: Vec<ExternalCard>,
}
#[derive(Debug, Deserialize)]
pub struct ExternalCard {
pub id: i32,
pub name: String,
pub cp: CpRange,
pub color: String,
pub skill: String,
pub lang: Option<LangData>,
}
#[derive(Debug, Deserialize)]
pub struct CpRange {
pub min: i32,
pub max: i32,
}
#[derive(Debug, Deserialize)]
pub struct LangData {
pub ja: Option<JapaneseData>,
}
#[derive(Debug, Deserialize)]
pub struct JapaneseData {
pub name: Option<String>,
pub skill: Option<String>,
}
/// atproto Models
#[derive(Debug, Serialize)]
pub struct AtprotoCardRecord {
#[serde(rename = "$type")]
pub record_type: String,
#[serde(rename = "cardId")]
pub card_id: i32,
pub cp: i32,
pub status: String,
#[serde(rename = "obtainedAt")]
pub obtained_at: DateTime<Utc>,
#[serde(rename = "isUnique")]
pub is_unique: bool,
#[serde(rename = "uniqueId")]
pub unique_id: Option<Uuid>,
}