diff --git a/api-util/json.go b/api-util/json.go deleted file mode 100644 index 0ce3032..0000000 --- a/api-util/json.go +++ /dev/null @@ -1,8 +0,0 @@ -package api_util - -import "encoding/json" - -func JsonString(o any) string { - bs, _ := json.Marshal(o) - return string(bs) -} diff --git a/api-util/umysql/index.go b/api-util/umysql/index.go deleted file mode 100644 index 7f7d7b0..0000000 --- a/api-util/umysql/index.go +++ /dev/null @@ -1,55 +0,0 @@ -package umysql - -import ( - "github.com/astaxie/beego/orm" - "strings" -) - -// FindSql 查询数据 根据sql -func FindSql(dbName string, sql string, result any) (err error) { - orm := orm.NewOrm() - orm.Using(dbName) - - if _, err = orm.Raw(sql).QueryRows(result); err != nil { - if strings.Contains(err.Error(), "doesn't exist") { - err = nil - return - } - return - } - return -} - -// FindOneSql 查询一条数据 根据sql -func FindOneSql(dbName string, sql string, result any) (err error) { - orm := orm.NewOrm() - orm.Using(dbName) - - if err = orm.Raw(sql).QueryRow(result); err != nil { - if strings.Contains(err.Error(), "doesn't exist") { - err = nil - return - } - return - } - return -} - -// -//// Find 查询数据 -//func Find(dbName string, tableName string, result any) (err error) { -// o := orm.NewOrm() -// o.Using(dbName) -// -// // 也可以直接使用对象作为表名 -// qs := o.QueryTable(tableName) -// -// if _, err = qs.All(result); err != nil { -// if strings.Contains(err.Error(), "doesn't exist") { -// err = nil -// return -// } -// return -// } -// return -//} diff --git a/models/ht-cardholder.go b/models/ht-cardholder.go index ea6ecc5..ae7ae5e 100644 --- a/models/ht-cardholder.go +++ b/models/ht-cardholder.go @@ -8,12 +8,21 @@ import ( "github.com/astaxie/beego/orm" ) +func InitHtCardholder() { + + // register model + orm.RegisterModel(new(HtCardHolderData)) + + // create table + orm.RunSyncdb("default", false, true) +} + // HtCardHolderData 卡牌活动持久数据 type HtCardHolderData struct { Uid int64 `orm:"pk"` // 玩家唯一ID ActivityId int64 // 活动ID - DetailsData *HtCardHolderDataDetails `orm:"-"` // 活动详情 - Details string `orm:"type(text)"` // 活动详情封装 + Details *HtCardHolderDataDetails `orm:"-"` // 活动详情 + DetailsText string `orm:"type(text)"` // 活动详情封装 CreateTime int64 // 创建时间戳 UpdateTime int64 // 修改时间戳 } @@ -30,8 +39,8 @@ type HtCardHolderDataDetails struct { func NewHtCardHolderData(uid int64) *HtCardHolderData { return &HtCardHolderData{ - Uid: uid, - DetailsData: NewHtCardHolderDataDetails(), + Uid: uid, + Details: NewHtCardHolderDataDetails(), } } @@ -52,17 +61,17 @@ func (d *HtCardHolderData) TableName() string { // Encode 打包数据 func (d *HtCardHolderData) Encode() { - details, err := json.Marshal(d.DetailsData) + details, err := json.Marshal(d.Details) if err != nil { lxalilog.Errors(err, "HtCardHolderData Encode Error", d.Uid, d.ActivityId) return } - d.Details = string(details) + d.DetailsText = string(details) } // Decode 分包数据 func (d *HtCardHolderData) Decode() { - err := json.Unmarshal([]byte(d.Details), d.DetailsData) + err := json.Unmarshal([]byte(d.DetailsText), d.Details) if err != nil { lxalilog.Errors(err, "HtCardHolderData Decode Error", d.Uid, d.ActivityId) return @@ -77,24 +86,15 @@ func (d *HtCardHolderData) GetInfo() dto.HtCardHolderInfo { Album: make(map[string]int), Round: 0, } - for i, i2 := range d.DetailsData.Cardholder { + for i, i2 := range d.Details.Cardholder { info.Cardholder[i] = i2 } - for i, i2 := range d.DetailsData.Cards { + for i, i2 := range d.Details.Cards { info.Cards[i] = i2 } - for i, i2 := range d.DetailsData.Album { + for i, i2 := range d.Details.Album { info.Album[i] = i2 } - info.Round = d.DetailsData.Round + info.Round = d.Details.Round return info } - -func InitHtCardholder() { - - // register model - orm.RegisterModel(new(HtCardHolderData)) - - // create table - orm.RunSyncdb("default", false, true) -} diff --git a/service/ht-cardholder/config-registry.go b/service/ht-cardholder/config-registry.go index 444f4c2..df9ef9d 100644 --- a/service/ht-cardholder/config-registry.go +++ b/service/ht-cardholder/config-registry.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "strings" ) var ( @@ -83,6 +84,7 @@ func ConfigDecode() { return } for _, i2 := range configs { + i2.NormalCardSequenceIds = strings.Split(i2.NormalCardSequenceId, ",") combineId := CombineIdSequenceIdCohort(i2.Id, i2.SequenceId, i2.Cohort) Config.NormalCardStarSequence[combineId] = i2 } @@ -96,6 +98,7 @@ func ConfigDecode() { return } for _, i2 := range configs { + i2.CardIdLists = strings.Split(i2.CardIdList, ",") combineId := CombineIdSequenceIdCohort(i2.Id, i2.SequenceId, i2.Cohort) Config.CardSequenceConfig[combineId] = i2 } diff --git a/service/ht-cardholder/config.go b/service/ht-cardholder/config.go index e53ee9d..df2a155 100644 --- a/service/ht-cardholder/config.go +++ b/service/ht-cardholder/config.go @@ -64,24 +64,26 @@ type CardConfig struct { type CardholderConfig struct { Id string `json:"id"` // ID GuaranteedStar string `json:"guaranteed_star_card_id"` // 保底卡星级序列ID - IsGoldCardholder int `json:"isgoldcardholder"` // 是否是金卡包 - IsNew int `json:"isnew"` // 是否是新卡包 + IsGoldCardholder int `json:"is_gold_card_holder"` // 是否是金卡包 + IsNew int `json:"is_new"` // 是否是新卡包 NormalCardNumber int `json:"normal_card_number"` // 非保底卡数量 MinimumGuaranteeCardId string `json:"minimum_guarantee_card_id"` // 非保底卡牌序列ID } // NormalCardStarSequence 非保底卡星级ID type NormalCardStarSequence struct { - Id string `json:"id"` // ID - SequenceId string `json:"user_sequence_id"` // 用户序列组ID - Cohort string `json:"cohort"` // 用户分组 - NormalCardSequenceId string `json:"normal_card_sequence_id"` // 非保底星级序列 + Id string `json:"id"` // ID + SequenceId string `json:"user_sequence_id"` // 用户序列组ID + Cohort string `json:"cohort"` // 用户分组 + NormalCardSequenceId string `json:"normal_card_sequence_id"` // 非保底星级序列 + NormalCardSequenceIds []string `json:"-"` // 非保底星级序列 } // CardSequenceConfig 星级ID对应的卡片 type CardSequenceConfig struct { - Id string `json:"id"` // SequenceId 用户序列组ID - SequenceId string `json:"user_sequence_id"` // 用户序列组ID - Cohort string `json:"cohort"` // 用户分组 - CardIdList string `json:"card_id_list"` // 卡牌抽取序列 + Id string `json:"id"` // SequenceId 用户序列组ID + SequenceId string `json:"user_sequence_id"` // 用户序列组ID + Cohort string `json:"cohort"` // 用户分组 + CardIdList string `json:"card_id_list"` // 卡牌抽取序列 + CardIdLists []string `json:"-"` // 卡牌抽取序列 } diff --git a/service/ht-cardholder/configs.go b/service/ht-cardholder/configs.go index 252111b..87e470a 100644 --- a/service/ht-cardholder/configs.go +++ b/service/ht-cardholder/configs.go @@ -1,9 +1,9 @@ package ht_cardholder import ( - "apigame/api-util/umysql" "apigame/lx-util/lxalilog" "apigame/service/constd" + "apigame/util/utmysql" "fmt" "github.com/astaxie/beego/logs" ) @@ -31,7 +31,7 @@ func LoadConfigs() { { conf := make([]CardActivityUpdateConfig, 0) sql := fmt.Sprintf("select id,status,update_time from %s", configTableName) - err := umysql.FindSql(constd.MYSQL_MERGECONFIG, sql, &conf) + err := utmysql.FindSql(constd.MYSQL_MERGECONFIG, sql, &conf) if err != nil { lxalilog.Errors(err, sql, constd.GAME_ID_HT) return @@ -53,7 +53,7 @@ func LoadConfigs() { logs.Debug("__________________尝试更新活动条目ID:", configOpen.Id) confNew := CardActivityConfigRaw{} sql := fmt.Sprintf("select * from %s where id=%d limit 1", configTableName, configOpen.Id) - err := umysql.FindOneSql(constd.MYSQL_MERGECONFIG, sql, &confNew) + err := utmysql.FindOneSql(constd.MYSQL_MERGECONFIG, sql, &confNew) if err != nil { lxalilog.Errors(err, sql, constd.GAME_ID_HT, configOpen.Id) return diff --git a/service/ht-cardholder/handle.go b/service/ht-cardholder/handle.go index b3bd794..ee6b69a 100644 --- a/service/ht-cardholder/handle.go +++ b/service/ht-cardholder/handle.go @@ -2,11 +2,8 @@ package ht_cardholder import ( "apigame/dto" - "apigame/lx-util/lxalilog" - "apigame/lx-util/lxtime" - "apigame/models" "apigame/service/constd" - "github.com/astaxie/beego/orm" + "apigame/util/uttype" "strconv" ) @@ -54,9 +51,10 @@ func HandleGetNew(req *dto.ReqHtCardHolderGetNew) (code string, rsp dto.RspHtCar // 读取游戏数据 gameData := LoadData(req.UID) - gameData.DetailsData.Cardholder[req.Id] += req.Count + gameData.Details.Cardholder[req.Id] += req.Count SaveData(gameData) + // 返回信息 rsp.HtCardHolderInfo = gameData.GetInfo() return @@ -75,100 +73,59 @@ func HandleOpen(req *dto.ReqHtCardHolderOpen) (code string, rsp dto.RspHtCardHol if code != constd.RECODE_OK { return } - //// 检查卡包ID - //confCardholder, okCardholderConfig := Registry.Config.CardholderConfig[strconv.Itoa(req.Id)] - //if !okCardholderConfig { - // code = constd.RECODE_MERGE_CARDHOLDER_CARDHOLDERID_ERROR - // return - //} - // - //// 读取游戏数据 - //gameData := LoadData(req.UID) - // - //// 判断卡包数目 - //countOld, _ := gameData.DetailsData.Cardholder[req.Id] - //if countOld < 1 { - // code = constd.RECODE_MERGE_CARDHOLDER_CARDHOLDER_NOTENOUGH_ERROR - // return - //} - // - //// 开始处理抽卡 - //sequenceId, cohort := GetUserSequenceIdAndCohort(req.UID) - //// 先抽保底卡 - //if confCardholder.GuaranteedStar != "0" { - // confGuaranteed, hasGuaranteed := FindCardSequenceConfig(confCardholder.GuaranteedStar, sequenceId, cohort) - // if hasGuaranteed { - // - // } - //} + // 检查卡包ID + confCardholder, okCardholderConfig := Config.CardholderConfig[strconv.Itoa(req.Id)] + if !okCardholderConfig { + code = constd.RECODE_MERGE_CARDHOLDER_CARDHOLDERID_ERROR + return + } - return -} + // 读取游戏数据 + gameData := LoadData(req.UID) -// SaveData 存储数据 -func SaveData(d *models.HtCardHolderData) { - d.UpdateTime = lxtime.NowUninx() - d.Encode() - o := orm.NewOrm() - o.Using(constd.MYSQL_DEFAULT) - if _, err := o.InsertOrUpdate(d); err != nil { - lxalilog.Errors(err, "ht_cardholder SaveData Error", d.Uid) + // 判断卡包数目 + countOld, _ := gameData.Details.Cardholder[req.Id] + if countOld < 1 { + code = constd.RECODE_MERGE_CARDHOLDER_CARDHOLDER_NOTENOUGH_ERROR + return } -} -func _LoadData(uid int64) (d *models.HtCardHolderData) { - d = models.NewHtCardHolderData(uid) - o := orm.NewOrm() - o.Using(constd.MYSQL_DEFAULT) - qs := o.QueryTable(d) - qs = qs.Filter("uid", uid) - count, err := qs.Count() - if count == 0 { - d.CreateTime = lxtime.NowUninx() + // 开始处理抽卡 + sequenceId, cohort := GetUserSequenceIdAndCohort(req.UID) + if confCardholder.IsNew != 0 { + // 如果是新卡包 按顺序查找数目最少的一张卡抽取 + cardId := GetNewCard(gameData) + // 增加卡牌 + gameData.Details.Cards[cardId] += 1 + rsp.NewCards = append(rsp.NewCards, cardId) } else { - err = qs.One(d) - if err != nil { - lxalilog.Errors(err, "ht_cardholder LoadData Error", uid) - } else { - d.DetailsData = models.NewHtCardHolderDataDetails() - d.Decode() + // 正常抽卡 + // 先抽保底卡 + if confCardholder.GuaranteedStar != "0" { + confGuaranteed, hasGuaranteed := FindCardSequenceConfig(confCardholder.GuaranteedStar, sequenceId, cohort) + if hasGuaranteed { + combineId := CombineIdSequenceIdCohort(confCardholder.GuaranteedStar, sequenceId, cohort) + scale := gameData.Details.CardSequenceScales[combineId] + cardId := GetOneFromArray(confGuaranteed.CardIdLists, scale) + cardIdInt := uttype.StringToInt(cardId) + // 增加刻度 + gameData.Details.CardSequenceScales[combineId] = scale + 1 + // 增加卡牌 + gameData.Details.Cards[cardIdInt] += 1 + rsp.NewCards = append(rsp.NewCards, cardIdInt) + } } - } - return -} -// LoadData 获取数据 外部接口 -func LoadData(uid int64) (d *models.HtCardHolderData) { - d = _LoadData(uid) - // 如果当前有上线活动(活动ID不为0),且活动ID和玩家数据不同,说明活动已切换 需更新 - if Config.Id != 0 && - Config.Id != d.ActivityId { - d.ActivityId = Config.Id - d.DetailsData = models.NewHtCardHolderDataDetails() - SaveData(d) } - return -} -// CheckStatus 判断活动是否开启 -func CheckStatus() string { - sec := lxtime.NowUninx() - if Config.Id == 0 { - return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN1_ERROR - } - if sec < Config.Raw.StartTime { - return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN1_ERROR - } - if sec > Config.Raw.EndTime { - return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN2_ERROR - } - return constd.RECODE_OK -} + // 删除一个卡包 + gameData.Details.Cardholder[req.Id] = countOld - 1 + + // 存档 + SaveData(gameData) + + // 返回信息 + rsp.HtCardHolderInfo = gameData.GetInfo() -// GetUserSequenceIdAndCohort 获取 用户序列组ID(sequenceId) 用户分组(cohort) -func GetUserSequenceIdAndCohort(uid int64) (sequenceId, cohort string) { - // todo 这里后续要对接 - sequenceId = "1" - cohort = "1" return } diff --git a/service/ht-cardholder/logic.go b/service/ht-cardholder/logic.go new file mode 100644 index 0000000..acc3987 --- /dev/null +++ b/service/ht-cardholder/logic.go @@ -0,0 +1,122 @@ +package ht_cardholder + +import ( + "apigame/lx-util/lxalilog" + "apigame/lx-util/lxtime" + "apigame/models" + "apigame/service/constd" + "apigame/util/uttype" + "github.com/astaxie/beego/orm" +) + +// SaveData 存储数据 +func SaveData(d *models.HtCardHolderData) { + d.UpdateTime = lxtime.NowUninx() + d.Encode() + o := orm.NewOrm() + o.Using(constd.MYSQL_DEFAULT) + if _, err := o.InsertOrUpdate(d); err != nil { + lxalilog.Errors(err, "ht_cardholder SaveData Error", d.Uid) + } +} + +func _LoadData(uid int64) (d *models.HtCardHolderData) { + d = models.NewHtCardHolderData(uid) + o := orm.NewOrm() + o.Using(constd.MYSQL_DEFAULT) + qs := o.QueryTable(d) + qs = qs.Filter("uid", uid) + count, err := qs.Count() + if count == 0 { + d.CreateTime = lxtime.NowUninx() + } else { + err = qs.One(d) + if err != nil { + lxalilog.Errors(err, "ht_cardholder LoadData Error", uid) + } else { + d.Details = models.NewHtCardHolderDataDetails() + d.Decode() + } + } + return +} + +// LoadData 获取数据 外部接口 +func LoadData(uid int64) (d *models.HtCardHolderData) { + d = _LoadData(uid) + // 如果当前有上线活动(活动ID不为0),且活动ID和玩家数据不同,说明活动已切换 需更新 + if Config.Id != 0 && + Config.Id != d.ActivityId { + d.ActivityId = Config.Id + d.Details = models.NewHtCardHolderDataDetails() + SaveData(d) + } + return +} + +// CheckStatus 判断活动是否开启 +func CheckStatus() string { + sec := lxtime.NowUninx() + if Config.Id == 0 { + return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN1_ERROR + } + if sec < Config.Raw.StartTime { + return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN1_ERROR + } + if sec > Config.Raw.EndTime { + return constd.RECODE_MERGE_CARDHOLDER_NOTOPEN2_ERROR + } + return constd.RECODE_OK +} + +// GetUserSequenceIdAndCohort 获取 用户序列组ID(sequenceId) 用户分组(cohort) +func GetUserSequenceIdAndCohort(uid int64) (sequenceId, cohort string) { + // todo 这里后续要对接 + sequenceId = "1" + cohort = "1" + return +} + +// GetOneFromArray 从配置的数组里获取一个值 scale=之前刻度 +func GetOneFromArray(array []string, scale int) string { + length := len(array) + if length < 1 { + return "" + } + if length == 1 { + return array[0] + } + return array[scale%length] +} + +// GetListFromArray 从配置的数组里获取一组值 scale=之前刻度 count=数目 +func GetListFromArray(array []string, scale, count int) []string { + list := make([]string, 0) + if count < 0 { + return list + } + s := scale + for i := 0; i < count; i++ { + one := GetOneFromArray(array, s) + list = append(list, one) + s++ + } + return list +} + +// GetNewCard 按顺序查找数目最少的一张卡抽取 +func GetNewCard(gameData *models.HtCardHolderData) int { + if len(Config.CardConfig) < 1 { + return 0 + } + rate := int64(100000000) + list := make([]int64, 0) + for id, _ := range Config.CardConfig { + count, _ := gameData.Details.Cards[id] + index := int64(count)*rate + int64(id) + list = append(list, index) + } + + indexMin := uttype.Min(list...) + return int(indexMin % rate) +} diff --git a/util/utjson/json.go b/util/utjson/json.go new file mode 100644 index 0000000..0c4156e --- /dev/null +++ b/util/utjson/json.go @@ -0,0 +1,8 @@ +package utjson + +import "encoding/json" + +func JsonString(o any) string { + bs, _ := json.Marshal(o) + return string(bs) +} diff --git a/util/utmysql/index.go b/util/utmysql/index.go new file mode 100644 index 0000000..d0b843b --- /dev/null +++ b/util/utmysql/index.go @@ -0,0 +1,55 @@ +package utmysql + +import ( + "github.com/astaxie/beego/orm" + "strings" +) + +// FindSql 查询数据 根据sql +func FindSql(dbName string, sql string, result any) (err error) { + orm := orm.NewOrm() + orm.Using(dbName) + + if _, err = orm.Raw(sql).QueryRows(result); err != nil { + if strings.Contains(err.Error(), "doesn't exist") { + err = nil + return + } + return + } + return +} + +// FindOneSql 查询一条数据 根据sql +func FindOneSql(dbName string, sql string, result any) (err error) { + orm := orm.NewOrm() + orm.Using(dbName) + + if err = orm.Raw(sql).QueryRow(result); err != nil { + if strings.Contains(err.Error(), "doesn't exist") { + err = nil + return + } + return + } + return +} + +// +//// Find 查询数据 +//func Find(dbName string, tableName string, result any) (err error) { +// o := orm.NewOrm() +// o.Using(dbName) +// +// // 也可以直接使用对象作为表名 +// qs := o.QueryTable(tableName) +// +// if _, err = qs.All(result); err != nil { +// if strings.Contains(err.Error(), "doesn't exist") { +// err = nil +// return +// } +// return +// } +// return +//} diff --git a/util/uttype/number.go b/util/uttype/number.go new file mode 100644 index 0000000..b770182 --- /dev/null +++ b/util/uttype/number.go @@ -0,0 +1,21 @@ +package uttype + +// Int 整型 +type Int interface { + int | int8 | int16 | int32 | int64 | float32 | float64 +} + +// Uint 无符号整型 +type Uint interface { + uint | uint8 | uint16 | uint32 +} + +// Float 浮点 +type Float interface { + float32 | float64 +} + +// Number 数字 +type Number interface { + Int | Uint | Float +} diff --git a/util/uttype/slice.go b/util/uttype/slice.go new file mode 100644 index 0000000..057c76d --- /dev/null +++ b/util/uttype/slice.go @@ -0,0 +1,21 @@ +package uttype + +func Min[T Number](values ...T) T { + result := values[0] + for _, v := range values[1:] { + if v < result { + result = v + } + } + return result +} + +func Max[T Number](values ...T) T { + result := values[0] + for _, v := range values[1:] { + if v > result { + result = v + } + } + return result +} diff --git a/util/uttype/string.go b/util/uttype/string.go new file mode 100644 index 0000000..72a68aa --- /dev/null +++ b/util/uttype/string.go @@ -0,0 +1,84 @@ +package uttype + +import ( + "strconv" + "strings" +) + +const ( + StrSpe1 = "|" + StrSpe2 = "_" +) + +func StringToInt(str string) int { + if value, err := strconv.Atoi(str); err == nil { + return value + } + return 0 +} +func StringToInt32(str string) int32 { + return int32(StringToInt(str)) +} +func StringToInt64(str string) int64 { + if value, err := strconv.ParseInt(str, 10, 64); err == nil { + return value + } + return 0 +} +func IntToString(value int) string { + return strconv.Itoa(value) +} +func Int32ToString(value int32) string { + return IntToString(int(value)) +} +func Int64ToString(value int64) string { + return strconv.FormatInt(value, 10) +} + +func ListStringToListInt(list []string) []int { + result := make([]int, 0) + for _, v := range list { + result = append(result, StringToInt(v)) + } + return result +} +func ListStringToListInt64(list []string) []int64 { + result := make([]int64, 0) + for _, v := range list { + result = append(result, StringToInt64(v)) + } + return result +} +func StringToListString(str string) []string { + return strings.Split(str, StrSpe1) +} +func StringToListInt(str string) []int { + return ListStringToListInt(strings.Split(str, StrSpe1)) +} +func StringToListListString(str string) [][]string { + result := make([][]string, 0) + list1 := strings.Split(str, StrSpe1) + for _, v := range list1 { + list2 := strings.Split(v, StrSpe2) + result = append(result, list2) + } + return result +} +func StringToListListInt(str string) [][]int { + result := make([][]int, 0) + list1 := strings.Split(str, StrSpe1) + for _, v := range list1 { + list2 := strings.Split(v, StrSpe2) + result = append(result, ListStringToListInt(list2)) + } + return result +} +func StringToListListInt64(str string) [][]int64 { + result := make([][]int64, 0) + list1 := strings.Split(str, StrSpe1) + for _, v := range list1 { + list2 := strings.Split(v, StrSpe2) + result = append(result, ListStringToListInt64(list2)) + } + return result +} -- libgit2 0.21.0