607 lines
20 KiB
Rust
607 lines
20 KiB
Rust
use super::*;
|
|
|
|
pub(crate) fn map_match3d_agent_session_procedure_result(
|
|
result: Match3DAgentSessionProcedureResult,
|
|
) -> Result<Match3DAgentSessionRecord, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::Procedure(
|
|
result
|
|
.error_message
|
|
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
|
|
));
|
|
}
|
|
|
|
let session = result.session.ok_or_else(|| {
|
|
SpacetimeClientError::Procedure(
|
|
"SpacetimeDB procedure 未返回 match3d agent session 快照".to_string(),
|
|
)
|
|
})?;
|
|
|
|
Ok(map_match3d_agent_session_snapshot(session))
|
|
}
|
|
|
|
pub(crate) fn map_match3d_work_procedure_result(
|
|
result: Match3DWorkProcedureResult,
|
|
) -> Result<Match3DWorkProfileRecord, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::Procedure(
|
|
result
|
|
.error_message
|
|
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
|
|
));
|
|
}
|
|
|
|
let work = result.work.ok_or_else(|| {
|
|
SpacetimeClientError::Procedure(
|
|
"SpacetimeDB procedure 未返回 match3d work 快照".to_string(),
|
|
)
|
|
})?;
|
|
|
|
Ok(map_match3d_work_snapshot(work))
|
|
}
|
|
|
|
pub(crate) fn map_match3d_works_procedure_result(
|
|
result: Match3DWorksProcedureResult,
|
|
) -> Result<Vec<Match3DWorkProfileRecord>, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::Procedure(
|
|
result
|
|
.error_message
|
|
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
|
|
));
|
|
}
|
|
|
|
Ok(result
|
|
.items
|
|
.into_iter()
|
|
.map(map_match3d_work_snapshot)
|
|
.collect())
|
|
}
|
|
|
|
pub(crate) fn map_match3d_run_procedure_result(
|
|
result: Match3DRunProcedureResult,
|
|
) -> Result<Match3DRunRecord, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::Procedure(
|
|
result
|
|
.error_message
|
|
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
|
|
));
|
|
}
|
|
|
|
let run = result.run.ok_or_else(|| {
|
|
SpacetimeClientError::Procedure("SpacetimeDB procedure 未返回 match3d run 快照".to_string())
|
|
})?;
|
|
Ok(map_match3d_run_snapshot(run))
|
|
}
|
|
|
|
pub(crate) fn map_match3d_click_item_procedure_result(
|
|
result: Match3DClickItemProcedureResult,
|
|
) -> Result<Match3DClickConfirmationRecord, SpacetimeClientError> {
|
|
if !result.ok {
|
|
return Err(SpacetimeClientError::Procedure(
|
|
result
|
|
.error_message
|
|
.unwrap_or_else(|| "SpacetimeDB procedure 返回未知错误".to_string()),
|
|
));
|
|
}
|
|
|
|
let run = result.run.ok_or_else(|| {
|
|
SpacetimeClientError::Procedure(
|
|
"SpacetimeDB procedure 未返回 match3d click run 快照".to_string(),
|
|
)
|
|
})?;
|
|
let run = map_match3d_run_snapshot(run);
|
|
let accepted = result.status == "Accepted";
|
|
let accepted_item_instance_id = result.accepted_item_instance_id.clone();
|
|
let entered_slot_index = accepted_item_instance_id.as_deref().and_then(|item_id| {
|
|
run.items
|
|
.iter()
|
|
.find(|item| item.item_instance_id == item_id)
|
|
.and_then(|item| item.tray_slot_index)
|
|
});
|
|
|
|
Ok(Match3DClickConfirmationRecord {
|
|
status: result.status.clone(),
|
|
accepted,
|
|
reject_reason: if accepted { None } else { Some(result.status) },
|
|
accepted_item_instance_id,
|
|
entered_slot_index,
|
|
cleared_item_instance_ids: result.cleared_item_instance_ids,
|
|
failure_reason: result.failure_reason,
|
|
run,
|
|
})
|
|
}
|
|
|
|
fn map_match3d_agent_session_snapshot(
|
|
snapshot: Match3DAgentSessionSnapshot,
|
|
) -> Match3DAgentSessionRecord {
|
|
let config = map_match3d_creator_config(snapshot.config);
|
|
Match3DAgentSessionRecord {
|
|
session_id: snapshot.session_id,
|
|
current_turn: snapshot.current_turn,
|
|
progress_percent: snapshot.progress_percent,
|
|
stage: normalize_match3d_stage(&snapshot.stage).to_string(),
|
|
anchor_pack: build_match3d_anchor_pack(&config),
|
|
draft: snapshot
|
|
.draft
|
|
.map(|draft| map_match3d_result_draft(draft, config.reference_image_src.clone())),
|
|
config: Some(config),
|
|
messages: snapshot
|
|
.messages
|
|
.into_iter()
|
|
.map(map_match3d_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_match3d_creator_config(
|
|
snapshot: Match3DCreatorConfigSnapshot,
|
|
) -> Match3DCreatorConfigRecord {
|
|
Match3DCreatorConfigRecord {
|
|
theme_text: snapshot.theme_text,
|
|
reference_image_src: snapshot.reference_image_src,
|
|
clear_count: snapshot.clear_count,
|
|
difficulty: snapshot.difficulty,
|
|
asset_style_id: snapshot.asset_style_id,
|
|
asset_style_label: snapshot.asset_style_label,
|
|
asset_style_prompt: snapshot.asset_style_prompt,
|
|
generate_click_sound: snapshot.generate_click_sound,
|
|
}
|
|
}
|
|
|
|
fn map_match3d_result_draft(
|
|
snapshot: Match3DDraftSnapshot,
|
|
reference_image_src: Option<String>,
|
|
) -> Match3DResultDraftRecord {
|
|
Match3DResultDraftRecord {
|
|
profile_id: snapshot.profile_id,
|
|
game_name: snapshot.game_name,
|
|
theme_text: snapshot.theme_text,
|
|
summary_text: snapshot.summary_text,
|
|
tags: snapshot.tags,
|
|
cover_image_src: None,
|
|
reference_image_src,
|
|
clear_count: snapshot.clear_count,
|
|
difficulty: snapshot.difficulty,
|
|
generated_item_assets_json: snapshot.generated_item_assets_json,
|
|
total_item_count: snapshot.clear_count.saturating_mul(3),
|
|
publish_ready: false,
|
|
blockers: Vec::new(),
|
|
}
|
|
}
|
|
|
|
fn map_match3d_agent_message_snapshot(
|
|
snapshot: Match3DAgentMessageSnapshot,
|
|
) -> Match3DAgentMessageRecord {
|
|
Match3DAgentMessageRecord {
|
|
message_id: snapshot.message_id,
|
|
role: snapshot.role,
|
|
kind: normalize_match3d_message_kind(&snapshot.kind).to_string(),
|
|
text: snapshot.text,
|
|
created_at: format_timestamp_micros(snapshot.created_at_micros),
|
|
}
|
|
}
|
|
|
|
fn map_match3d_work_snapshot(snapshot: Match3DWorkSnapshot) -> Match3DWorkProfileRecord {
|
|
let config = map_match3d_creator_config(snapshot.config);
|
|
Match3DWorkProfileRecord {
|
|
work_id: snapshot.profile_id.clone(),
|
|
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,
|
|
summary: snapshot.summary_text,
|
|
tags: snapshot.tags,
|
|
cover_image_src: empty_string_to_none(snapshot.cover_image_src),
|
|
cover_asset_id: empty_string_to_none(snapshot.cover_asset_id),
|
|
reference_image_src: config.reference_image_src,
|
|
clear_count: snapshot.clear_count,
|
|
difficulty: snapshot.difficulty,
|
|
publication_status: normalize_match3d_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,
|
|
generated_item_assets_json: snapshot.generated_item_assets_json,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn map_match3d_gallery_view_row(row: Match3DGalleryViewRow) -> Match3DWorkProfileRecord {
|
|
Match3DWorkProfileRecord {
|
|
work_id: row.profile_id.clone(),
|
|
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,
|
|
summary: row.summary_text,
|
|
tags: row.tags,
|
|
cover_image_src: empty_string_to_none(row.cover_image_src),
|
|
cover_asset_id: empty_string_to_none(row.cover_asset_id),
|
|
reference_image_src: row.reference_image_src,
|
|
clear_count: row.clear_count,
|
|
difficulty: row.difficulty,
|
|
publication_status: normalize_match3d_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,
|
|
generated_item_assets_json: row.generated_item_assets_json,
|
|
}
|
|
}
|
|
|
|
fn map_match3d_run_snapshot(snapshot: Match3DRunSnapshot) -> Match3DRunRecord {
|
|
let tray_slots = snapshot
|
|
.tray_slots
|
|
.into_iter()
|
|
.map(map_match3d_tray_slot_snapshot)
|
|
.collect::<Vec<_>>();
|
|
let items = snapshot
|
|
.items
|
|
.into_iter()
|
|
.map(|item| {
|
|
let tray_slot_index = tray_slots
|
|
.iter()
|
|
.find(|slot| {
|
|
slot.item_instance_id.as_deref() == Some(item.item_instance_id.as_str())
|
|
})
|
|
.map(|slot| slot.slot_index);
|
|
map_match3d_item_snapshot(item, tray_slot_index)
|
|
})
|
|
.collect();
|
|
|
|
Match3DRunRecord {
|
|
run_id: snapshot.run_id,
|
|
profile_id: snapshot.profile_id,
|
|
owner_user_id: String::new(),
|
|
status: snapshot.status,
|
|
snapshot_version: u64::from(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),
|
|
clear_count: snapshot.clear_count,
|
|
total_item_count: snapshot.total_item_count,
|
|
cleared_item_count: snapshot.cleared_item_count,
|
|
items,
|
|
tray_slots,
|
|
failure_reason: snapshot.failure_reason,
|
|
last_confirmed_action_id: None,
|
|
}
|
|
}
|
|
|
|
fn map_match3d_item_snapshot(
|
|
snapshot: Match3DItemSnapshot,
|
|
tray_slot_index: Option<u32>,
|
|
) -> Match3DItemSnapshotRecord {
|
|
Match3DItemSnapshotRecord {
|
|
item_instance_id: snapshot.item_instance_id,
|
|
item_type_id: snapshot.item_type_id,
|
|
visual_key: snapshot.visual_key,
|
|
x: snapshot.x,
|
|
y: snapshot.y,
|
|
radius: snapshot.radius,
|
|
layer: snapshot.layer,
|
|
state: snapshot.state,
|
|
clickable: snapshot.clickable,
|
|
tray_slot_index,
|
|
}
|
|
}
|
|
|
|
fn map_match3d_tray_slot_snapshot(snapshot: Match3DTraySlotSnapshot) -> Match3DTraySlotRecord {
|
|
Match3DTraySlotRecord {
|
|
slot_index: snapshot.slot_index,
|
|
item_instance_id: snapshot.item_instance_id,
|
|
item_type_id: snapshot.item_type_id,
|
|
visual_key: snapshot.visual_key,
|
|
}
|
|
}
|
|
|
|
fn build_match3d_anchor_pack(config: &Match3DCreatorConfigRecord) -> Match3DAnchorPackRecord {
|
|
let clear_count = config.clear_count.to_string();
|
|
let difficulty = config.difficulty.to_string();
|
|
Match3DAnchorPackRecord {
|
|
theme: build_match3d_anchor_item("theme", "题材主题", config.theme_text.as_str()),
|
|
clear_count: build_match3d_anchor_item("clearCount", "需要消除次数", clear_count.as_str()),
|
|
difficulty: build_match3d_anchor_item("difficulty", "难度", difficulty.as_str()),
|
|
}
|
|
}
|
|
|
|
fn build_match3d_anchor_item(key: &str, label: &str, value: &str) -> Match3DAnchorItemRecord {
|
|
Match3DAnchorItemRecord {
|
|
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_match3d_stage(value: &str) -> &str {
|
|
match value {
|
|
"Collecting" | "collecting" | "collecting_config" => "collecting_config",
|
|
"ReadyToCompile" | "ready_to_compile" => "ready_to_compile",
|
|
"DraftCompiled" | "draft_compiled" | "draft_ready" => "draft_ready",
|
|
"Published" | "published" => "published",
|
|
_ => value,
|
|
}
|
|
}
|
|
|
|
fn normalize_match3d_publication_status(value: &str) -> &str {
|
|
match value {
|
|
"Draft" | "draft" => "draft",
|
|
"Published" | "published" => "published",
|
|
_ => value,
|
|
}
|
|
}
|
|
|
|
fn normalize_match3d_message_kind(value: &str) -> &str {
|
|
match value {
|
|
"text" => "chat",
|
|
_ => value,
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAgentSessionCreateRecordInput {
|
|
pub session_id: String,
|
|
pub owner_user_id: String,
|
|
pub seed_text: String,
|
|
pub welcome_message_id: String,
|
|
pub welcome_message_text: String,
|
|
pub config_json: Option<String>,
|
|
pub created_at_micros: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAgentMessageSubmitRecordInput {
|
|
pub session_id: String,
|
|
pub owner_user_id: String,
|
|
pub user_message_id: String,
|
|
pub user_message_text: String,
|
|
pub submitted_at_micros: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAgentMessageFinalizeRecordInput {
|
|
pub session_id: String,
|
|
pub owner_user_id: String,
|
|
pub assistant_message_id: Option<String>,
|
|
pub assistant_reply_text: Option<String>,
|
|
pub config_json: Option<String>,
|
|
pub progress_percent: u32,
|
|
pub stage: String,
|
|
pub updated_at_micros: i64,
|
|
pub error_message: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DCompileDraftRecordInput {
|
|
pub session_id: String,
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub author_display_name: String,
|
|
pub game_name: Option<String>,
|
|
pub summary_text: Option<String>,
|
|
pub tags_json: Option<String>,
|
|
pub cover_image_src: Option<String>,
|
|
pub cover_asset_id: Option<String>,
|
|
pub compiled_at_micros: i64,
|
|
pub generated_item_assets_json: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DWorkUpdateRecordInput {
|
|
pub profile_id: String,
|
|
pub owner_user_id: String,
|
|
pub game_name: String,
|
|
pub theme_text: String,
|
|
pub summary_text: String,
|
|
pub tags_json: String,
|
|
pub cover_image_src: String,
|
|
pub cover_asset_id: String,
|
|
pub clear_count: u32,
|
|
pub difficulty: u32,
|
|
pub updated_at_micros: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DRunStartRecordInput {
|
|
pub run_id: String,
|
|
pub owner_user_id: String,
|
|
pub profile_id: String,
|
|
pub started_at_ms: i64,
|
|
pub item_type_count_override: u32,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DRunClickRecordInput {
|
|
pub run_id: String,
|
|
pub owner_user_id: String,
|
|
pub item_instance_id: String,
|
|
pub client_snapshot_version: u32,
|
|
pub client_event_id: String,
|
|
pub clicked_at_ms: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DRunStopRecordInput {
|
|
pub run_id: String,
|
|
pub owner_user_id: String,
|
|
pub stopped_at_ms: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DRunRestartRecordInput {
|
|
pub source_run_id: String,
|
|
pub next_run_id: String,
|
|
pub owner_user_id: String,
|
|
pub restarted_at_ms: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DRunTimeUpRecordInput {
|
|
pub run_id: String,
|
|
pub owner_user_id: String,
|
|
pub finished_at_ms: i64,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAnchorItemRecord {
|
|
pub key: String,
|
|
pub label: String,
|
|
pub value: String,
|
|
pub status: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAnchorPackRecord {
|
|
pub theme: Match3DAnchorItemRecord,
|
|
pub clear_count: Match3DAnchorItemRecord,
|
|
pub difficulty: Match3DAnchorItemRecord,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DCreatorConfigRecord {
|
|
pub theme_text: String,
|
|
pub reference_image_src: Option<String>,
|
|
pub clear_count: u32,
|
|
pub difficulty: u32,
|
|
pub asset_style_id: Option<String>,
|
|
pub asset_style_label: Option<String>,
|
|
pub asset_style_prompt: Option<String>,
|
|
pub generate_click_sound: bool,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DResultDraftRecord {
|
|
pub profile_id: String,
|
|
pub game_name: String,
|
|
pub theme_text: String,
|
|
pub summary_text: String,
|
|
pub tags: Vec<String>,
|
|
pub cover_image_src: Option<String>,
|
|
pub reference_image_src: Option<String>,
|
|
pub clear_count: u32,
|
|
pub difficulty: u32,
|
|
pub generated_item_assets_json: Option<String>,
|
|
pub total_item_count: u32,
|
|
pub publish_ready: bool,
|
|
pub blockers: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAgentMessageRecord {
|
|
pub message_id: String,
|
|
pub role: String,
|
|
pub kind: String,
|
|
pub text: String,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DAgentSessionRecord {
|
|
pub session_id: String,
|
|
pub current_turn: u32,
|
|
pub progress_percent: u32,
|
|
pub stage: String,
|
|
pub anchor_pack: Match3DAnchorPackRecord,
|
|
pub config: Option<Match3DCreatorConfigRecord>,
|
|
pub draft: Option<Match3DResultDraftRecord>,
|
|
pub messages: Vec<Match3DAgentMessageRecord>,
|
|
pub last_assistant_reply: Option<String>,
|
|
pub published_profile_id: Option<String>,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DWorkProfileRecord {
|
|
pub work_id: String,
|
|
pub profile_id: String,
|
|
pub owner_user_id: String,
|
|
pub source_session_id: Option<String>,
|
|
pub author_display_name: String,
|
|
pub game_name: String,
|
|
pub theme_text: String,
|
|
pub summary: String,
|
|
pub tags: Vec<String>,
|
|
pub cover_image_src: Option<String>,
|
|
pub cover_asset_id: Option<String>,
|
|
pub reference_image_src: Option<String>,
|
|
pub clear_count: u32,
|
|
pub difficulty: u32,
|
|
pub publication_status: String,
|
|
pub play_count: u32,
|
|
pub updated_at: String,
|
|
pub published_at: Option<String>,
|
|
pub publish_ready: bool,
|
|
pub generated_item_assets_json: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct Match3DItemSnapshotRecord {
|
|
pub item_instance_id: String,
|
|
pub item_type_id: String,
|
|
pub visual_key: String,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub radius: f32,
|
|
pub layer: u32,
|
|
pub state: String,
|
|
pub clickable: bool,
|
|
pub tray_slot_index: Option<u32>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Match3DTraySlotRecord {
|
|
pub slot_index: u32,
|
|
pub item_instance_id: Option<String>,
|
|
pub item_type_id: Option<String>,
|
|
pub visual_key: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct Match3DRunRecord {
|
|
pub run_id: String,
|
|
pub profile_id: String,
|
|
pub owner_user_id: String,
|
|
pub status: String,
|
|
pub snapshot_version: u64,
|
|
pub started_at_ms: u64,
|
|
pub duration_limit_ms: u64,
|
|
pub server_now_ms: Option<u64>,
|
|
pub remaining_ms: u64,
|
|
pub clear_count: u32,
|
|
pub total_item_count: u32,
|
|
pub cleared_item_count: u32,
|
|
pub items: Vec<Match3DItemSnapshotRecord>,
|
|
pub tray_slots: Vec<Match3DTraySlotRecord>,
|
|
pub failure_reason: Option<String>,
|
|
pub last_confirmed_action_id: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct Match3DClickConfirmationRecord {
|
|
pub status: String,
|
|
pub accepted: bool,
|
|
pub reject_reason: Option<String>,
|
|
pub accepted_item_instance_id: Option<String>,
|
|
pub entered_slot_index: Option<u32>,
|
|
pub cleared_item_instance_ids: Vec<String>,
|
|
pub failure_reason: Option<String>,
|
|
pub run: Match3DRunRecord,
|
|
}
|