use super::*; pub(crate) fn map_square_hole_agent_session_procedure_result( result: SquareHoleAgentSessionProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let session = result .session .ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole agent session 快照"))?; Ok(map_square_hole_agent_session_snapshot(session)) } pub(crate) fn map_square_hole_work_procedure_result( result: SquareHoleWorkProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let work = result .work .ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole work 快照"))?; Ok(map_square_hole_work_snapshot(work)) } pub(crate) fn map_square_hole_works_procedure_result( result: SquareHoleWorksProcedureResult, ) -> Result, SpacetimeClientError> { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } Ok(result .items .into_iter() .map(map_square_hole_work_snapshot) .collect()) } pub(crate) fn map_square_hole_run_procedure_result( result: SquareHoleRunProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let run = result .run .ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole run 快照"))?; Ok(map_square_hole_run_snapshot(run)) } pub(crate) fn map_square_hole_drop_shape_procedure_result( result: SquareHoleDropShapeProcedureResult, ) -> Result { if !result.ok { return Err(SpacetimeClientError::procedure_failed(result.error_message)); } let run = result .run .ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop run 快照"))?; let feedback = result .feedback .ok_or_else(|| SpacetimeClientError::missing_snapshot("square hole drop feedback 快照"))?; let run = map_square_hole_run_snapshot(run); Ok(SquareHoleDropConfirmationRecord { status: result.status, accepted: feedback.accepted, reject_reason: feedback.reject_reason.clone(), failure_reason: result.failure_reason, feedback: map_square_hole_feedback_snapshot(feedback), run, }) } fn map_square_hole_agent_session_snapshot( snapshot: SquareHoleAgentSessionSnapshot, ) -> SquareHoleAgentSessionRecord { let config = map_square_hole_creator_config(snapshot.config); SquareHoleAgentSessionRecord { session_id: snapshot.session_id, current_turn: snapshot.current_turn, progress_percent: snapshot.progress_percent, stage: normalize_square_hole_stage(&snapshot.stage).to_string(), anchor_pack: build_square_hole_anchor_pack(&config), config, draft: snapshot.draft.map(map_square_hole_result_draft), messages: snapshot .messages .into_iter() .map(map_square_hole_agent_message_snapshot) .collect(), last_assistant_reply: empty_string_to_none(snapshot.last_assistant_reply), published_profile_id: snapshot.published_profile_id, updated_at: format_timestamp_micros(snapshot.updated_at_micros), } } fn map_square_hole_creator_config( snapshot: SquareHoleCreatorConfigSnapshot, ) -> SquareHoleCreatorConfigRecord { SquareHoleCreatorConfigRecord { theme_text: snapshot.theme_text, twist_rule: snapshot.twist_rule, shape_count: snapshot.shape_count, difficulty: snapshot.difficulty, shape_options: snapshot .shape_options .into_iter() .map(map_square_hole_shape_option) .collect(), hole_options: snapshot .hole_options .into_iter() .map(map_square_hole_hole_option) .collect(), background_prompt: snapshot.background_prompt, cover_image_src: empty_string_to_none(snapshot.cover_image_src), background_image_src: empty_string_to_none(snapshot.background_image_src), } } fn map_square_hole_result_draft(snapshot: SquareHoleDraftSnapshot) -> SquareHoleResultDraftRecord { SquareHoleResultDraftRecord { profile_id: snapshot.profile_id, game_name: snapshot.game_name, theme_text: snapshot.theme_text, twist_rule: snapshot.twist_rule, summary: snapshot.summary_text, tags: snapshot.tags, cover_image_src: empty_string_to_none(snapshot.cover_image_src), background_prompt: snapshot.background_prompt, background_image_src: empty_string_to_none(snapshot.background_image_src), shape_options: snapshot .shape_options .into_iter() .map(map_square_hole_shape_option) .collect(), hole_options: snapshot .hole_options .into_iter() .map(map_square_hole_hole_option) .collect(), shape_count: snapshot.shape_count, difficulty: snapshot.difficulty, publish_ready: false, blockers: Vec::new(), } } fn map_square_hole_agent_message_snapshot( snapshot: SquareHoleAgentMessageSnapshot, ) -> SquareHoleAgentMessageRecord { SquareHoleAgentMessageRecord { id: snapshot.message_id, role: snapshot.role, kind: normalize_square_hole_message_kind(&snapshot.kind).to_string(), text: snapshot.text, created_at: format_timestamp_micros(snapshot.created_at_micros), } } fn map_square_hole_work_snapshot(snapshot: SquareHoleWorkSnapshot) -> SquareHoleWorkProfileRecord { SquareHoleWorkProfileRecord { work_id: snapshot.work_id, profile_id: snapshot.profile_id, owner_user_id: snapshot.owner_user_id, source_session_id: empty_string_to_none(snapshot.source_session_id), author_display_name: snapshot.author_display_name, game_name: snapshot.game_name, theme_text: snapshot.theme_text, twist_rule: snapshot.twist_rule, summary: snapshot.summary_text, tags: snapshot.tags, cover_image_src: empty_string_to_none(snapshot.cover_image_src), background_prompt: snapshot.background_prompt, background_image_src: empty_string_to_none(snapshot.background_image_src), shape_options: snapshot .shape_options .into_iter() .map(map_square_hole_shape_option) .collect(), hole_options: snapshot .hole_options .into_iter() .map(map_square_hole_hole_option) .collect(), shape_count: snapshot.shape_count, difficulty: snapshot.difficulty, publication_status: normalize_square_hole_publication_status(&snapshot.publication_status) .to_string(), play_count: snapshot.play_count, updated_at: format_timestamp_micros(snapshot.updated_at_micros), published_at: snapshot.published_at_micros.map(format_timestamp_micros), publish_ready: snapshot.publish_ready, } } pub(crate) fn map_square_hole_gallery_view_row( row: SquareHoleGalleryViewRow, ) -> SquareHoleWorkProfileRecord { SquareHoleWorkProfileRecord { work_id: row.work_id, profile_id: row.profile_id, owner_user_id: row.owner_user_id, source_session_id: empty_string_to_none(row.source_session_id), author_display_name: row.author_display_name, game_name: row.game_name, theme_text: row.theme_text, twist_rule: row.twist_rule, summary: row.summary_text, tags: row.tags, cover_image_src: empty_string_to_none(row.cover_image_src), background_prompt: row.background_prompt, background_image_src: empty_string_to_none(row.background_image_src), shape_options: row .shape_options .into_iter() .map(map_square_hole_shape_option) .collect(), hole_options: row .hole_options .into_iter() .map(map_square_hole_hole_option) .collect(), shape_count: row.shape_count, difficulty: row.difficulty, publication_status: normalize_square_hole_publication_status(&row.publication_status) .to_string(), play_count: row.play_count, updated_at: format_timestamp_micros(row.updated_at_micros), published_at: row.published_at_micros.map(format_timestamp_micros), publish_ready: row.publish_ready, } } fn map_square_hole_run_snapshot(snapshot: SquareHoleRunSnapshot) -> SquareHoleRunRecord { SquareHoleRunRecord { run_id: snapshot.run_id, profile_id: snapshot.profile_id, owner_user_id: snapshot.owner_user_id, status: normalize_square_hole_run_status(&snapshot.status).to_string(), snapshot_version: snapshot.snapshot_version, started_at_ms: i64_to_u64_ms(snapshot.started_at_ms), duration_limit_ms: i64_to_u64_ms(snapshot.duration_limit_ms), server_now_ms: Some(i64_to_u64_ms(snapshot.server_now_ms)), remaining_ms: i64_to_u64_ms(snapshot.remaining_ms), total_shape_count: snapshot.total_shape_count, completed_shape_count: snapshot.completed_shape_count, combo: snapshot.combo, best_combo: snapshot.best_combo, score: snapshot.score, rule_label: snapshot.rule_label, background_image_src: empty_string_to_none(snapshot.background_image_src), current_shape: snapshot.current_shape.map(map_square_hole_shape_snapshot), holes: snapshot .holes .into_iter() .map(map_square_hole_hole_snapshot) .collect(), last_feedback: snapshot .last_feedback .map(map_square_hole_feedback_snapshot), last_confirmed_action_id: None, } } fn map_square_hole_shape_snapshot( snapshot: SquareHoleShapeSnapshot, ) -> SquareHoleShapeSnapshotRecord { SquareHoleShapeSnapshotRecord { shape_id: snapshot.shape_id, shape_kind: snapshot.shape_kind, label: snapshot.label, target_hole_id: snapshot.target_hole_id, color: snapshot.color, image_src: empty_string_to_none(snapshot.image_src), } } fn map_square_hole_hole_snapshot(snapshot: SquareHoleHoleSnapshot) -> SquareHoleHoleSnapshotRecord { SquareHoleHoleSnapshotRecord { hole_id: snapshot.hole_id, hole_kind: snapshot.hole_kind, label: snapshot.label, x: snapshot.x, y: snapshot.y, image_src: empty_string_to_none(snapshot.image_src), } } fn map_square_hole_shape_option( snapshot: SquareHoleShapeOptionSnapshot, ) -> SquareHoleShapeOptionRecord { SquareHoleShapeOptionRecord { option_id: snapshot.option_id, shape_kind: snapshot.shape_kind, label: snapshot.label, target_hole_id: snapshot.target_hole_id, image_prompt: snapshot.image_prompt, image_src: empty_string_to_none(snapshot.image_src), } } fn map_square_hole_hole_option( snapshot: SquareHoleHoleOptionSnapshot, ) -> SquareHoleHoleOptionRecord { SquareHoleHoleOptionRecord { hole_id: snapshot.hole_id, hole_kind: snapshot.hole_kind, label: snapshot.label, image_prompt: snapshot.image_prompt, image_src: empty_string_to_none(snapshot.image_src), } } fn map_square_hole_feedback_snapshot( snapshot: SquareHoleDropFeedbackSnapshot, ) -> SquareHoleDropFeedbackRecord { SquareHoleDropFeedbackRecord { accepted: snapshot.accepted, reject_reason: snapshot .reject_reason .map(|value| normalize_square_hole_reject_reason(&value).to_string()), message: snapshot.message, } } fn build_square_hole_anchor_pack( config: &SquareHoleCreatorConfigRecord, ) -> SquareHoleAnchorPackRecord { let shape_count = config.shape_count.to_string(); let difficulty = config.difficulty.to_string(); SquareHoleAnchorPackRecord { theme: build_square_hole_anchor_item("theme", "题材主题", config.theme_text.as_str()), twist_rule: build_square_hole_anchor_item( "twistRule", "反差规则", config.twist_rule.as_str(), ), shape_count: build_square_hole_anchor_item("shapeCount", "形状数量", shape_count.as_str()), difficulty: build_square_hole_anchor_item("difficulty", "难度", difficulty.as_str()), } } fn build_square_hole_anchor_item( key: &str, label: &str, value: &str, ) -> SquareHoleAnchorItemRecord { SquareHoleAnchorItemRecord { key: key.to_string(), label: label.to_string(), value: value.to_string(), status: if value.trim().is_empty() { "missing" } else { "confirmed" } .to_string(), } } fn normalize_square_hole_stage(value: &str) -> &str { match value { "Collecting" | "CollectingConfig" | "collecting" | "collecting_config" => { "collecting_config" } "ReadyToCompile" | "ready_to_compile" => "ready_to_compile", "DraftCompiled" | "DraftReady" | "draft_compiled" | "draft_ready" => "draft_ready", "Published" | "published" => "published", _ => value, } } fn normalize_square_hole_publication_status(value: &str) -> &str { match value { "Draft" | "draft" => "draft", "Published" | "published" => "published", _ => value, } } fn normalize_square_hole_run_status(value: &str) -> &str { match value { "Running" | "running" => "running", "Won" | "won" => "won", "Failed" | "failed" => "failed", "Stopped" | "stopped" => "stopped", _ => value, } } fn normalize_square_hole_message_kind(value: &str) -> &str { match value { "text" => "chat", _ => value, } } fn normalize_square_hole_reject_reason(value: &str) -> &str { match value { "RunNotActive" | "run_not_active" => "run_not_active", "SnapshotVersionMismatch" | "snapshot_version_mismatch" => "snapshot_version_mismatch", "HoleNotFound" | "hole_not_found" => "hole_not_found", "Incompatible" | "incompatible" => "incompatible", "TimeUp" | "time_up" => "time_up", _ => value, } }