251 lines
10 KiB
TypeScript
251 lines
10 KiB
TypeScript
import { apiRequest } from "@/shared/api/request";
|
|
import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
|
|
import type { ApiPage, PageQuery } from "@/shared/api/types";
|
|
|
|
export interface LuckyGiftTierDto {
|
|
pool: string;
|
|
tierId: string;
|
|
rewardCoins: number;
|
|
weight: number;
|
|
highWaterOnly: boolean;
|
|
enabled: boolean;
|
|
}
|
|
|
|
export interface LuckyGiftConfigDto {
|
|
appCode?: string;
|
|
enabled: boolean;
|
|
ruleVersion: number;
|
|
giftPrice: number;
|
|
targetRTPPPM: number;
|
|
poolRatePPM: number;
|
|
globalWindowDraws: number;
|
|
giftWindowDraws: number;
|
|
noviceDrawLimit: number;
|
|
intermediateDrawLimit: number;
|
|
highMultiplier: number;
|
|
highWaterPoolMultiple: number;
|
|
platformPoolWeightPPM: number;
|
|
roomPoolWeightPPM: number;
|
|
giftPoolWeightPPM: number;
|
|
initialPlatformPool: number;
|
|
initialGiftPool: number;
|
|
initialRoomPool: number;
|
|
platformReserve: number;
|
|
giftReserve: number;
|
|
roomReserve: number;
|
|
maxSinglePayout: number;
|
|
userHourlyPayoutCap: number;
|
|
userDailyPayoutCap: number;
|
|
deviceDailyPayoutCap: number;
|
|
roomHourlyPayoutCap: number;
|
|
anchorDailyPayoutCap: number;
|
|
roomAtmosphereRatePPM: number;
|
|
roomAtmosphereInitial: number;
|
|
roomAtmosphereReserve: number;
|
|
activityBudget: number;
|
|
activityDailyLimit: number;
|
|
largeTierEnabled: boolean;
|
|
tiers: LuckyGiftTierDto[];
|
|
updatedByAdminId?: number;
|
|
createdAtMs?: number;
|
|
updatedAtMs?: number;
|
|
}
|
|
|
|
export interface LuckyGiftConfigPayload {
|
|
enabled: boolean;
|
|
gift_price: number;
|
|
target_rtp_ppm: number;
|
|
pool_rate_ppm: number;
|
|
global_window_draws: number;
|
|
gift_window_draws: number;
|
|
novice_draw_limit: number;
|
|
intermediate_draw_limit: number;
|
|
high_multiplier: number;
|
|
high_water_pool_multiple: number;
|
|
platform_pool_weight_ppm: number;
|
|
room_pool_weight_ppm: number;
|
|
gift_pool_weight_ppm: number;
|
|
initial_platform_pool: number;
|
|
initial_gift_pool: number;
|
|
initial_room_pool: number;
|
|
platform_reserve: number;
|
|
gift_reserve: number;
|
|
room_reserve: number;
|
|
max_single_payout: number;
|
|
user_hourly_payout_cap: number;
|
|
user_daily_payout_cap: number;
|
|
device_daily_payout_cap: number;
|
|
room_hourly_payout_cap: number;
|
|
anchor_daily_payout_cap: number;
|
|
room_atmosphere_rate_ppm: number;
|
|
room_atmosphere_initial: number;
|
|
room_atmosphere_reserve: number;
|
|
activity_budget: number;
|
|
activity_daily_limit: number;
|
|
large_tier_enabled: boolean;
|
|
tiers: Array<{
|
|
pool: string;
|
|
tier_id: string;
|
|
reward_coins: number;
|
|
weight: number;
|
|
high_water_only: boolean;
|
|
enabled: boolean;
|
|
}>;
|
|
}
|
|
|
|
export interface LuckyGiftDrawDto {
|
|
drawId: string;
|
|
commandId?: string;
|
|
giftId: string;
|
|
ruleVersion: number;
|
|
experiencePool: string;
|
|
selectedTierId: string;
|
|
baseRewardCoins: number;
|
|
roomAtmosphereRewardCoins: number;
|
|
activitySubsidyCoins: number;
|
|
effectiveRewardCoins: number;
|
|
budgetSourcesJson?: string;
|
|
rewardStatus?: string;
|
|
rtpWindowIndex: number;
|
|
giftRTPWindowIndex: number;
|
|
globalBaseRTPPPM: number;
|
|
giftBaseRTPPPM: number;
|
|
stageFeedback: boolean;
|
|
highMultiplier: boolean;
|
|
createdAtMs?: number;
|
|
}
|
|
|
|
type RawConfig = LuckyGiftConfigDto & Record<string, unknown>;
|
|
type RawTier = LuckyGiftTierDto & Record<string, unknown>;
|
|
type RawDraw = LuckyGiftDrawDto & Record<string, unknown>;
|
|
|
|
export function getLuckyGiftConfig(): Promise<LuckyGiftConfigDto> {
|
|
const endpoint = API_ENDPOINTS.getLuckyGiftConfig;
|
|
return apiRequest<RawConfig>(apiEndpointPath(API_OPERATIONS.getLuckyGiftConfig), {
|
|
method: endpoint.method,
|
|
}).then(normalizeConfig);
|
|
}
|
|
|
|
export function updateLuckyGiftConfig(payload: LuckyGiftConfigPayload): Promise<LuckyGiftConfigDto> {
|
|
const endpoint = API_ENDPOINTS.upsertLuckyGiftConfig;
|
|
return apiRequest<RawConfig, LuckyGiftConfigPayload>(
|
|
apiEndpointPath(API_OPERATIONS.upsertLuckyGiftConfig),
|
|
{
|
|
body: payload,
|
|
method: endpoint.method,
|
|
},
|
|
).then(normalizeConfig);
|
|
}
|
|
|
|
export function listLuckyGiftDraws(query: PageQuery = {}): Promise<ApiPage<LuckyGiftDrawDto>> {
|
|
const endpoint = API_ENDPOINTS.listLuckyGiftDraws;
|
|
return apiRequest<ApiPage<RawDraw>>(apiEndpointPath(API_OPERATIONS.listLuckyGiftDraws), {
|
|
method: endpoint.method,
|
|
query,
|
|
}).then((page) => ({
|
|
...page,
|
|
items: (page.items || []).map(normalizeDraw),
|
|
}));
|
|
}
|
|
|
|
function normalizeConfig(item: RawConfig): LuckyGiftConfigDto {
|
|
return {
|
|
appCode: stringValue(item.appCode ?? item.app_code),
|
|
enabled: booleanValue(item.enabled),
|
|
ruleVersion: numberValue(item.ruleVersion ?? item.rule_version),
|
|
giftPrice: numberValue(item.giftPrice ?? item.gift_price),
|
|
targetRTPPPM: numberValue(item.targetRTPPPM ?? item.target_rtp_ppm),
|
|
poolRatePPM: numberValue(item.poolRatePPM ?? item.pool_rate_ppm),
|
|
globalWindowDraws: numberValue(item.globalWindowDraws ?? item.global_window_draws),
|
|
giftWindowDraws: numberValue(item.giftWindowDraws ?? item.gift_window_draws),
|
|
noviceDrawLimit: numberValue(item.noviceDrawLimit ?? item.novice_draw_limit),
|
|
intermediateDrawLimit: numberValue(item.intermediateDrawLimit ?? item.intermediate_draw_limit),
|
|
highMultiplier: numberValue(item.highMultiplier ?? item.high_multiplier),
|
|
highWaterPoolMultiple: numberValue(item.highWaterPoolMultiple ?? item.high_water_pool_multiple),
|
|
platformPoolWeightPPM: numberValue(item.platformPoolWeightPPM ?? item.platform_pool_weight_ppm),
|
|
roomPoolWeightPPM: numberValue(item.roomPoolWeightPPM ?? item.room_pool_weight_ppm),
|
|
giftPoolWeightPPM: numberValue(item.giftPoolWeightPPM ?? item.gift_pool_weight_ppm),
|
|
initialPlatformPool: numberValue(item.initialPlatformPool ?? item.initial_platform_pool),
|
|
initialGiftPool: numberValue(item.initialGiftPool ?? item.initial_gift_pool),
|
|
initialRoomPool: numberValue(item.initialRoomPool ?? item.initial_room_pool),
|
|
platformReserve: numberValue(item.platformReserve ?? item.platform_reserve),
|
|
giftReserve: numberValue(item.giftReserve ?? item.gift_reserve),
|
|
roomReserve: numberValue(item.roomReserve ?? item.room_reserve),
|
|
maxSinglePayout: numberValue(item.maxSinglePayout ?? item.max_single_payout),
|
|
userHourlyPayoutCap: numberValue(item.userHourlyPayoutCap ?? item.user_hourly_payout_cap),
|
|
userDailyPayoutCap: numberValue(item.userDailyPayoutCap ?? item.user_daily_payout_cap),
|
|
deviceDailyPayoutCap: numberValue(item.deviceDailyPayoutCap ?? item.device_daily_payout_cap),
|
|
roomHourlyPayoutCap: numberValue(item.roomHourlyPayoutCap ?? item.room_hourly_payout_cap),
|
|
anchorDailyPayoutCap: numberValue(item.anchorDailyPayoutCap ?? item.anchor_daily_payout_cap),
|
|
roomAtmosphereRatePPM: numberValue(item.roomAtmosphereRatePPM ?? item.room_atmosphere_rate_ppm),
|
|
roomAtmosphereInitial: numberValue(item.roomAtmosphereInitial ?? item.room_atmosphere_initial),
|
|
roomAtmosphereReserve: numberValue(item.roomAtmosphereReserve ?? item.room_atmosphere_reserve),
|
|
activityBudget: numberValue(item.activityBudget ?? item.activity_budget),
|
|
activityDailyLimit: numberValue(item.activityDailyLimit ?? item.activity_daily_limit),
|
|
largeTierEnabled: booleanValue(item.largeTierEnabled ?? item.large_tier_enabled),
|
|
tiers: arrayValue(item.tiers).map(normalizeTier),
|
|
updatedByAdminId: numberValue(item.updatedByAdminId ?? item.updated_by_admin_id),
|
|
createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
|
|
updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
|
|
};
|
|
}
|
|
|
|
function normalizeTier(raw: unknown): LuckyGiftTierDto {
|
|
const item = asRecord(raw) as RawTier;
|
|
return {
|
|
pool: stringValue(item.pool),
|
|
tierId: stringValue(item.tierId ?? item.tier_id),
|
|
rewardCoins: numberValue(item.rewardCoins ?? item.reward_coins),
|
|
weight: numberValue(item.weight),
|
|
highWaterOnly: booleanValue(item.highWaterOnly ?? item.high_water_only),
|
|
enabled: booleanValue(item.enabled),
|
|
};
|
|
}
|
|
|
|
function normalizeDraw(item: RawDraw): LuckyGiftDrawDto {
|
|
return {
|
|
drawId: stringValue(item.drawId ?? item.draw_id),
|
|
commandId: stringValue(item.commandId ?? item.command_id),
|
|
giftId: stringValue(item.giftId ?? item.gift_id),
|
|
ruleVersion: numberValue(item.ruleVersion ?? item.rule_version),
|
|
experiencePool: stringValue(item.experiencePool ?? item.experience_pool),
|
|
selectedTierId: stringValue(item.selectedTierId ?? item.selected_tier_id),
|
|
baseRewardCoins: numberValue(item.baseRewardCoins ?? item.base_reward_coins),
|
|
roomAtmosphereRewardCoins: numberValue(
|
|
item.roomAtmosphereRewardCoins ?? item.room_atmosphere_reward_coins,
|
|
),
|
|
activitySubsidyCoins: numberValue(item.activitySubsidyCoins ?? item.activity_subsidy_coins),
|
|
effectiveRewardCoins: numberValue(item.effectiveRewardCoins ?? item.effective_reward_coins),
|
|
budgetSourcesJson: stringValue(item.budgetSourcesJson ?? item.budget_sources_json),
|
|
rewardStatus: stringValue(item.rewardStatus ?? item.reward_status),
|
|
rtpWindowIndex: numberValue(item.rtpWindowIndex ?? item.rtp_window_index),
|
|
giftRTPWindowIndex: numberValue(item.giftRTPWindowIndex ?? item.gift_rtp_window_index),
|
|
globalBaseRTPPPM: numberValue(item.globalBaseRTPPPM ?? item.global_base_rtp_ppm),
|
|
giftBaseRTPPPM: numberValue(item.giftBaseRTPPPM ?? item.gift_base_rtp_ppm),
|
|
stageFeedback: booleanValue(item.stageFeedback ?? item.stage_feedback),
|
|
highMultiplier: booleanValue(item.highMultiplier ?? item.high_multiplier),
|
|
createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
|
|
};
|
|
}
|
|
|
|
function asRecord(value: unknown): Record<string, unknown> {
|
|
return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
|
|
}
|
|
|
|
function arrayValue(value: unknown): unknown[] {
|
|
return Array.isArray(value) ? value : [];
|
|
}
|
|
|
|
function booleanValue(value: unknown) {
|
|
return value === true || value === "true" || value === 1 || value === "1";
|
|
}
|
|
|
|
function stringValue(value: unknown) {
|
|
return typeof value === "string" ? value : value === undefined || value === null ? "" : String(value);
|
|
}
|
|
|
|
function numberValue(value: unknown) {
|
|
const number = Number(value || 0);
|
|
return Number.isFinite(number) ? number : 0;
|
|
}
|