package service import ( "blazing/cool" basemodel "blazing/modules/base/model" "blazing/modules/base/service" "blazing/modules/player/model" "context" "fmt" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" ) // nextCatchTime 鐢熸垚涓嬩竴涓敮涓€鎹曟崏鏃堕棿鎴筹紙鍘熷瓙閫掑 max_ts锛? func (s *PetService) nextCatchTime(m ...*gdb.Model) (uint32, error) { dbm := cool.DBM(service.NewBaseSysUserService().Model) if len(m) > 0 { dbm = m[0] } sql := fmt.Sprintf(` UPDATE %s SET max_ts = CASE WHEN max_ts < EXTRACT(EPOCH FROM NOW())::INT THEN EXTRACT(EPOCH FROM NOW())::INT ELSE max_ts + 1 END WHERE id = ? AND deleted_at IS NULL RETURNING max_ts;`, service.NewBaseSysUserService().Model.TableName()) ret, err := dbm.Raw(sql, s.userid).All() if err != nil { return 0, fmt.Errorf("鐢熸垚鎹曟崏鏃堕棿澶辫触: %w", err) } arr := ret.Array() if len(arr) == 0 { return 0, fmt.Errorf("generate catch time failed: empty result") } return arr[0].Uint32(), nil } // setCatchTime 灏?Pet.CatchTime 鍚屾鍒?Pet.Data.CatchTime func setCatchTime(pet *model.Pet) { if pet != nil { pet.Data.CatchTime = pet.CatchTime } } // 鑾峰彇绮剧伒淇℃伅 0鏄粨搴?1鏄斁鐢? func (s *PetService) PetInfo(flag int) []model.Pet { var tt []model.Pet if err := s.dbm(s.Model).Where("free", flag).Scan(&tt); err != nil { return nil } for i := range tt { tt[i].Data.CatchTime = tt[i].CatchTime } return tt } func (s *PetService) StorageInfo(isVip int, free int) []model.Pet { var tt []model.Pet if err := s.dbm_fix(s.Model).Where("free", free).Where("is_vip", isVip).Scan(&tt); err != nil { return nil } for i := range tt { tt[i].Data.CatchTime = tt[i].CatchTime } return tt } func (s *PetService) PetCount(flag int) int { ret, err := s.dbm(s.Model).Where("free", flag).Count() if err != nil { return 0 } return ret } func (s *PetService) UpdateFree(catchTime, fromFree, toFree uint32) bool { res, err := s.dbm(s.Model). Where("catch_time", catchTime). Where("free", fromFree). Data("free", toFree). Update() if err != nil { return false } r, _ := res.RowsAffected() return r > 0 } func (s *PetService) UpdatePrice(catchTime, price, free uint32) error { var item model.Pet var feeRate float64 if free == 2 { t, _ := s.dbm(s.Model).Where("free", 2).Count() if t > 3 { return fmt.Errorf("绮剧伒鏁伴噺宸叉弧") } } else { if err := s.dbm(s.Model).Where("catch_time", catchTime).Scan(&item); err != nil { return err } _, feeRate, _ = item.GetOffShelfFee() _ = feeRate // feeRate 浠呭湪 non-2 鍒嗘敮浣跨敤锛屽湪姝ゅ0鏄庝互缁熶竴浣滅敤鍩? } res, _ := s.dbm(s.Model).Where("catch_time", catchTime).Data(g.Map{ "sale_price": price, "free": free, }).Update() affected, _ := res.RowsAffected() if affected > 0 && free != 2 && feeRate != 0 { amount := item.CalculateOffShelfAmount(feeRate) service.NewBaseSysUserService().UpdateFreeGold(s.userid, -int64(amount*100)) } return nil } func (s *PetService) BuyPet(pid uint32) error { tt := NewPetService(0).PetInfoOneByID(pid) if tt == nil { return fmt.Errorf("pet not found") } if tt.IsVip != 0 { return fmt.Errorf("pet cannot be traded") } if tt.Free != 2 { return fmt.Errorf("pet is not on sale") } if tt.SalePrice == 0 { return fmt.Errorf("pet sale price is not set") } if !tt.UpdateTime.AddDate(0, 0, 1).Before(gtime.Now()) { return fmt.Errorf("鏈埌璐拱鏃堕棿") } return g.DB().Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error { useGold := int64(tt.SalePrice)*102 + int64(tt.SaleCount)*5 var user basemodel.BaseSysUser if err := tx.Model(basemodel.BaseSysUser{}).Where("id", s.userid).Fields("free_gold").Scan(&user); err != nil { return err } if user.FreeGold < useGold { return fmt.Errorf("浣欓涓嶈冻") } if _, err := tx.Model(basemodel.BaseSysUser{}).Where("id", s.userid).Increment("free_gold", -useGold); err != nil { return err } res, err := tx.Model(s.Model).Where("id", tt.ID).Delete() if err != nil { return err } affected, _ := res.RowsAffected() if affected == 0 { return fmt.Errorf("閲嶅璁㈠崟") } if _, err := tx.Model(basemodel.BaseSysUser{}).Where("id", tt.PlayerID).Increment("free_gold", int64(tt.SalePrice)*98); err != nil { return err } catchTime, err := s.nextCatchTime(tx.Model(service.NewBaseSysUserService().Model)) if err != nil { return err } player := model.Pet{ PlayerID: s.userid, Data: tt.Data, CatchTime: catchTime, Free: 0, SalePrice: tt.SalePrice, SaleCount: tt.SaleCount + 1, } player.IsVip = cool.Config.ServerInfo.IsVip player.Data.OldCatchTime = 0 if _, err := tx.Model(s.Model).Insert(player); err != nil { return err } return nil }) } func (s *PetService) Update(t model.PetInfo) bool { _, err := s.dbm(s.Model).Where("catch_time", t.CatchTime).Data("data", t).Update() return err == nil } func (s *PetService) PetInfoOneByCatchTime(catchTime uint32) *model.Pet { var tt *model.Pet if err := s.dbm(s.Model).Where("catch_time", catchTime).Scan(&tt); err != nil || tt == nil { return nil } setCatchTime(tt) return tt } func (s *PetService) PetInfoOneByID(id uint32) *model.Pet { var tt *model.Pet if err := s.dbm(s.Model).Where("id", id).Scan(&tt); err != nil || tt == nil { return nil } setCatchTime(tt) return tt } func (s *PetService) PetInfoOneOther(userid, catchTime uint32) model.Pet { var tt model.Pet s.dbm(s.Model).Where("catch_time", catchTime).Scan(&tt) tt.Data.CatchTime = tt.CatchTime return tt } func (s *PetService) PetInfoOneUnscoped(catchTime uint32) *model.Pet { var tt *model.Pet if err := s.dbm(s.Model).Where("catch_time", catchTime).Unscoped().Scan(&tt); err != nil || tt == nil { return nil } setCatchTime(tt) return tt } func (s *PetService) PetDel(catchTime uint32) { s.dbm(s.Model).Where("catch_time", catchTime).Delete() } func (s *PetService) PetLevelAll() []model.Pet { var tt []model.Pet s.dbm(s.Model).As("pp"). Wheref("(pp.data->>'Level')::INT > 100"). OrderDesc("(pp.data->>'Level')::INT"). Scan(&tt) return tt } // PetAdd 绮剧伒鐪熸娣诲姞鍚庣殑鎹曟崏鏃堕棿鎵嶆槸鐪熸鐨勬椂闂? func (s *PetService) PetAdd(y *model.PetInfo, saleCount uint32) (uint32, error) { if y == nil { return 0, nil } catchTime, err := s.nextCatchTime() if err != nil { return 0, err } y.CatchTime = catchTime player := model.Pet{ PlayerID: s.userid, Data: *y, CatchTime: catchTime, Free: 0, SaleCount: saleCount, } player.IsVip = cool.Config.ServerInfo.IsVip if _, err := cool.DBM(s.Model).Where("player_id", s.userid).Insert(player); err != nil { return 0, err } return catchTime, nil } type PetService struct { BaseService } func NewPetService(userid uint32) *PetService { return &PetService{ BaseService: BaseService{ userid: userid, Service: &cool.Service{ Model: model.NewPet(), ListQueryOp: &cool.QueryOp{ AddOrderby: g.MapStrStr{"updateTime": "asc"}, FieldEQ: []string{"player_id", "free"}, Where: func(ctx context.Context) [][]interface{} { return [][]interface{}{ {"free", 0, false}, {"is_vip", 0, true}, } }, }, PageQueryOp: &cool.QueryOp{ FieldEQ: []string{"player_id", "free"}, DataFieldEQ: []string{"ID"}, Where: func(ctx context.Context) [][]interface{} { return [][]interface{}{ {"free", 0, false}, {"is_vip", 0, true}, } }, }, }, }, } }