落地方洞挑战图片与运行态交互
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
kdletters
2026-05-06 12:51:28 +08:00
parent 60b667a9d1
commit d06107f2c6
51 changed files with 2590 additions and 989 deletions

View File

@@ -84,6 +84,7 @@ struct SquareHoleAgentShapeOptionOutput {
option_id: String,
shape_kind: String,
label: String,
target_hole_id: String,
image_prompt: String,
#[serde(default)]
image_src: String,
@@ -95,8 +96,9 @@ struct SquareHoleAgentHoleOptionOutput {
hole_id: String,
hole_kind: String,
label: String,
image_prompt: String,
#[serde(default)]
bonus: bool,
image_src: String,
}
pub(crate) async fn run_square_hole_agent_turn<F>(
@@ -195,12 +197,12 @@ fn parse_model_config(
));
}
let theme_text = read_text_field(value, "themeText")
.unwrap_or_else(|| session.config.theme_text.clone());
let twist_rule = read_text_field(value, "twistRule")
.unwrap_or_else(|| session.config.twist_rule.clone());
let shape_options = parse_shape_options(value, session, &theme_text);
let hole_options = parse_hole_options(value, session);
let theme_text =
read_text_field(value, "themeText").unwrap_or_else(|| session.config.theme_text.clone());
let twist_rule =
read_text_field(value, "twistRule").unwrap_or_else(|| session.config.twist_rule.clone());
let hole_options = parse_hole_options(value, session, &theme_text);
let shape_options = parse_shape_options(value, session, &theme_text, hole_options.as_slice());
let background_prompt = read_text_field(value, "backgroundPrompt")
.or_else(|| {
session
@@ -243,6 +245,7 @@ fn parse_shape_options(
value: &JsonValue,
session: &SquareHoleAgentSessionRecord,
theme_text: &str,
hole_options: &[SquareHoleHoleOption],
) -> Vec<SquareHoleShapeOption> {
let parsed = value
.get("shapeOptions")
@@ -258,8 +261,19 @@ fn parse_shape_options(
.unwrap_or_else(|| fallback_shape_kind(index).to_string()),
label: read_text_field(item, "label")
.unwrap_or_else(|| fallback_shape_label(index).to_string()),
target_hole_id: read_text_field(item, "targetHoleId")
.filter(|value| hole_options.iter().any(|option| option.hole_id == *value))
.unwrap_or_else(|| {
hole_options
.get(index % hole_options.len().max(1))
.map(|option| option.hole_id.clone())
.unwrap_or_else(|| fallback_target_hole_id(index).to_string())
}),
image_prompt: read_text_field(item, "imagePrompt").unwrap_or_else(|| {
format!("{theme_text}主题的{}贴纸图,透明背景,明亮游戏资产", fallback_shape_label(index))
format!(
"{theme_text}主题的{}贴纸图,透明背景,明亮游戏资产",
fallback_shape_label(index)
)
}),
image_src: read_text_field(item, "imageSrc"),
})
@@ -274,18 +288,20 @@ fn parse_shape_options(
option_id: option.option_id.clone(),
shape_kind: option.shape_kind.clone(),
label: option.label.clone(),
target_hole_id: option.target_hole_id.clone(),
image_prompt: option.image_prompt.clone(),
image_src: option.image_src.clone(),
})
.collect()
});
normalize_shape_options(parsed, theme_text)
normalize_shape_options(parsed, theme_text, hole_options)
}
fn parse_hole_options(
value: &JsonValue,
session: &SquareHoleAgentSessionRecord,
theme_text: &str,
) -> Vec<SquareHoleHoleOption> {
let parsed = value
.get("holeOptions")
@@ -298,13 +314,16 @@ fn parse_hole_options(
hole_id: read_text_field(item, "holeId")
.unwrap_or_else(|| format!("hole-option-{index}")),
hole_kind: read_text_field(item, "holeKind")
.unwrap_or_else(|| fallback_shape_kind(index).to_string()),
.unwrap_or_else(|| format!("hole-{}", index + 1)),
label: read_text_field(item, "label")
.unwrap_or_else(|| fallback_hole_label(index).to_string()),
bonus: item
.get("bonus")
.and_then(JsonValue::as_bool)
.unwrap_or(index == 0),
image_prompt: read_text_field(item, "imagePrompt").unwrap_or_else(|| {
format!(
"{theme_text}主题的{}贴纸图,透明背景,明亮游戏资产",
fallback_hole_label(index)
)
}),
image_src: read_text_field(item, "imageSrc"),
})
.collect::<Vec<_>>()
})
@@ -317,12 +336,13 @@ fn parse_hole_options(
hole_id: option.hole_id.clone(),
hole_kind: option.hole_kind.clone(),
label: option.label.clone(),
bonus: option.bonus,
image_prompt: option.image_prompt.clone(),
image_src: option.image_src.clone(),
})
.collect()
});
normalize_hole_options(parsed)
normalize_hole_options(parsed, theme_text)
}
fn read_text_field(value: &JsonValue, field_name: &str) -> Option<String> {
@@ -363,14 +383,15 @@ fn fallback_shape_label(index: usize) -> &'static str {
}
}
fn fallback_hole_label(index: usize) -> &'static str {
match fallback_shape_kind(index) {
"square" => "方洞",
"circle" => "圆洞",
"triangle" => "三角洞",
"diamond" => "菱形洞",
"star" => "星形洞",
_ => "拱形洞",
fn fallback_hole_label(index: usize) -> String {
format!("洞口 {}", index + 1)
}
fn fallback_target_hole_id(index: usize) -> &'static str {
match index % 3 {
0 => "hole-1",
1 => "hole-2",
_ => "hole-3",
}
}
@@ -380,6 +401,7 @@ impl From<SquareHoleShapeOption> for SquareHoleAgentShapeOptionOutput {
option_id: option.option_id,
shape_kind: option.shape_kind,
label: option.label,
target_hole_id: option.target_hole_id,
image_prompt: option.image_prompt,
image_src: option.image_src.unwrap_or_default(),
}
@@ -392,7 +414,8 @@ impl From<SquareHoleHoleOption> for SquareHoleAgentHoleOptionOutput {
hole_id: option.hole_id,
hole_kind: option.hole_kind,
label: option.label,
bonus: option.bonus,
image_prompt: option.image_prompt,
image_src: option.image_src.unwrap_or_default(),
}
}
}
@@ -472,15 +495,16 @@ mod tests {
"optionId": "stamp",
"shapeKind": "circle",
"label": "圆形印章",
"targetHoleId": "folder",
"imagePrompt": "办公室圆形印章贴纸"
}
],
"holeOptions": [
{
"holeId": "folder",
"holeKind": "square",
"holeKind": "folder",
"label": "档案盒方洞",
"bonus": true
"imagePrompt": "办公室档案盒洞口贴纸"
}
],
"backgroundPrompt": "办公室桌面纸箱玩具背景"
@@ -501,8 +525,12 @@ mod tests {
assert_eq!(output.next_config.difficulty, 6);
assert!(output.next_config.shape_options.len() >= 6);
assert_eq!(output.next_config.shape_options[0].label, "圆形印章");
assert_eq!(output.next_config.shape_options[0].target_hole_id, "folder");
assert_eq!(output.next_config.hole_options[0].label, "档案盒方洞");
assert!(output.next_config.hole_options[0].bonus);
assert_eq!(
output.next_config.hole_options[0].image_prompt,
"办公室档案盒洞口贴纸"
);
assert_eq!(
output.next_config.background_prompt,
"办公室桌面纸箱玩具背景"