package model import ( "context" "fmt" "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc" "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 // Transaction 开启事务,传入方法即可 Transaction(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error // InsertTx 插入事务 InsertTx(ctx context.Context, tx *gorm.DB, data *StatisticsPvp) error // 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) } 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 bool // 是否击杀玩家 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) InsertTx(ctx context.Context, tx *gorm.DB, data *StatisticsPvp) error { return withTx(ctx, m.conn, tx).Create(data).Error } func (m *customStatisticsPvpModel) Transaction(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error { return withTx(ctx, m.conn, tx).Transaction(func(tx *gorm.DB) error { return fn(tx) }) } func (m *customStatisticsPvpModel) UpdateRecord(ctx context.Context, tx *gorm.DB, userId int64, props *UpdateRecordProps) error { // 条件构建 db := withTx(ctx, m.conn, tx) db = db.Model(&StatisticsPvp{}).Where("user_id = ?", userId) data := make(map[string]interface{}) if props.Damage != nil { data["damage"] = gorm.Expr("damage + ?", *props.Damage) } if props.DeDamage != nil { data["de_damage"] = gorm.Expr("de_damage + ?", *props.DeDamage) } if props.KillUnitCount != nil { data["kill_unit_count"] = gorm.Expr("kill_unit_count + ?", *props.KillUnitCount) } if props.DeKillUnitCount != nil { 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 { data["kill_player_count"] = gorm.Expr("kill_player_count + 1") } 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) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return ErrRowsAffectedZero } return nil } func (m *customStatisticsPvpModel) FindGreaterByScore(ctx context.Context, score int64, scoreType ScoreType, limit int) ([]UserAndScore, error) { db := m.conn.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 switch err { case nil: return result, nil case gormc.ErrNotFound: return nil, ErrNotFound default: return nil, err } }