This commit is contained in:
2026-04-29 11:51:04 +08:00
parent e191619ab3
commit 412279ae11
89 changed files with 3966 additions and 491 deletions

View File

@@ -1885,6 +1885,9 @@ pub(crate) fn map_custom_world_library_entry_from_profile_snapshot(
.to_string(),
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
})
}
@@ -1910,6 +1913,9 @@ pub(crate) fn map_custom_world_gallery_entry_snapshot(
.to_string(),
playable_npc_count: snapshot.playable_npc_count,
landmark_count: snapshot.landmark_count,
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
})
}
@@ -2387,6 +2393,8 @@ pub(crate) fn map_puzzle_work_profile(
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
publish_ready: snapshot.publish_ready,
anchor_pack: map_puzzle_anchor_pack(snapshot.anchor_pack),
}
@@ -3937,6 +3945,9 @@ pub struct CustomWorldLibraryEntryRecord {
pub theme_mode: String,
pub playable_npc_count: u32,
pub landmark_count: u32,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -3956,6 +3967,9 @@ pub struct CustomWorldGalleryEntryRecord {
pub theme_mode: String,
pub playable_npc_count: u32,
pub landmark_count: u32,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
}
#[derive(Clone, Debug, PartialEq)]
@@ -4172,6 +4186,23 @@ pub struct CustomWorldProfileUpsertRecordInput {
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfileRemixRecordInput {
pub source_owner_user_id: String,
pub source_profile_id: String,
pub target_owner_user_id: String,
pub target_profile_id: String,
pub author_display_name: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldProfilePlayReportRecordInput {
pub owner_user_id: String,
pub profile_id: String,
pub played_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldPublishWorldRecordInput {
pub session_id: String,
@@ -4334,6 +4365,18 @@ pub struct PuzzleWorkUpsertRecordInput {
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleWorkRemixRecordInput {
pub source_profile_id: String,
pub target_owner_user_id: String,
pub target_session_id: String,
pub target_profile_id: String,
pub target_work_id: String,
pub author_display_name: String,
pub welcome_message_id: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleRunStartRecordInput {
pub run_id: String,
@@ -4376,6 +4419,15 @@ pub struct BigFishPlayReportRecordInput {
pub reported_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigFishWorkRemixRecordInput {
pub source_session_id: String,
pub target_session_id: String,
pub target_owner_user_id: String,
pub welcome_message_id: String,
pub remixed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PuzzleAnchorItemRecord {
pub key: String,
@@ -4502,6 +4554,8 @@ pub struct PuzzleWorkProfileRecord {
pub updated_at: String,
pub published_at: Option<String>,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
pub publish_ready: bool,
pub anchor_pack: PuzzleAnchorPackRecord,
}
@@ -4771,12 +4825,15 @@ pub struct BigFishWorkSummaryRecord {
pub cover_image_src: Option<String>,
pub status: String,
pub updated_at_micros: i64,
pub published_at_micros: Option<i64>,
pub publish_ready: bool,
pub level_count: u32,
pub level_main_image_ready_count: u32,
pub level_motion_ready_count: u32,
pub background_ready: bool,
pub play_count: u32,
pub remix_count: u32,
pub like_count: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
@@ -4791,6 +4848,8 @@ struct CompatibleBigFishWorkSummaryRecord {
cover_image_src: Option<String>,
status: String,
updated_at_micros: i64,
#[serde(default)]
published_at_micros: Option<i64>,
publish_ready: bool,
level_count: u32,
level_main_image_ready_count: u32,
@@ -4798,6 +4857,10 @@ struct CompatibleBigFishWorkSummaryRecord {
background_ready: bool,
#[serde(default)]
play_count: u32,
#[serde(default)]
remix_count: u32,
#[serde(default)]
like_count: u32,
}
impl CompatibleBigFishWorkSummaryRecord {
@@ -4817,12 +4880,15 @@ impl CompatibleBigFishWorkSummaryRecord {
cover_image_src: self.cover_image_src,
status: self.status,
updated_at_micros: self.updated_at_micros,
published_at_micros: self.published_at_micros,
publish_ready: self.publish_ready,
level_count: self.level_count,
level_main_image_ready_count: self.level_main_image_ready_count,
level_motion_ready_count: self.level_motion_ready_count,
background_ready: self.background_ready,
play_count: self.play_count,
remix_count: self.remix_count,
like_count: self.like_count,
}
}
}
@@ -4831,6 +4897,73 @@ impl CompatibleBigFishWorkSummaryRecord {
mod tests {
use super::*;
#[test]
fn puzzle_works_mapper_backfills_missing_public_stat_fields() {
let result = PuzzleWorksProcedureResult {
ok: true,
items_json: Some(
r#"[{
"work_id":"puzzle-work-1",
"profile_id":"puzzle-profile-1",
"owner_user_id":"user-1",
"source_session_id":null,
"author_display_name":"测试作者",
"level_name":"雨夜拼图",
"summary":"旧公开作品摘要",
"theme_tags":["雨夜","猫咪","神庙"],
"cover_image_src":null,
"cover_asset_id":null,
"publication_status":"Published",
"updated_at_micros":123000000,
"published_at_micros":123000000,
"publish_ready":true,
"anchor_pack":{
"theme_promise":{
"key":"themePromise",
"label":"题材承诺",
"value":"雨夜冒险",
"status":"Inferred"
},
"visual_subject":{
"key":"visualSubject",
"label":"画面主体",
"value":"猫咪神庙",
"status":"Inferred"
},
"visual_mood":{
"key":"visualMood",
"label":"视觉气质",
"value":"温暖",
"status":"Inferred"
},
"composition_hooks":{
"key":"compositionHooks",
"label":"拼图记忆点",
"value":"灯光",
"status":"Inferred"
},
"tags_and_forbidden":{
"key":"tagsAndForbidden",
"label":"标签与禁忌",
"value":"雨夜, 猫咪, 神庙",
"status":"Inferred"
}
}
}]"#
.to_string(),
),
error_message: None,
};
let items = map_puzzle_works_procedure_result(result)
.expect("旧 puzzle works JSON 缺统计字段时应按 0 兼容");
assert_eq!(items.len(), 1);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
#[test]
fn big_fish_works_mapper_backfills_missing_owner_user_id_for_private_lists() {
let result = BigFishWorksProcedureResult {
@@ -4861,6 +4994,10 @@ mod tests {
assert_eq!(items.len(), 1);
assert_eq!(items[0].owner_user_id, "user-1");
assert_eq!(items[0].published_at_micros, None);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
#[test]
@@ -4893,6 +5030,10 @@ mod tests {
assert_eq!(items.len(), 1);
assert!(items[0].owner_user_id.is_empty());
assert_eq!(items[0].published_at_micros, None);
assert_eq!(items[0].play_count, 0);
assert_eq!(items[0].remix_count, 0);
assert_eq!(items[0].like_count, 0);
}
}