79 lines
2.3 KiB
Go

package strategy
import (
"bindbox-game/internal/repository/mysql/dao"
"bindbox-game/internal/repository/mysql/model"
"context"
"encoding/json"
"fmt"
"time"
)
type ActivityDrawStrategy interface {
PreChecks(ctx context.Context, activityID int64, issueID int64, userID int64) error
SelectItem(ctx context.Context, activityID int64, issueID int64, userID int64) (int64, map[string]any, error)
SelectItemBySlot(ctx context.Context, activityID int64, issueID int64, slotIndex int64) (int64, map[string]any, error)
GrantReward(ctx context.Context, userID int64, rewardID int64) error
PostEffects(ctx context.Context, userID int64, activityID int64, issueID int64, rewardID int64) error
}
// SaveDrawReceipt 保存抽奖凭据(用户可验证信息)
// drawLogID: ActivityDrawLogs 记录的 ID
// issueID: 期ID
// userID: 用户ID
// proof: SelectItem 返回的 proof map
// w: 写库 dao.Query
func SaveDrawReceipt(ctx context.Context, w *dao.Query, drawLogID int64, issueID int64, userID int64, proof map[string]any) error {
if proof == nil || drawLogID <= 0 {
return nil
}
// 从 proof 中提取数据
seedHash := ""
if v, ok := proof["seed_hash"].(string); ok {
seedHash = v
}
weightsTotal := int64(0)
if v, ok := proof["weights_total"].(int64); ok {
weightsTotal = v
}
randVal := int64(0)
if v, ok := proof["rand"].(int64); ok {
randVal = v
}
slotIndex := int32(-1)
if v, ok := proof["slot_index"].(int64); ok {
slotIndex = int32(v)
}
totalSlots := int64(0)
if v, ok := proof["total_slots"].(int64); ok {
totalSlots = v
weightsTotal = totalSlots // 一番赏用 total_slots 替代 weights_total
}
// 序列化 proof 作为 items_snapshot
proofJSON, _ := json.Marshal(proof)
receipt := &model.ActivityDrawReceipts{
CreatedAt: time.Now(),
DrawLogID: drawLogID,
AlgoVersion: "HMAC-SHA256-v1",
RoundID: issueID,
DrawID: drawLogID,
ClientID: userID,
Timestamp: time.Now().UnixMilli(),
ServerSeedHash: seedHash,
ServerSubSeed: "",
ClientSeed: "",
Nonce: time.Now().UnixNano(),
ItemsRoot: "",
WeightsTotal: weightsTotal,
SelectedIndex: slotIndex,
RandProof: fmt.Sprintf("%x", randVal),
Signature: "",
ItemsSnapshot: string(proofJSON),
}
return w.ActivityDrawReceipts.WithContext(ctx).Create(receipt)
}