307 lines
7.9 KiB
Go
307 lines
7.9 KiB
Go
package model
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
"math/rand"
|
||
"time"
|
||
|
||
"github.com/globalsign/mgo/bson"
|
||
"mongo.games.com/goserver/core/logger"
|
||
)
|
||
|
||
// 礼包码
|
||
var (
|
||
chars = []rune{
|
||
'4', '1', '7', '2', '3', '6', '5', '8', '9',
|
||
'q', 'n', 'c', 'r', 't', 'm', 'a', 'd', 'e', 'h', 'j', 'l', 'f', 'b', 'g',
|
||
'Q', 'N', 'C', 'R', 'T', 'M', 'A', 'D', 'E', 'H', 'J', 'L', 'F', 'B', 'G',
|
||
}
|
||
divider = 'i' // 分割标识(区分补位,应该是chars里面没出现的字符)
|
||
charLen = uint64(len(chars))
|
||
charIndexMap = make(map[rune]int, len(chars)) // 初始化就完成写入 不存在并发读写问题
|
||
Keystart int64 = 100000 // 单兑换码上限十万
|
||
|
||
)
|
||
|
||
var (
|
||
ErrJYBCode = errors.New("CodeExist")
|
||
ErrJYBRpc = errors.New("Rpcisnil")
|
||
ErrJYBPlCode = errors.New("PlayCodeExist") // 已经兑换过该礼包
|
||
ErrJybISReceive = errors.New("jyb is receive") // 该兑换码已被使用
|
||
ErrJybTsTimeErr = errors.New("jyb ts is not") // 该兑换码已过期
|
||
ErrJybIsNotExist = errors.New("jyb is not exist") // 请输入正确的兑换码
|
||
)
|
||
|
||
func init() {
|
||
for i, char := range chars {
|
||
charIndexMap[char] = i
|
||
}
|
||
}
|
||
|
||
type JybInfoAward struct {
|
||
Item []*Item // 道具
|
||
Coin int64 // 金币
|
||
Diamond int64 // 钻石
|
||
}
|
||
|
||
type JybInfos struct {
|
||
Jybs []*JybInfo
|
||
}
|
||
|
||
type JybInfo struct {
|
||
JybId bson.ObjectId `bson:"_id"` // 礼包ID
|
||
Platform string //平台
|
||
Name string // 礼包名称
|
||
CodeType int32 // 礼包类型 1 通用 2专属(自动生成兑换码,每个玩家领一个) 3活动(自动生产兑换码,每个兑换码领一个)
|
||
StartTime int64 // 开始时间 Unix
|
||
EndTime int64 // 结束时间
|
||
Content string // 礼包内容
|
||
Max int32 // 总个数
|
||
Receive int32 // 领取个数
|
||
CodeStart int64 // Code生成起始
|
||
Code map[string]int32 // 礼包码
|
||
Award *JybInfoAward // 礼包内东西
|
||
CreateTs int64
|
||
}
|
||
|
||
// JybKey 自增
|
||
type JybKey struct {
|
||
KeyId bson.ObjectId `bson:"_id"`
|
||
Keyint int64
|
||
Plakeyid string // keystart+Platform
|
||
GeCode map[string]string // 通用礼包
|
||
}
|
||
|
||
// 验证玩家是否领取礼包 可能存在map并发问题
|
||
type JybUserInfo struct {
|
||
JybUserId bson.ObjectId `bson:"_id"`
|
||
SnId int32 // 玩家id
|
||
Platform string //平台
|
||
JybInfos map[string]int32 //已领取礼包 web和world使用 注意线程安全
|
||
}
|
||
|
||
type GetJybInfoArgs struct {
|
||
Id string // 礼包ID
|
||
Plt string // 平台
|
||
UseCode string // 礼包码
|
||
SnId int32 // 玩家id
|
||
CodeType int32
|
||
}
|
||
|
||
type InitJybInfoArgs struct {
|
||
Plt string // 平台
|
||
}
|
||
|
||
type VerifyUpJybInfoArgs struct {
|
||
UseCode string // 礼包码
|
||
CodeStart int64 // Code生成起始
|
||
Plt string // 平台
|
||
SnId int32 // 玩家id
|
||
CodeType int32
|
||
}
|
||
|
||
type CreateJyb struct {
|
||
*JybInfo
|
||
Codelen int32
|
||
Num uint64
|
||
}
|
||
|
||
// NewJybUserInfo 初始化
|
||
func NewJybKey(plt string) *JybKey {
|
||
jk := &JybKey{KeyId: bson.NewObjectId(), Keyint: Keystart, Plakeyid: fmt.Sprintf("%d_%s", Keystart, plt)}
|
||
return jk
|
||
}
|
||
|
||
// sync.Map new(sync.Map)
|
||
// NewJybUserInfo 初始化
|
||
func NewJybUserInfo(sid int32, plt string) *JybUserInfo {
|
||
jUserInfo := &JybUserInfo{JybUserId: bson.NewObjectId(), SnId: sid, Platform: plt, JybInfos: make(map[string]int32)}
|
||
return jUserInfo
|
||
}
|
||
|
||
func NewJybInfo(plt, name, content, code string, startTs, endTs int64, max, codetype int32, award *JybInfoAward) *JybInfo {
|
||
jyb := &JybInfo{
|
||
JybId: bson.NewObjectId(),
|
||
Platform: plt,
|
||
Name: name,
|
||
Content: content,
|
||
CodeType: codetype,
|
||
StartTime: startTs,
|
||
EndTime: endTs,
|
||
Max: max,
|
||
Receive: 0,
|
||
Code: make(map[string]int32),
|
||
Award: award,
|
||
CreateTs: time.Now().Unix(),
|
||
}
|
||
if codetype == 1 {
|
||
jyb.Code[code] = 1
|
||
}
|
||
return jyb
|
||
}
|
||
|
||
func NewJybCode(jyb *JybInfo, codelen int32, num uint64) {
|
||
cl := int(codelen)
|
||
num += uint64(jyb.CodeStart)
|
||
for i := uint64(jyb.CodeStart); i != num; i++ {
|
||
key := Id2Code(i, cl, true)
|
||
jyb.Code[key] = 1
|
||
}
|
||
}
|
||
|
||
func CreateJybInfo(args *CreateJyb) error {
|
||
if rpcCli == nil {
|
||
return ErrJYBRpc
|
||
}
|
||
ret := &JybInfo{}
|
||
err := rpcCli.CallWithTimeout("JybSvc.CreateJybItem", args, &ret, time.Second*30)
|
||
if err != nil {
|
||
logger.Logger.Warnf("CreateJybInfo err:%v Id:%v ", err, args.JybId)
|
||
return err
|
||
}
|
||
//args.JybInfo = ret // 获取code
|
||
return nil
|
||
}
|
||
|
||
func UpgradeJybUser(args *GetJybInfoArgs) *JybInfo {
|
||
if rpcCli == nil {
|
||
return nil
|
||
}
|
||
ret := &JybInfo{}
|
||
err := rpcCli.CallWithTimeout("JybUserSvc.UpgradeJybUser", args, ret, time.Second*30)
|
||
if err != nil {
|
||
logger.Logger.Warnf("UpgradeJybUser err:%v Id:%v ", err, args.UseCode)
|
||
return nil
|
||
}
|
||
return ret
|
||
}
|
||
|
||
func VerifyUpJybInfo(args *VerifyUpJybInfoArgs) (*JybInfo, error) {
|
||
if rpcCli == nil {
|
||
return nil, ErrJYBRpc
|
||
}
|
||
ret := &JybInfo{}
|
||
err := rpcCli.CallWithTimeout("JybUserSvc.VerifyUpJybUser", args, ret, time.Second*30)
|
||
if err != nil {
|
||
logger.Logger.Warnf("VerifyUpJybUser err:%v Id:%v ", err, args.UseCode)
|
||
return nil, err
|
||
}
|
||
return ret, err
|
||
}
|
||
|
||
func DelJybInfo(args *GetJybInfoArgs) error {
|
||
|
||
if rpcCli == nil {
|
||
return nil
|
||
}
|
||
|
||
ret := false
|
||
err := rpcCli.CallWithTimeout("JybSvc.DelJyb", args, &ret, time.Second*30)
|
||
if err != nil {
|
||
logger.Logger.Warnf("DelJybInfo err:%v Id:%v ", err, args.Id)
|
||
}
|
||
|
||
return err
|
||
}
|
||
|
||
func InitJybItem(args *InitJybInfoArgs) *JybInfos {
|
||
|
||
if rpcCli == nil {
|
||
return nil
|
||
}
|
||
|
||
ret := &JybInfos{}
|
||
err := rpcCli.CallWithTimeout("JybSvc.InitJybItem", args, ret, time.Second*30)
|
||
if err != nil {
|
||
logger.Logger.Warnf("InitJybItem err:%v Id:%v ", err, args.Plt)
|
||
return nil
|
||
}
|
||
|
||
return ret
|
||
}
|
||
|
||
func reverseSlice(strSlice []rune) []rune {
|
||
sLen := len(strSlice)
|
||
for i := 0; i < sLen/2; i++ {
|
||
strSlice[i], strSlice[sLen-i-1] = strSlice[sLen-i-1], strSlice[i]
|
||
}
|
||
return strSlice
|
||
}
|
||
|
||
// Id2Code 把id转为兑换码
|
||
func Id2Code(id uint64, codeMixLength int, isRandomFix bool) string {
|
||
code := make([]rune, 0, codeMixLength)
|
||
for id/charLen > 0 {
|
||
code = append(code, chars[id%charLen])
|
||
id /= charLen
|
||
}
|
||
|
||
code = append(code, chars[id%charLen]) // 处理未除尽的余数
|
||
// slice.ReverseSlice(code)
|
||
reverseSlice(code)
|
||
fixLen := codeMixLength - len(code) // 需要补码的长度
|
||
if fixLen > 0 {
|
||
rand.Seed(time.Now().UnixNano())
|
||
code = append(code, divider)
|
||
for i := 0; i < fixLen-1; i++ {
|
||
// 每次固定,如果需要变的话,后面补码的内容可以改变
|
||
if isRandomFix {
|
||
code = append(code, chars[rand.Intn(int(charLen))])
|
||
} else {
|
||
code = append(code, chars[i])
|
||
}
|
||
}
|
||
}
|
||
return string(code)
|
||
}
|
||
|
||
func Code2Id(code string) (uint64, error) {
|
||
if len(code) == 0 {
|
||
return 0, nil
|
||
}
|
||
var id uint64 = 0
|
||
codeRuneList := []rune(code)
|
||
for i := range codeRuneList {
|
||
// 如果是补码标志直接退出
|
||
if codeRuneList[i] == divider {
|
||
break
|
||
}
|
||
charIndex, ok := charIndexMap[codeRuneList[i]]
|
||
if !ok {
|
||
return 0, errors.New("code有误,解码失败")
|
||
}
|
||
if i > 0 {
|
||
id = id*charLen + uint64(charIndex)
|
||
} else {
|
||
id = uint64(charIndex)
|
||
}
|
||
}
|
||
return id, nil
|
||
}
|
||
|
||
type JybItem struct {
|
||
Id int32 `json:"id"`
|
||
Num int32 `json:"num"`
|
||
}
|
||
|
||
type JybLog struct {
|
||
Platform string `json:"platform"` // 平台
|
||
Id string `json:"jybId"` // 礼包id
|
||
Ts int64 `json:"ts"` // 时间戳
|
||
SnId int32 `json:"snid"` // 玩家id
|
||
Tp int32 `json:"tp"` // 礼包类型 1:通用礼包 2:专属礼包
|
||
Name string `json:"name"` // 礼包名称
|
||
Award []*JybItem `json:"award"` // 礼包奖励
|
||
}
|
||
|
||
//go:generate mongoctl -model-dir=. -model-names=JybCodeLog -dao-dir=../dao/
|
||
type JybCodeLog struct {
|
||
Id primitive.ObjectID `bson:"_id" gen:"autoFill"`
|
||
JybId string `bson:"jybid"` // 礼包id
|
||
Ts int64 `bson:"ts"` // 兑换时间
|
||
SnId int32 `bson:"snid"` // 玩家id
|
||
Code string `bson:"code"` // 兑换码
|
||
}
|