You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.7 KiB
Go

package model
import (
"context"
"fmt"
"git.noahlan.cn/northlan/ntools-go/gorm-zero/gormx"
"gorm.io/gorm"
)
var _ StatisticsPvpModel = (*customStatisticsPvpModel)(nil)
type ScoreType string
const (
ScoreTypeDamage ScoreType = "damage"
ScoreTypeDeDamage = "de_damage"
ScoreTypeGeneral = "general_count"
ScoreTypeDeGeneral = "de_general_count"
ScoreTypeKillUnit = "kill_unit_count"
ScoreTypeDeKillUnit = "de_kill_unit_count"
ScoreTypeKillPlayer = "kill_player_count"
ScoreTypeDeKillPlayer = "de_kill_player_count"
ScoreTypeWin = "win_count"
ScoreTypeLost = "lost_count"
ScoreTypeFirstBlood = "first_blood_count"
ScoreTypeDeFirstBlood = "de_first_blood_count"
)
type (
// StatisticsPvpModel is an interface to be customized, add more methods here,
// and implement the added methods in customStatisticsPvpModel.
StatisticsPvpModel interface {
statisticsPvpModel
// UpdateRecord 更新记录
UpdateRecord(ctx context.Context, tx *gorm.DB, userId int64, props *UpdateRecordProps) error
// FindGreaterByScore 找到比给定分数大的用户id以及具体分数
FindGreaterByScore(ctx context.Context, score int64, scoreType ScoreType, limit int) ([]UserAndScore, error)
// FindScoreByType 根据类型获取用户分数
FindScoreByType(ctx context.Context, tx *gorm.DB, userId int64, scoreType []ScoreType) (map[string]int64, error)
// CleanByType 清空某字段
CleanByType(ctx context.Context, tx *gorm.DB, scoreType ScoreType) error
}
UserAndScore struct {
UserId int64 `gorm:"user_id"`
Score int64 `gorm:"score"`
}
UpdateRecordProps struct {
Damage int64 // 伤害
DeDamage int64 // 被伤害
KillUnitCount int64 // 击杀单位数量
DeKillUnitCount int64 // 被击杀单位被击杀
Win bool // 是否获胜
Lost bool // 是否战败
KillPlayer int64 // 击杀玩家数量
DeKillPlayer bool // 是否玩家被击杀
General bool // 是否拿到名将
DeGeneral bool // 是否名将罗马
FirstBlood bool // 是否拿到一血
DeFirstBlood bool // 是否被拿一血
}
customStatisticsPvpModel struct {
*defaultStatisticsPvpModel
}
)
// NewStatisticsPvpModel returns a model for the database table.
func NewStatisticsPvpModel(conn *gorm.DB) StatisticsPvpModel {
return &customStatisticsPvpModel{
defaultStatisticsPvpModel: newStatisticsPvpModel(conn),
}
}
func (m *customStatisticsPvpModel) UpdateRecord(ctx context.Context, tx *gorm.DB, userId int64, props *UpdateRecordProps) error {
// 条件构建
db := gormx.WithTx(ctx, m.DB, tx)
db = db.Model(&StatisticsPvp{}).Where("user_id = ?", userId)
data := make(map[string]interface{})
if props.Damage != 0 {
data["damage"] = gorm.Expr("damage + ?", props.Damage)
}
if props.DeDamage != 0 {
data["de_damage"] = gorm.Expr("de_damage + ?", props.DeDamage)
}
if props.KillUnitCount != 0 {
data["kill_unit_count"] = gorm.Expr("kill_unit_count + ?", props.KillUnitCount)
}
if props.DeKillUnitCount != 0 {
data["de_kill_unit_count"] = gorm.Expr("de_kill_unit_count + ?", props.DeKillUnitCount)
}
if props.Win {
data["win_count"] = gorm.Expr("win_count + 1")
}
if props.Lost {
data["lost_count"] = gorm.Expr("lost_count + 1")
}
if props.KillPlayer != 0 {
data["kill_player_count"] = gorm.Expr("kill_player_count + ?", props.KillPlayer)
}
if props.DeKillPlayer {
data["de_kill_player_count"] = gorm.Expr("de_kill_player_count + 1")
}
if props.General {
data["general_count"] = gorm.Expr("general_count + 1")
}
if props.DeGeneral {
data["de_general_count"] = gorm.Expr("de_general_count + 1")
}
if props.FirstBlood {
data["first_blood_count"] = gorm.Expr("first_blood_count + 1")
}
if props.DeFirstBlood {
data["de_first_blood_count"] = gorm.Expr("de_first_blood_count + 1")
}
result := db.Updates(data)
return gormx.WrapUpdateErr(result.Error, result.RowsAffected)
}
func (m *customStatisticsPvpModel) FindGreaterByScore(ctx context.Context, score int64, scoreType ScoreType, limit int) ([]UserAndScore, error) {
db := m.DB.WithContext(ctx)
if limit > MaxRankN {
limit = MaxRankN
}
if limit <= 0 {
limit = MaxRankN
}
whereSql := fmt.Sprintf("%s.%s >= ?", m.table, scoreType)
// 0 不入榜
if score == 0 {
whereSql = fmt.Sprintf("%s.%s > ?", m.table, scoreType)
}
whereSql = fmt.Sprintf("%s AND user_id > 0", whereSql)
var result []UserAndScore
err := db.Table(m.table).
Select(fmt.Sprintf("%s.user_id, %s.%s AS score", m.table, m.table, scoreType)).
Where(whereSql, score).
Order(fmt.Sprintf("%s.%s desc", m.table, scoreType)).
Limit(limit).Find(&result).Error
err = gormx.WrapSelectErr(err)
if err != nil {
return nil, err
}
return result, nil
}
func (m *customStatisticsPvpModel) FindScoreByType(ctx context.Context, tx *gorm.DB, userId int64, scoreType []ScoreType) (map[string]int64, error) {
selectFields := make([]string, 0, len(scoreType))
for _, tmp := range scoreType {
selectFields = append(selectFields, string(tmp))
}
db := gormx.WithTx(ctx, m.DB, tx)
resp := map[string]interface{}{}
err := db.Table(m.table).
Select(selectFields).
Where("user_id = ?", userId).Take(&resp).Error
err = gormx.WrapSelectErr(err)
if err != nil {
return nil, err
}
result := make(map[string]int64)
for k, v := range resp {
result[k] = v.(int64)
}
return result, nil
}
func (m *customStatisticsPvpModel) CleanByType(ctx context.Context, tx *gorm.DB, scoreType ScoreType) error {
db := gormx.WithTx(ctx, m.DB, tx).Session(&gorm.Session{AllowGlobalUpdate: true})
result := db.Table(m.table).
Update(string(scoreType), 0)
return gormx.WrapUpdateErr(result.Error, result.RowsAffected)
}