package gamecardlibrary import ( "encoding/json" "math/rand" "os" "sort" "time" "bet24.com/log" coreservice "bet24.com/servers/coreservice/client" pb "bet24.com/servers/micros/cardlibrary/proto" userLabel "bet24.com/servers/micros/userlabel/proto" ) const ( Scenario = "scenariocardlibrary" Invincible = "invinciblecardlibrary" HighScore = "highscorecardlibrary" Doubling = "doublingcardlibrary" NewUser = "newusercardlibrary" DoublingScenario = "doublingscenariocardlibrary" ) const config_key = "cardlibrary_config" var lib *cardLibraryMgr func Run() { lib = newCardLibraryMgr() } func Dump(cmd, param string) { lib.dump(cmd, param) } func GetControlCards(libraryType, controlChair, firstOutCard, doublings int) (bool, []int) { return lib.getCardCombination(libraryType, controlChair, firstOutCard, doublings) } func GetUserControlCards(userId int) (bool, []pb.BalootCardLibrary) { return lib.getBalootCardsByUserLabel(userId) } func GetUserCardLibraryrWeightValue(userId int) int { return lib.getUserCardLibraryrWeightValue(userId) } func isValidCardType(libraryType int) bool { return libraryType >= pb.Baloot_LibraryType_Scenario && libraryType <= pb.Baloot_LibraryType_Doubling_Scenario } func getLibraryName(libraryType int) string { switch libraryType { case pb.Baloot_LibraryType_HighScore: return HighScore case pb.Baloot_LibraryType_Invincible: return Invincible case pb.Baloot_LibraryType_Scenario: return Scenario case pb.Baloot_LibraryType_Doubling: return Doubling case pb.Baloot_LibraryType_NewUser: return NewUser case pb.Baloot_LibraryType_Doubling_Scenario: return DoublingScenario } return "" } type CardCombination struct { FirstOutCard int ControlChair int Doublings int Cards []int } type UserLabelInfo struct { LabelId string IsOpen bool WeightValue int TriggerProb int // 触发概率 pb.BalootCardLibrary } type cardLibraryMgr struct { scenarioCardLibrary []CardCombination // 剧情牌牌库 invincibleCardLibrary []CardCombination // 无敌牌牌库 highScoreCardLibrary []CardCombination // 高分牌牌库 doublingCardLibrary []CardCombination // 加倍牌库 newUserCardLibrary []CardCombination // 新手牌库 doublingScenarioCardLibrary []CardCombination // 加倍场情景牌库 LabelInfoList []UserLabelInfo } func newCardLibraryMgr() *cardLibraryMgr { ret := new(cardLibraryMgr) ret.initCardLibrary() return ret } // 导入牌库 func (cl *cardLibraryMgr) initCardLibrary() { for libraryType := pb.Baloot_LibraryType_Scenario; libraryType <= pb.Baloot_LibraryType_Doubling_Scenario; libraryType++ { if !cl.loadRedisConfig(getLibraryName(libraryType)) { fileName := "serviceconf/cardlibrary/" + getLibraryName(libraryType) + ".json" data, err := os.ReadFile(fileName) if err != nil { log.Release("read rooms failed %s", fileName) } else { if cl.marshalData(data, getLibraryName(libraryType)) { // 写入redis //coreservice.SetPlatformConfig(Scenario, string(data)) log.Release("init %s Success", getLibraryName(libraryType)) } } } } cl.loadConf() } func (cl *cardLibraryMgr) loadConf() { time.AfterFunc(1*time.Minute, cl.loadConf) data := coreservice.GetPlatformConfig(config_key) if data == "" { data, err := os.ReadFile("serviceconf/cardlibraryconf.json") if err != nil { log.Release("read cardlibraryconf failed serviceconf/cardlibraryconf.json") return } err = json.Unmarshal(data, &cl.LabelInfoList) if err != nil { log.Release("Unmarshal CardLibraryConf failed err:%v", err) return } coreservice.SetPlatformConfig(config_key, string(data)) } else { err := json.Unmarshal([]byte(data), &cl.LabelInfoList) if err != nil { log.Release("Unmarshal CardLibraryConf failed err:%v", err) return } } sort.Slice(cl.LabelInfoList, func(i, j int) bool { return cl.LabelInfoList[i].WeightValue > cl.LabelInfoList[j].WeightValue }) } func (cl *cardLibraryMgr) loadRedisConfig(libName string) bool { data := coreservice.GetPlatformConfig(libName) if data == "" { log.Release("%s CardCombination is null", libName) return false } return cl.marshalData([]byte(data), libName) } func (cl *cardLibraryMgr) marshalData(data []byte, libName string) bool { switch libName { case Scenario: err := json.Unmarshal(data, &cl.scenarioCardLibrary) if err != nil { log.Release("Unmarshal scenarioCardLibrary CardCombination failed err:%v", err) return false } case Invincible: err := json.Unmarshal(data, &cl.invincibleCardLibrary) if err != nil { log.Release("Unmarshal invincibleCardLibrary CardCombination failed err:%v", err) return false } case HighScore: err := json.Unmarshal(data, &cl.highScoreCardLibrary) if err != nil { log.Release("Unmarshal highScoreCardLibrary CardCombination failed err:%v", err) return false } case Doubling: err := json.Unmarshal(data, &cl.doublingCardLibrary) if err != nil { log.Release("Unmarshal doublingCardLibrary CardCombination failed err:%v", err) return false } case NewUser: err := json.Unmarshal(data, &cl.newUserCardLibrary) if err != nil { log.Release("Unmarshal newUserCardLibrary CardCombination failed err:%v", err) return false } case DoublingScenario: err := json.Unmarshal(data, &cl.doublingScenarioCardLibrary) if err != nil { log.Release("Unmarshal doublingScenarioCardLibrary CardCombination failed err:%v", err) } default: return false } return true } func (cl *cardLibraryMgr) getCardCombination(libraryType, controlChair, firstOutChair, doublings int) (bool, []int) { var ret []int if !isValidCardType(libraryType) { return false, ret } var combs []CardCombination if libraryType == pb.Baloot_LibraryType_Doubling { libraryType = pb.Baloot_LibraryType_Doubling_Scenario } switch libraryType { case pb.Baloot_LibraryType_Scenario: if len(cl.scenarioCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.scenarioCardLibrary); i++ { if cl.scenarioCardLibrary[i].ControlChair == controlChair && cl.scenarioCardLibrary[i].FirstOutCard == firstOutChair { combs = append(combs, cl.scenarioCardLibrary[i]) } } case pb.Baloot_LibraryType_Invincible: if len(cl.invincibleCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.invincibleCardLibrary); i++ { if cl.invincibleCardLibrary[i].ControlChair == controlChair && cl.invincibleCardLibrary[i].FirstOutCard == firstOutChair { combs = append(combs, cl.invincibleCardLibrary[i]) } } case pb.Baloot_LibraryType_HighScore: if len(cl.highScoreCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.highScoreCardLibrary); i++ { if cl.highScoreCardLibrary[i].ControlChair == controlChair && cl.highScoreCardLibrary[i].FirstOutCard == firstOutChair { combs = append(combs, cl.highScoreCardLibrary[i]) } } case pb.Baloot_LibraryType_Doubling: if len(cl.doublingCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.doublingCardLibrary); i++ { if cl.doublingCardLibrary[i].ControlChair == controlChair && cl.doublingCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingCardLibrary[i].Doublings == doublings { combs = append(combs, cl.doublingCardLibrary[i]) } } if len(combs) == 0 { if doublings > 0 { max := 0 for i := 0; i < len(cl.doublingCardLibrary); i++ { if cl.doublingCardLibrary[i].ControlChair == controlChair && cl.doublingCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingCardLibrary[i].Doublings < doublings && cl.doublingCardLibrary[i].Doublings >= max { max = cl.doublingCardLibrary[i].Doublings } } for i := 0; i < len(cl.doublingCardLibrary); i++ { if cl.doublingCardLibrary[i].ControlChair == controlChair && cl.doublingCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingCardLibrary[i].Doublings == max { combs = append(combs, cl.doublingCardLibrary[i]) } } } else { min := 10000 for i := 0; i < len(cl.doublingCardLibrary); i++ { if cl.doublingCardLibrary[i].ControlChair == controlChair && cl.doublingCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingCardLibrary[i].Doublings <= min { min = cl.doublingCardLibrary[i].Doublings } } for i := 0; i < len(cl.doublingCardLibrary); i++ { if cl.doublingCardLibrary[i].ControlChair == controlChair && cl.doublingCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingCardLibrary[i].Doublings == min { combs = append(combs, cl.doublingCardLibrary[i]) } } } } case pb.Baloot_LibraryType_NewUser: if len(cl.newUserCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.newUserCardLibrary); i++ { if cl.newUserCardLibrary[i].ControlChair == controlChair && cl.newUserCardLibrary[i].FirstOutCard == firstOutChair { combs = append(combs, cl.newUserCardLibrary[i]) } } case pb.Baloot_LibraryType_Doubling_Scenario: if len(cl.doublingScenarioCardLibrary) == 0 { return false, ret } for i := 0; i < len(cl.doublingScenarioCardLibrary); i++ { if cl.doublingScenarioCardLibrary[i].ControlChair == controlChair && cl.doublingScenarioCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingScenarioCardLibrary[i].Doublings == doublings { combs = append(combs, cl.doublingScenarioCardLibrary[i]) } } if len(combs) == 0 { if doublings > 0 { max := 0 for i := 0; i < len(cl.doublingScenarioCardLibrary); i++ { if cl.doublingScenarioCardLibrary[i].ControlChair == controlChair && cl.doublingScenarioCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingScenarioCardLibrary[i].Doublings < doublings && cl.doublingScenarioCardLibrary[i].Doublings >= max { max = cl.doublingScenarioCardLibrary[i].Doublings } } for i := 0; i < len(cl.doublingScenarioCardLibrary); i++ { if cl.doublingScenarioCardLibrary[i].ControlChair == controlChair && cl.doublingScenarioCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingScenarioCardLibrary[i].Doublings == max { combs = append(combs, cl.doublingScenarioCardLibrary[i]) } } } else { min := 10000 for i := 0; i < len(cl.doublingScenarioCardLibrary); i++ { if cl.doublingScenarioCardLibrary[i].ControlChair == controlChair && cl.doublingScenarioCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingScenarioCardLibrary[i].Doublings <= min { min = cl.doublingScenarioCardLibrary[i].Doublings } } for i := 0; i < len(cl.doublingScenarioCardLibrary); i++ { if cl.doublingScenarioCardLibrary[i].ControlChair == controlChair && cl.doublingScenarioCardLibrary[i].FirstOutCard == firstOutChair && cl.doublingScenarioCardLibrary[i].Doublings == min { combs = append(combs, cl.doublingScenarioCardLibrary[i]) } } } } } if len(combs) == 0 { return false, ret } ret = combs[rand.Intn(len(combs))].Cards return true, ret } func (cl *cardLibraryMgr) getWeightValueByUserLabel(labelId string) int { for i := 0; i < len(cl.LabelInfoList); i++ { if cl.LabelInfoList[i].LabelId == labelId { return cl.LabelInfoList[i].WeightValue } } return 0 } func (cl *cardLibraryMgr) getUserCardLibraryrWeightValue(userId int) int { list := userLabel.GetLabel(userId, 0) if len(list) == 0 { return 0 } weightValue := 0 for i := 0; i < len(list); i++ { weightValue += cl.getWeightValueByUserLabel(list[i].LabelId) } return weightValue } func (cl *cardLibraryMgr) isUserHaveUserTheLabel(list []userLabel.LabelColor, labelId string) bool { for n := 0; n < len(list); n++ { if list[n].LabelId == labelId { return true } } return false } func (cl *cardLibraryMgr) getBalootCardsByUserLabel(userId int) (bool, []pb.BalootCardLibrary) { list := userLabel.GetLabel(userId, 0) if len(list) == 0 { return false, []pb.BalootCardLibrary{} } var librarys []pb.BalootCardLibrary for i := 0; i < len(cl.LabelInfoList); i++ { if !cl.LabelInfoList[i].IsOpen { continue } if !cl.isUserHaveUserTheLabel(list, cl.LabelInfoList[i].LabelId) { continue } prob := rand.Intn(100) if prob < cl.LabelInfoList[i].TriggerProb { librarys = append(librarys, cl.LabelInfoList[i].BalootCardLibrary) } } return len(librarys) > 0, librarys } func (cl *cardLibraryMgr) dump(cmd, param string) { }