1
This commit is contained in:
@@ -3459,6 +3459,19 @@ pub fn current_puzzle_unix_micros() -> i64 {
|
||||
(current_unix_ms() as i64).saturating_mul(1_000)
|
||||
}
|
||||
|
||||
pub fn puzzle_point_incentive_claimable_points(total_half_points: u64, claimed_points: u64) -> u64 {
|
||||
total_half_points
|
||||
.saturating_div(2)
|
||||
.saturating_sub(claimed_points)
|
||||
}
|
||||
|
||||
pub fn puzzle_point_incentive_total_after_spend(
|
||||
total_half_points: u64,
|
||||
spent_points: u64,
|
||||
) -> u64 {
|
||||
total_half_points.saturating_add(spent_points)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -3779,6 +3792,16 @@ mod tests {
|
||||
assert_ne!(first_positions, second_positions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn puzzle_point_incentive_uses_half_points_and_floor_claimable() {
|
||||
// 中文注释:累计单位是 half point,消耗 1 个陶泥币只让作者获得 0.5 个待结算陶泥币。
|
||||
assert_eq!(puzzle_point_incentive_total_after_spend(0, 1), 1);
|
||||
assert_eq!(puzzle_point_incentive_claimable_points(1, 0), 0);
|
||||
assert_eq!(puzzle_point_incentive_claimable_points(2, 0), 1);
|
||||
assert_eq!(puzzle_point_incentive_claimable_points(5, 1), 1);
|
||||
assert_eq!(puzzle_point_incentive_claimable_points(5, 2), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_board_has_no_original_neighbor_pairs() {
|
||||
for grid_size in PUZZLE_SUPPORTED_GRID_SIZES {
|
||||
|
||||
@@ -26,20 +26,20 @@ pub use mapper::{
|
||||
CustomWorldPublishGateRecord, CustomWorldPublishWorldRecord,
|
||||
CustomWorldPublishWorldRecordInput, CustomWorldPublishedProfileCompileRecord,
|
||||
CustomWorldResultPreviewBlockerRecord, CustomWorldSupportedActionRecord,
|
||||
CustomWorldWorkSummaryRecord, NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord,
|
||||
CustomWorldWorkSummaryRecord, Match3DAgentMessageFinalizeRecordInput,
|
||||
Match3DAgentMessageRecord, Match3DAgentMessageSubmitRecordInput,
|
||||
Match3DAgentSessionCreateRecordInput, Match3DAgentSessionRecord, Match3DAnchorItemRecord,
|
||||
Match3DAnchorPackRecord, Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput,
|
||||
Match3DCreatorConfigRecord, Match3DItemSnapshotRecord, Match3DResultDraftRecord,
|
||||
Match3DRunClickRecordInput, Match3DRunRecord, Match3DRunRestartRecordInput,
|
||||
Match3DRunStartRecordInput, Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput,
|
||||
Match3DTraySlotRecord, Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput,
|
||||
NpcBattleInteractionRecord, NpcInteractionRecord, NpcStateRecord,
|
||||
PuzzleAgentMessageFinalizeRecordInput, PuzzleAgentMessageRecord,
|
||||
PuzzleAgentMessageSubmitRecordInput, PuzzleAgentSessionCreateRecordInput,
|
||||
PuzzleAgentSessionRecord, PuzzleAgentSuggestedActionRecord, PuzzleAnchorItemRecord,
|
||||
PuzzleAnchorPackRecord, PuzzleBoardRecord, PuzzleCellPositionRecord, PuzzleCreatorIntentRecord,
|
||||
PuzzleDraftLevelRecord, PuzzleFormDraftRecord, PuzzleFormDraftSaveRecordInput,
|
||||
Match3DAgentMessageFinalizeRecordInput, Match3DAgentMessageRecord,
|
||||
Match3DAgentMessageSubmitRecordInput, Match3DAgentSessionCreateRecordInput,
|
||||
Match3DAgentSessionRecord, Match3DAnchorItemRecord, Match3DAnchorPackRecord,
|
||||
Match3DClickConfirmationRecord, Match3DCompileDraftRecordInput, Match3DCreatorConfigRecord,
|
||||
Match3DItemSnapshotRecord, Match3DResultDraftRecord, Match3DRunClickRecordInput,
|
||||
Match3DRunRecord, Match3DRunRestartRecordInput, Match3DRunStartRecordInput,
|
||||
Match3DRunStopRecordInput, Match3DRunTimeUpRecordInput, Match3DTraySlotRecord,
|
||||
Match3DWorkProfileRecord, Match3DWorkUpdateRecordInput,
|
||||
PuzzleGeneratedImageCandidateRecord, PuzzleGeneratedImagesSaveRecordInput,
|
||||
PuzzleLeaderboardEntryRecord, PuzzleLeaderboardSubmitRecordInput, PuzzleMergedGroupRecord,
|
||||
PuzzlePieceStateRecord, PuzzlePublishRecordInput, PuzzleRecommendedNextWorkRecord,
|
||||
|
||||
@@ -2,17 +2,23 @@
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::runtime_profile_invite_code_admin_procedure_result_type::RuntimeProfileInviteCodeAdminProcedureResult;
|
||||
use super::runtime_profile_invite_code_admin_upsert_input_type::RuntimeProfileInviteCodeAdminUpsertInput;
|
||||
use super::runtime_profile_invite_code_admin_procedure_result_type::RuntimeProfileInviteCodeAdminProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct AdminUpsertProfileInviteCodeArgs {
|
||||
struct AdminUpsertProfileInviteCodeArgs {
|
||||
pub input: RuntimeProfileInviteCodeAdminUpsertInput,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for AdminUpsertProfileInviteCodeArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -22,19 +28,16 @@ impl __sdk::InModule for AdminUpsertProfileInviteCodeArgs {
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait admin_upsert_profile_invite_code {
|
||||
fn admin_upsert_profile_invite_code(&self, input: RuntimeProfileInviteCodeAdminUpsertInput) {
|
||||
self.admin_upsert_profile_invite_code_then(input, |_, _| {});
|
||||
fn admin_upsert_profile_invite_code(&self, input: RuntimeProfileInviteCodeAdminUpsertInput,
|
||||
) {
|
||||
self.admin_upsert_profile_invite_code_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn admin_upsert_profile_invite_code_then(
|
||||
&self,
|
||||
input: RuntimeProfileInviteCodeAdminUpsertInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<RuntimeProfileInviteCodeAdminProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<RuntimeProfileInviteCodeAdminProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,17 +46,12 @@ impl admin_upsert_profile_invite_code for super::RemoteProcedures {
|
||||
&self,
|
||||
input: RuntimeProfileInviteCodeAdminUpsertInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<RuntimeProfileInviteCodeAdminProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
__callback: impl FnOnce(&super::ProcedureEventContext, Result<RuntimeProfileInviteCodeAdminProcedureResult, __sdk::InternalError>) + Send + 'static,
|
||||
) {
|
||||
self.imp
|
||||
.invoke_procedure_with_callback::<_, RuntimeProfileInviteCodeAdminProcedureResult>(
|
||||
"admin_upsert_profile_invite_code",
|
||||
AdminUpsertProfileInviteCodeArgs { input },
|
||||
__callback,
|
||||
);
|
||||
self.imp.invoke_procedure_with_callback::<_, RuntimeProfileInviteCodeAdminProcedureResult>(
|
||||
"admin_upsert_profile_invite_code",
|
||||
AdminUpsertProfileInviteCodeArgs { input, },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
use super::runtime_profile_invite_code_snapshot_type::RuntimeProfileInviteCodeSnapshot;
|
||||
|
||||
@@ -10,10 +15,11 @@ use super::runtime_profile_invite_code_snapshot_type::RuntimeProfileInviteCodeSn
|
||||
#[sats(crate = __lib)]
|
||||
pub struct RuntimeProfileInviteCodeAdminProcedureResult {
|
||||
pub ok: bool,
|
||||
pub record: Option<RuntimeProfileInviteCodeSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
pub record: Option::<RuntimeProfileInviteCodeSnapshot>,
|
||||
pub error_message: Option::<String>,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for RuntimeProfileInviteCodeAdminProcedureResult {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
@@ -13,6 +19,7 @@ pub struct RuntimeProfileInviteCodeAdminUpsertInput {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for RuntimeProfileInviteCodeAdminUpsertInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
use spacetimedb_sdk::__codegen::{
|
||||
self as __sdk,
|
||||
__lib,
|
||||
__sats,
|
||||
__ws,
|
||||
};
|
||||
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
@@ -14,6 +20,7 @@ pub struct RuntimeProfileInviteCodeSnapshot {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
|
||||
impl __sdk::InModule for RuntimeProfileInviteCodeSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
@@ -1911,7 +1911,7 @@ fn claim_puzzle_work_point_incentive_tx(
|
||||
return Err("无权领取该作品的积分激励".to_string());
|
||||
}
|
||||
|
||||
let claimable_points = puzzle_point_incentive_claimable_points(
|
||||
let claimable_points = module_puzzle::puzzle_point_incentive_claimable_points(
|
||||
row.point_incentive_total_half_points,
|
||||
row.point_incentive_claimed_points,
|
||||
);
|
||||
@@ -2571,9 +2571,9 @@ fn upsert_puzzle_profile_save_archive(
|
||||
"runtimeKind": "puzzle",
|
||||
"runId": run.run_id,
|
||||
"entryProfileId": run.entry_profile_id,
|
||||
"currentProfileId": target.profile_id,
|
||||
"currentProfileId": target.profile_id.clone(),
|
||||
"currentLevelIndex": target.level_index,
|
||||
"currentLevelId": target.level_id,
|
||||
"currentLevelId": target.level_id.clone(),
|
||||
"status": target.status.as_str(),
|
||||
}))
|
||||
.unwrap_or_else(|_| "{}".to_string());
|
||||
@@ -2613,6 +2613,8 @@ fn resolve_puzzle_archive_target(
|
||||
run: &PuzzleRunSnapshot,
|
||||
current_level: &module_puzzle::PuzzleRuntimeLevelSnapshot,
|
||||
) -> Result<PuzzleArchiveTarget, String> {
|
||||
// 中文注释:通关后若已经算出同作品下一关,存档页直接投影到下一关入口;
|
||||
// 跨作品候选需要玩家选择,不能在存档里提前替玩家切换作品。
|
||||
let owner_user_id = resolve_puzzle_current_owner_user_id(ctx, ¤t_level.profile_id);
|
||||
if current_level.status != PuzzleRuntimeLevelStatus::Cleared {
|
||||
return Ok(PuzzleArchiveTarget {
|
||||
@@ -2697,12 +2699,6 @@ fn puzzle_archive_summary_text(status: PuzzleRuntimeLevelStatus) -> String {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn puzzle_point_incentive_claimable_points(total_half_points: u64, claimed_points: u64) -> u64 {
|
||||
total_half_points
|
||||
.saturating_div(2)
|
||||
.saturating_sub(claimed_points)
|
||||
}
|
||||
|
||||
fn accrue_puzzle_point_incentive(
|
||||
ctx: &TxContext,
|
||||
profile_id: &str,
|
||||
@@ -2749,9 +2745,10 @@ fn accrue_puzzle_point_incentive(
|
||||
play_count: row.play_count,
|
||||
remix_count: row.remix_count,
|
||||
like_count: row.like_count,
|
||||
point_incentive_total_half_points: row
|
||||
.point_incentive_total_half_points
|
||||
.saturating_add(spent_points),
|
||||
point_incentive_total_half_points: module_puzzle::puzzle_point_incentive_total_after_spend(
|
||||
row.point_incentive_total_half_points,
|
||||
spent_points,
|
||||
),
|
||||
point_incentive_claimed_points: row.point_incentive_claimed_points,
|
||||
anchor_pack_json: row.anchor_pack_json.clone(),
|
||||
publish_ready: row.publish_ready,
|
||||
|
||||
Reference in New Issue
Block a user