380 lines
14 KiB
Go
380 lines
14 KiB
Go
package luckygift
|
||
|
||
const (
|
||
DefaultPoolID = "default"
|
||
|
||
StatusDraft = "draft"
|
||
StatusActive = "active"
|
||
StatusPaused = "paused"
|
||
StatusClosed = "closed"
|
||
StatusPending = "pending"
|
||
StatusGranted = "granted"
|
||
StatusFailed = "failed"
|
||
|
||
PoolNovice = "novice"
|
||
PoolIntermediate = "intermediate"
|
||
PoolAdvanced = "advanced"
|
||
|
||
StageNovice = "novice"
|
||
StageNormal = "normal"
|
||
StageAdvanced = "advanced"
|
||
|
||
// StrategyFixedV2 保留现网不可变规则的原始语义;只有显式发布 StrategyDynamicV3 才启用动态水位、充值加权和多维风控。
|
||
StrategyFixedV2 = "fixed_v2"
|
||
StrategyDynamicV3 = "dynamic_v3"
|
||
|
||
PoolAdjustmentIn = "in"
|
||
PoolAdjustmentOut = "out"
|
||
|
||
EventTypeLuckyGiftDrawn = "LuckyGiftDrawn"
|
||
EventTypeLuckyGiftRewardSettlement = "LuckyGiftRewardSettlement"
|
||
EventTypeExternalLuckyGiftDrawn = "ExternalLuckyGiftDrawn"
|
||
)
|
||
|
||
// Tier 是单个体验池里的候选奖档;权重只塑造体验节奏,基础成本仍由 RTP 窗口兜住。
|
||
type Tier struct {
|
||
Pool string `json:"pool"`
|
||
TierID string `json:"tier_id"`
|
||
RewardCoins int64 `json:"reward_coins"`
|
||
MultiplierPPM int64 `json:"multiplier_ppm"`
|
||
Weight int64 `json:"weight"`
|
||
HighWaterOnly bool `json:"high_water_only"`
|
||
Enabled bool `json:"enabled"`
|
||
}
|
||
|
||
// Config 是幸运礼物线上规则快照。金额均为整数金币,比例均为 ppm。
|
||
type Config struct {
|
||
AppCode string `json:"app_code"`
|
||
GiftID string `json:"gift_id"`
|
||
PoolID string `json:"pool_id"`
|
||
Enabled bool `json:"enabled"`
|
||
RuleVersion int64 `json:"rule_version"`
|
||
StrategyVersion string `json:"strategy_version"`
|
||
GiftPrice int64 `json:"gift_price"`
|
||
TargetRTPPPM int64 `json:"target_rtp_ppm"`
|
||
PoolRatePPM int64 `json:"pool_rate_ppm"`
|
||
ProfitRatePPM int64 `json:"profit_rate_ppm"`
|
||
AnchorRatePPM int64 `json:"anchor_rate_ppm"`
|
||
ControlBandPPM int64 `json:"control_band_ppm"`
|
||
// SettlementWindowWager 是 dynamic_v3 结算窗口的真实金币流水阈值;不能按参考礼物价格换算成抽数。
|
||
SettlementWindowWager int64 `json:"settlement_window_wager"`
|
||
GlobalWindowDraws int64 `json:"global_window_draws"`
|
||
GiftWindowDraws int64 `json:"gift_window_draws"`
|
||
NoviceMaxEquivalentDraws int64 `json:"novice_max_equivalent_draws"`
|
||
NormalMaxEquivalentDraws int64 `json:"normal_max_equivalent_draws"`
|
||
HighMultiplier int64 `json:"high_multiplier"`
|
||
HighWaterPoolMultiple int64 `json:"high_water_pool_multiple"`
|
||
InitialBasePool int64 `json:"initial_base_pool"`
|
||
BasePoolReserve int64 `json:"base_pool_reserve"`
|
||
InitialPoolCoins int64 `json:"initial_pool_coins"`
|
||
LossStreakGuarantee int64 `json:"loss_streak_guarantee"`
|
||
LowWatermarkCoins int64 `json:"low_watermark_coins"`
|
||
LowWaterNonzeroFactorPPM int64 `json:"low_water_nonzero_factor_ppm"`
|
||
HighWatermarkCoins int64 `json:"high_watermark_coins"`
|
||
HighWaterNonzeroFactorPPM int64 `json:"high_water_nonzero_factor_ppm"`
|
||
RechargeBoostWindowMS int64 `json:"recharge_boost_window_ms"`
|
||
RechargeBoostFactorPPM int64 `json:"recharge_boost_factor_ppm"`
|
||
JackpotMultiplierPPMs []int64 `json:"jackpot_multiplier_ppms"`
|
||
JackpotGlobalRTPMaxPPM int64 `json:"jackpot_global_rtp_max_ppm"`
|
||
JackpotUserDayRTPMaxPPM int64 `json:"jackpot_user_day_rtp_max_ppm"`
|
||
JackpotUser72hRTPMaxPPM int64 `json:"jackpot_user_72h_rtp_max_ppm"`
|
||
JackpotSpendThresholdCoins int64 `json:"jackpot_spend_threshold_coins"`
|
||
MaxJackpotHitsPerUserDay int64 `json:"max_jackpot_hits_per_user_day"`
|
||
MaxSinglePayout int64 `json:"max_single_payout"`
|
||
UserHourlyPayoutCap int64 `json:"user_hourly_payout_cap"`
|
||
UserDailyPayoutCap int64 `json:"user_daily_payout_cap"`
|
||
DeviceDailyPayoutCap int64 `json:"device_daily_payout_cap"`
|
||
RoomHourlyPayoutCap int64 `json:"room_hourly_payout_cap"`
|
||
AnchorDailyPayoutCap int64 `json:"anchor_daily_payout_cap"`
|
||
MultiplierPPMs []int64 `json:"multiplier_ppms"`
|
||
// Stages 保留 dynamic_v3 的充值门槛;Tiers 仍是 fixed_v2 候选选择使用的扁平运行结构。
|
||
Stages []RuleStage `json:"stages"`
|
||
Tiers []Tier `json:"tiers"`
|
||
UpdatedByAdminID int64 `json:"updated_by_admin_id"`
|
||
CreatedAtMS int64 `json:"created_at_ms"`
|
||
UpdatedAtMS int64 `json:"updated_at_ms"`
|
||
}
|
||
|
||
// RuleTier 是 v2 配置契约里的阶段奖档。倍率和概率在服务端内部统一用 ppm 保存。
|
||
type RuleTier struct {
|
||
Stage string `json:"stage"`
|
||
TierID string `json:"tier_id"`
|
||
MultiplierPPM int64 `json:"multiplier_ppm"`
|
||
BaseWeightPPM int64 `json:"base_weight_ppm"`
|
||
HighWaterOnly bool `json:"high_water_only"`
|
||
Enabled bool `json:"enabled"`
|
||
}
|
||
|
||
// RuleStage 保存某个用户阶段的完整奖档概率。每个阶段的基础概率必须合计 1000000。
|
||
type RuleStage struct {
|
||
Stage string `json:"stage"`
|
||
MinRecharge7DCoins int64 `json:"min_recharge_7d_coins"`
|
||
MinRecharge30DCoins int64 `json:"min_recharge_30d_coins"`
|
||
Tiers []RuleTier `json:"tiers"`
|
||
}
|
||
|
||
// RuleConfig 是幸运礼物不可变配置版本快照。fixed_v2 与 dynamic_v3 共用基础 RTP 契约,动态字段只由后者解释;
|
||
// 比例和倍率统一使用 ppm,后台百分比/倍率业务单位只在发布入口转换。
|
||
type RuleConfig struct {
|
||
AppCode string `json:"app_code"`
|
||
PoolID string `json:"pool_id"`
|
||
RuleVersion int64 `json:"rule_version"`
|
||
StrategyVersion string `json:"strategy_version"`
|
||
Enabled bool `json:"enabled"`
|
||
TargetRTPPPM int64 `json:"target_rtp_ppm"`
|
||
PoolRatePPM int64 `json:"pool_rate_ppm"`
|
||
ProfitRatePPM int64 `json:"profit_rate_ppm"`
|
||
AnchorRatePPM int64 `json:"anchor_rate_ppm"`
|
||
SettlementWindowWager int64 `json:"settlement_window_wager"`
|
||
ControlBandPPM int64 `json:"control_band_ppm"`
|
||
GiftPriceReference int64 `json:"gift_price_reference"`
|
||
NoviceMaxEquivalentDraws int64 `json:"novice_max_equivalent_draws"`
|
||
NormalMaxEquivalentDraws int64 `json:"normal_max_equivalent_draws"`
|
||
EffectiveFromMS int64 `json:"effective_from_ms"`
|
||
CreatedByAdminID int64 `json:"created_by_admin_id"`
|
||
CreatedAtMS int64 `json:"created_at_ms"`
|
||
InitialPoolCoins int64 `json:"initial_pool_coins"`
|
||
LossStreakGuarantee int64 `json:"loss_streak_guarantee"`
|
||
LowWatermarkCoins int64 `json:"low_watermark_coins"`
|
||
LowWaterNonzeroFactorPPM int64 `json:"low_water_nonzero_factor_ppm"`
|
||
HighWatermarkCoins int64 `json:"high_watermark_coins"`
|
||
HighWaterNonzeroFactorPPM int64 `json:"high_water_nonzero_factor_ppm"`
|
||
RechargeBoostWindowMS int64 `json:"recharge_boost_window_ms"`
|
||
RechargeBoostFactorPPM int64 `json:"recharge_boost_factor_ppm"`
|
||
JackpotMultiplierPPMs []int64 `json:"jackpot_multiplier_ppms"`
|
||
JackpotGlobalRTPMaxPPM int64 `json:"jackpot_global_rtp_max_ppm"`
|
||
JackpotUserDayRTPMaxPPM int64 `json:"jackpot_user_day_rtp_max_ppm"`
|
||
JackpotUser72hRTPMaxPPM int64 `json:"jackpot_user_72h_rtp_max_ppm"`
|
||
JackpotSpendThresholdCoins int64 `json:"jackpot_spend_threshold_coins"`
|
||
MaxJackpotHitsPerUserDay int64 `json:"max_jackpot_hits_per_user_day"`
|
||
MaxSinglePayout int64 `json:"max_single_payout"`
|
||
UserHourlyPayoutCap int64 `json:"user_hourly_payout_cap"`
|
||
UserDailyPayoutCap int64 `json:"user_daily_payout_cap"`
|
||
DeviceDailyPayoutCap int64 `json:"device_daily_payout_cap"`
|
||
RoomHourlyPayoutCap int64 `json:"room_hourly_payout_cap"`
|
||
AnchorDailyPayoutCap int64 `json:"anchor_daily_payout_cap"`
|
||
Stages []RuleStage `json:"stages"`
|
||
}
|
||
|
||
type CheckCommand struct {
|
||
PoolID string
|
||
GiftID string
|
||
UserID int64
|
||
RoomID string
|
||
}
|
||
|
||
type DrawCommand struct {
|
||
CommandID string
|
||
PoolID string
|
||
UserID int64
|
||
TargetUserID int64
|
||
DeviceID string
|
||
RoomID string
|
||
AnchorID string
|
||
GiftID string
|
||
GiftCount int32
|
||
CoinSpent int64
|
||
PaidAtMS int64
|
||
VisibleRegionID int64
|
||
CountryID int64
|
||
Recharge7DCoins int64
|
||
Recharge30DCoins int64
|
||
LastRechargedAtMS int64
|
||
GiftIncomeCoins int64
|
||
// Sender* 是扣费时刻的公开展示快照;owner outbox 必须携带快照,避免下游为一条飘屏同步反查 user-service。
|
||
SenderName string
|
||
SenderAvatar string
|
||
SenderDisplayUserID string
|
||
SenderPrettyDisplayUserID string
|
||
}
|
||
|
||
type CheckResult struct {
|
||
Enabled bool
|
||
Reason string
|
||
PoolID string
|
||
GiftID string
|
||
GiftPrice int64
|
||
RuleVersion int64
|
||
StrategyVersion string
|
||
TargetRTPPPM int64
|
||
ExperiencePool string
|
||
}
|
||
|
||
type DrawResult struct {
|
||
DrawID string
|
||
DrawIDs []string
|
||
CommandID string
|
||
AppCode string
|
||
UserID int64
|
||
ExternalUserID string
|
||
PoolID string
|
||
GiftID string
|
||
RuleVersion int64
|
||
ExperiencePool string
|
||
SelectedTierID string
|
||
MultiplierPPM int64
|
||
BaseRewardCoins int64
|
||
EffectiveRewardCoins int64
|
||
RewardStatus string
|
||
RTPWindowIndex int64
|
||
GiftRTPWindowIndex int64
|
||
GlobalBaseRTPPPM int64
|
||
GiftBaseRTPPPM int64
|
||
StageFeedback bool
|
||
HighMultiplier bool
|
||
CreatedAtMS int64
|
||
WalletTransactionID string
|
||
CoinBalanceAfter int64
|
||
// Hits 只保留 gift_count 批量中的中奖子抽,避免为了连击表现把所有 999 条审计记录塞进同步响应。
|
||
Hits []DrawHit
|
||
}
|
||
|
||
type DrawHit struct {
|
||
GiftIndex int32
|
||
DrawID string
|
||
SelectedTierID string
|
||
MultiplierPPM int64
|
||
RewardCoins int64
|
||
}
|
||
|
||
type DrawSummary struct {
|
||
PoolID string
|
||
TotalDraws int64
|
||
UniqueUsers int64
|
||
UniqueRooms int64
|
||
TotalSpentCoins int64
|
||
TotalRewardCoins int64
|
||
BaseRewardCoins int64
|
||
ActualRTPPPM int64
|
||
PendingDraws int64
|
||
GrantedDraws int64
|
||
FailedDraws int64
|
||
}
|
||
|
||
// PoolBalance 是后台看到的 app+pool_id 单池账本快照。
|
||
// materialized=false 表示该池还没有真实 lucky_pools 行,展示的是规则默认初始水位,不能当成已经入库的资金流水。
|
||
type PoolBalance struct {
|
||
AppCode string
|
||
PoolID string
|
||
StrategyVersion string
|
||
Balance int64
|
||
ReserveFloor int64
|
||
AvailableBalance int64
|
||
TotalIn int64
|
||
TotalOut int64
|
||
ManualCreditTotal int64
|
||
ManualDebitTotal int64
|
||
Materialized bool
|
||
UpdatedAtMS int64
|
||
}
|
||
|
||
type PoolBalanceQuery struct {
|
||
AppCode string
|
||
PoolID string
|
||
StrategyVersion string
|
||
}
|
||
|
||
// PoolAdjustmentCommand 是人工注资/扣资的 owner 命令。AdjustmentID 由调用方生成并在 App 内唯一,
|
||
// 同一个 ID 的重试只能复用完全相同的资金参数,避免网络重试演变成重复记账。
|
||
type PoolAdjustmentCommand struct {
|
||
AppCode string
|
||
PoolID string
|
||
StrategyVersion string
|
||
AdjustmentID string
|
||
Direction string
|
||
AmountCoins int64
|
||
Reason string
|
||
OperatorAdminID int64
|
||
RequestID string
|
||
}
|
||
|
||
type PoolAdjustment struct {
|
||
AdjustmentID string
|
||
AppCode string
|
||
PoolID string
|
||
StrategyVersion string
|
||
Direction string
|
||
AmountCoins int64
|
||
Reason string
|
||
OperatorAdminID int64
|
||
BalanceBefore int64
|
||
BalanceAfter int64
|
||
CreatedAtMS int64
|
||
}
|
||
|
||
type PoolAdjustmentResult struct {
|
||
Adjustment PoolAdjustment
|
||
Pool PoolBalance
|
||
IdempotentReplay bool
|
||
}
|
||
|
||
type AdminConfigQuery struct {
|
||
PoolID string
|
||
}
|
||
|
||
type DrawQuery struct {
|
||
AppCode string
|
||
PoolID string
|
||
GiftID string
|
||
UserID int64
|
||
RoomID string
|
||
Status string
|
||
Page int32
|
||
PageSize int32
|
||
// ExternalUserID 只用于外部 App 接入流水查询;内部房间抽奖不会填这个字段。
|
||
ExternalUserID string
|
||
ExternalOnly bool
|
||
}
|
||
|
||
// ExternalDrawCommand 是外部 App “已扣费后请求抽奖”的业务事实。
|
||
// HyApp 不接管外部 App 余额,因此这里没有 target_user_id、room_id 或 wallet command_id;幂等边界固定为
|
||
// app_code + request_id,任何重试都必须返回同一条抽奖结果。
|
||
type ExternalDrawCommand struct {
|
||
AppCode string
|
||
ExternalUserID string
|
||
// DeviceID 是外部调用方在自己认证/签名边界内绑定的稳定设备标识;dynamic_v3 必填。
|
||
DeviceID string
|
||
RequestID string
|
||
GiftCount int64
|
||
UnitAmount int64
|
||
TotalAmount int64
|
||
Currency string
|
||
PaidAtMS int64
|
||
MetadataJSON string
|
||
PoolID string
|
||
}
|
||
|
||
// ExternalDrawResult 是返回给外部 App 的最终抽奖结果。
|
||
// reward_status=granted 表示 HyApp 已完成抽奖审计并把 reward_amount 交给调用方处理;它不代表 HyApp wallet 入账。
|
||
type ExternalDrawResult struct {
|
||
DrawID string
|
||
RequestID string
|
||
AppCode string
|
||
ExternalUserID string
|
||
GiftCount int64
|
||
UnitAmount int64
|
||
TotalAmount int64
|
||
RewardAmount int64
|
||
MultiplierPPM int64
|
||
RewardStatus string
|
||
RuleVersion int64
|
||
CreatedAtMS int64
|
||
}
|
||
|
||
// DrawOutbox 是幸运礼物抽奖事务写出的异步副作用载体,worker 只消费这个持久事实。
|
||
type DrawOutbox struct {
|
||
AppCode string
|
||
OutboxID string
|
||
EventType string
|
||
PayloadJSON string
|
||
RetryCount int
|
||
CreatedAtMS int64
|
||
}
|
||
|
||
type DrawRewardState struct {
|
||
AllGranted bool
|
||
WalletTransactionID string
|
||
// RewardGrantedAtMS 取 granted draw 的稳定 updated_at_ms;owner MQ 重投必须保持同一事实正文不漂移。
|
||
RewardGrantedAtMS int64
|
||
}
|