use shared_kernel::{normalize_optional_string, normalize_required_string, normalize_string_list}; use crate::{ MATCH3D_MAX_DIFFICULTY, MATCH3D_MIN_DIFFICULTY, Match3DCreatorConfig, Match3DFieldError, Match3DResultDraft, }; pub fn build_creator_config( theme_text: &str, reference_image_src: Option, clear_count: u32, difficulty: u32, ) -> Result { let theme_text = normalize_required_string(theme_text).ok_or(Match3DFieldError::MissingText)?; if clear_count == 0 { return Err(Match3DFieldError::InvalidClearCount); } if !(MATCH3D_MIN_DIFFICULTY..=MATCH3D_MAX_DIFFICULTY).contains(&difficulty) { return Err(Match3DFieldError::InvalidDifficulty); } Ok(Match3DCreatorConfig { theme_text, reference_image_src: normalize_optional_string(reference_image_src), clear_count, difficulty, }) } /// 根据已确认的题材、消除次数和难度编译首版结果草稿。 pub fn validate_publish_requirements(draft: &Match3DResultDraft) -> Vec { let mut blockers = validate_result_publish_fields(draft); if draft.clear_count == 0 { blockers.push("需要消除次数必须为正整数".to_string()); } if !(MATCH3D_MIN_DIFFICULTY..=MATCH3D_MAX_DIFFICULTY).contains(&draft.difficulty) { blockers.push("难度必须在 1 到 10 之间".to_string()); } blockers } /// 将结果草稿转换为可保存的作品 profile,实际持久化由 SpacetimeDB 分支负责。 pub(crate) fn validate_basic_publish_fields( game_name: &str, summary: &str, tags: &[String], ) -> Vec { let mut blockers = Vec::new(); if normalize_required_string(game_name).is_none() { blockers.push("游戏名称不能为空".to_string()); } if normalize_required_string(summary).is_none() { blockers.push("简介不能为空".to_string()); } let normalized_tags = normalize_string_list(tags.to_vec()); if normalized_tags.is_empty() { blockers.push("至少需要 1 个标签".to_string()); } blockers } pub(crate) fn validate_result_publish_fields(draft: &Match3DResultDraft) -> Vec { let mut blockers = validate_basic_publish_fields(&draft.game_name, &draft.summary, &draft.tags); if draft .cover_image_src .as_deref() .and_then(normalize_required_string) .is_none() { blockers.push("封面图不能为空".to_string()); } blockers } pub(crate) fn default_tags_for_theme(theme_text: &str) -> Vec { let mut tags = vec![ "抓大鹅".to_string(), "经典消除".to_string(), theme_text.to_string(), ]; tags.sort(); tags.dedup(); tags }