按后台配置扣除创作泥点
前端创作表单泥点预校验改为读取入口契约配置 拼图和抓大鹅初始生成后端扣费改为解析后台配置 汪汪声浪初始三图生成按入口总成本拆分扣费 创作工作台按钮和确认弹窗展示后台配置泥点成本 补充泥点扣费回归测试并同步文档与共享记忆
This commit is contained in:
@@ -36,7 +36,7 @@ use time::{Duration as TimeDuration, OffsetDateTime};
|
||||
|
||||
use crate::{
|
||||
api_response::json_success_body,
|
||||
asset_billing::execute_billable_asset_operation,
|
||||
asset_billing::execute_billable_asset_operation_with_cost,
|
||||
auth::AuthenticatedAccessToken,
|
||||
generated_image_assets::{
|
||||
GeneratedImageAssetAdapter, GeneratedImageAssetDataUrl,
|
||||
@@ -62,6 +62,8 @@ const BARK_BATTLE_RUN_ID_PREFIX: &str = "bark-battle-run-";
|
||||
const BARK_BATTLE_RUN_TOKEN_PREFIX: &str = "bark-battle-token-";
|
||||
const BARK_BATTLE_IMAGE_ID_PREFIX: &str = "bark-battle-image-";
|
||||
const BARK_BATTLE_PLAY_TYPE_ID: &str = "bark-battle";
|
||||
const BARK_BATTLE_INITIAL_DRAFT_GENERATION_BILLING_PURPOSE: &str = "initial_draft_generation";
|
||||
const BARK_BATTLE_INITIAL_DRAFT_GENERATION_SLOT_COUNT: u64 = 3;
|
||||
const BARK_BATTLE_RUN_TTL_SECONDS: i64 = 10 * 60;
|
||||
const BARK_BATTLE_CHARACTER_IMAGE_SIZE: &str = "1024*1024";
|
||||
const BARK_BATTLE_BACKGROUND_IMAGE_SIZE: &str = "1024*1792";
|
||||
@@ -303,11 +305,13 @@ pub async fn generate_bark_battle_image_asset(
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(ToString::to_string);
|
||||
let result = execute_billable_asset_operation(
|
||||
let points_cost = resolve_bark_battle_image_asset_points_cost(&state, &payload).await;
|
||||
let result = execute_billable_asset_operation_with_cost(
|
||||
&state,
|
||||
&owner_user_id,
|
||||
bark_battle_slot_asset_kind(&slot),
|
||||
asset_id.as_str(),
|
||||
points_cost,
|
||||
async {
|
||||
generate_and_persist_bark_battle_image_asset(
|
||||
&state,
|
||||
@@ -328,6 +332,40 @@ pub async fn generate_bark_battle_image_asset(
|
||||
Ok(json_success_body(Some(&request_context), result))
|
||||
}
|
||||
|
||||
async fn resolve_bark_battle_image_asset_points_cost(
|
||||
state: &AppState,
|
||||
payload: &BarkBattleImageAssetGenerateRequest,
|
||||
) -> u64 {
|
||||
if payload.billing_purpose.as_deref()
|
||||
!= Some(BARK_BATTLE_INITIAL_DRAFT_GENERATION_BILLING_PURPOSE)
|
||||
{
|
||||
return crate::asset_billing::ASSET_OPERATION_POINTS_COST;
|
||||
}
|
||||
|
||||
let total_cost = crate::creation_entry_config::resolve_creation_entry_mud_point_cost(
|
||||
state,
|
||||
BARK_BATTLE_PLAY_TYPE_ID,
|
||||
BARK_BATTLE_INITIAL_DRAFT_GENERATION_SLOT_COUNT
|
||||
* crate::asset_billing::ASSET_OPERATION_POINTS_COST,
|
||||
)
|
||||
.await;
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(&payload.slot, total_cost)
|
||||
}
|
||||
|
||||
fn resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
slot: &BarkBattleAssetSlot,
|
||||
total_cost: u64,
|
||||
) -> u64 {
|
||||
let base_cost = total_cost / BARK_BATTLE_INITIAL_DRAFT_GENERATION_SLOT_COUNT;
|
||||
let remainder = total_cost % BARK_BATTLE_INITIAL_DRAFT_GENERATION_SLOT_COUNT;
|
||||
let slot_index = match slot {
|
||||
BarkBattleAssetSlot::PlayerCharacter => 0,
|
||||
BarkBattleAssetSlot::OpponentCharacter => 1,
|
||||
BarkBattleAssetSlot::UiBackground => 2,
|
||||
};
|
||||
base_cost + u64::from(slot_index < remainder)
|
||||
}
|
||||
|
||||
pub async fn publish_bark_battle_work(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
@@ -1661,6 +1699,94 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_generation_slot_cost_splits_creation_entry_total_cost() {
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::PlayerCharacter,
|
||||
1,
|
||||
),
|
||||
1,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::OpponentCharacter,
|
||||
1,
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::UiBackground,
|
||||
1,
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::PlayerCharacter,
|
||||
2,
|
||||
),
|
||||
1,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::OpponentCharacter,
|
||||
2,
|
||||
),
|
||||
1,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::UiBackground,
|
||||
2,
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::PlayerCharacter,
|
||||
6,
|
||||
),
|
||||
2,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::OpponentCharacter,
|
||||
6,
|
||||
),
|
||||
2,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::UiBackground,
|
||||
6,
|
||||
),
|
||||
2,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::PlayerCharacter,
|
||||
8,
|
||||
),
|
||||
3,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::OpponentCharacter,
|
||||
8,
|
||||
),
|
||||
3,
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_bark_battle_initial_generation_slot_points_cost(
|
||||
&BarkBattleAssetSlot::UiBackground,
|
||||
8,
|
||||
),
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draft_config_mapping_includes_stable_work_identity() {
|
||||
let request_context = RequestContext::new(
|
||||
|
||||
Reference in New Issue
Block a user