package smithy import ( "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" "math/rand" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx" ) type modelTrade struct { modules.MCompModel module *Smithy } func (this *modelTrade) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { this.TableName = string(comm.TableSmithyTrade) err = this.MCompModel.Init(service, module, comp, options) this.module = module.(*Smithy) // uid 创建索引 this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}}, }) return } type WeightItem struct { Id interface{} Weight int } // 权重项目 type WeightedRandom struct { items []*WeightItem totalWeight int } func newWeightedRandom(items []*WeightItem) *WeightedRandom { wr := &WeightedRandom{items: items} for _, item := range wr.items { wr.totalWeight += int(item.Weight) } return wr } func (wr *WeightedRandom) pick() *WeightItem { if wr.totalWeight <= 0 { return nil } randomNumber := rand.Intn(wr.totalWeight) for _, item := range wr.items { if randomNumber < int(item.Weight) { return item } randomNumber -= int(item.Weight) } return nil } // 随机顾客 func (s *modelTrade) getCustomerRandom() (customerId int32) { confList := s.module.configure.GetSmithyCustomerConfList() var items []*WeightItem for _, v := range confList { items = append(items, &WeightItem{Id: v.CustomerId, Weight: int(v.Weight)}) } wr := newWeightedRandom(items) if c := wr.pick(); c != nil { customerId = (c.Id).(int32) } return } func (s *modelTrade) getDBCustomer(uid string) (*pb.DBCustomer, error) { customer := &pb.DBCustomer{} if err := s.Get(uid, customer); err != nil { return nil, err } return customer, nil } // 初始顾客 func (s *modelTrade) addCustomer(uid string, num int32) (*pb.DBCustomer, error) { customer := &pb.DBCustomer{ Id: primitive.NewObjectID().Hex(), Uid: uid, Total: num, LastRefreshTime: configure.Now().Unix(), } for i := 0; i < int(num); i++ { randCustomerId := s.getCustomerRandom() conf, err := s.module.configure.GetSmithyCustomerConf(randCustomerId) if err != nil { return nil, comm.NewCustomError(pb.ErrorCode_ConfigNoFound) } suitId := s.GetSuitRandom(uid, conf.CustomerType) if suitId != 0 { customer.Customers = append(customer.Customers, &pb.CustomerInfo{ CustomerId: randCustomerId, SuitId: suitId, EquipCount: s.module.modelStove.StoveSkillBuyEquip(uid), }) } } if err := s.Add(uid, customer); err != nil { s.module.Errorln(err) return nil, err } return customer, nil } // 移除顾客 func (s *modelTrade) removeCustomer(cus *pb.DBCustomer, customerId int32) *pb.DBCustomer { var ( temp []*pb.CustomerInfo = make([]*pb.CustomerInfo, 0) ) for _, v := range cus.Customers { if v.CustomerId != customerId { temp = append(temp, v) } } cus.Customers = temp // for i, v := range cus.Customers { // if v.CustomerId == customerId { // cus.Customers = append(cus.Customers[:i], cus.Customers[i+1:]...) // i-- // } // } return cus } // 随机新顾客 func (s *modelTrade) updateCustomer(uid string, customerId int32) (*pb.DBCustomer, error) { cus, err := s.getDBCustomer(uid) if err == nil { cus = s.removeCustomer(cus, customerId) cus.Total++ //上限 limit := s.module.modelStove.StoveSkillAddCustomer(uid) left := limit - cus.Total if left < 0 { return nil, comm.NewCustomError(pb.ErrorCode_SmithyCustomerLimit) } randCustomerId := s.getCustomerRandom() conf, err := s.module.configure.GetSmithyCustomerConf(randCustomerId) if err != nil { return nil, comm.NewCustomError(pb.ErrorCode_ConfigNoFound) } suiteId := s.GetSuitRandom(uid, conf.CustomerType) if suiteId != 0 { cus.Customers = append(cus.Customers, &pb.CustomerInfo{ CustomerId: randCustomerId, SuitId: suiteId, EquipCount: s.module.modelStove.StoveSkillBuyEquip(uid), }) } cus.LastRefreshTime = configure.Now().Unix() update := map[string]interface{}{ "customers": cus.Customers, "total": cus.Total, "lastRefreshTime": cus.LastRefreshTime, } if err := s.Change(uid, update); err != nil { return nil, err } } return cus, nil } // 返回概率下的套装 func (s *modelTrade) GetSuitRandom(uid string, ctype int32) (suiteId int32) { //获取玩家所有解锁套装 uex, err := s.module.ModuleUser.GetUserExpand(uid) if err != nil { s.module.Errorln(err) return } var unlockSuiteItems []*WeightItem for _, v := range uex.SuiteId { unlockSuiteItems = append(unlockSuiteItems, &WeightItem{ Id: v, Weight: 5, }) } //获取玩家已有装备 ec, suites := s.module.ModuleEquipment.GetActionableSuit(uid) if ec != nil { s.module.Error("获取玩家已有装备:", log.Field{Key: "code", Value: ec}) return } var ownerSuiteItems []*WeightItem for _, v := range suites { ownerSuiteItems = append(ownerSuiteItems, &WeightItem{ Id: v, Weight: 7, }) } var merge []*WeightItem if ctype == 1 { merge = append(unlockSuiteItems, ownerSuiteItems...) } else if ctype == 2 { merge = unlockSuiteItems } // 设置权重 wr := newWeightedRandom(merge) if c := wr.pick(); c != nil { return c.Id.(int32) } return } // 交易 func (s *modelTrade) trade(uid string, customerId int32) error { cus, err := s.getDBCustomer(uid) if err != nil { return err } for i, v := range cus.Customers { if v.CustomerId == customerId { if v.EquipCount <= 0 { return comm.NewCustomError(pb.ErrorCode_SmithyCustomerEquipNoEnough) } cus.Customers = append(cus.Customers[:i], cus.Customers[i+1:]...) i-- } } return nil }