From fb7c0d4e6307c0493b80e4d72a8039c152a416ef Mon Sep 17 00:00:00 2001 From: NorthLan <6995syu@163.com> Date: Wed, 8 Jun 2022 00:30:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8C=87=E4=BB=A4=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8D=95=E7=8B=ACdistinct=E9=85=8D=E7=BD=AE=EF=BC=8C=E4=B8=BAz?= =?UTF-8?q?hg=E7=9A=84s=E6=8C=87=E4=BB=A4=E6=B7=BB=E5=8A=A0=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E6=96=B9=E5=BC=8Fs1,10=EF=BC=88=E6=9C=80=E5=A4=A710?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-dev.yml | 9 +- config/config.go | 9 +- game/live_logic/zhg_handler.go | 147 ++++++++++++++++++++------------- pkg/cmd/cmd_parser.go | 26 ++++-- pkg/cmd/cmd_parser_test.go | 49 ++++++++++- 5 files changed, 165 insertions(+), 75 deletions(-) diff --git a/config-dev.yml b/config-dev.yml index f56b8ce..95cb4f0 100644 --- a/config-dev.yml +++ b/config-dev.yml @@ -34,12 +34,13 @@ Game: # 1元=10 Coin (1元40个步兵) CoinFoodRatio: 4 OutbreakCount: 3 + OutbreakMaxCount: 10 # 3x10=30 OutbreakBaseCost: 5 OutbreakCostDict: - 1: 3 # 步兵 - 2: 7 # 骑兵 - 3: 4 # 弓箭手 - 4: 3 # 法师 + 1: 1 # 步兵 + 2: 2.333 # 骑兵 + 3: 1.333 # 弓箭手 + 4: 1 # 法师 Zhghz: Zhgfb: Zhgzd: diff --git a/config/config.go b/config/config.go index 4598bdc..48808e9 100644 --- a/config/config.go +++ b/config/config.go @@ -40,10 +40,11 @@ type ( AdminUserId []int64 // 管理员ID // Zhg 指挥官PvP模式 Zhg struct { - CoinFoodRatio float32 // 硬币到粮草的转换系数(乘) - OutbreakCount int64 // 每次暴兵数量 - OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种) - OutbreakCostDict map[int]int64 // 暴兵消耗表 + CoinFoodRatio float32 // 硬币到粮草的转换系数(乘) + OutbreakCount int64 // 默认暴兵指令每次暴兵数量 + OutbreakMaxCount int64 // 单次暴兵数量最大限制 + OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种) + OutbreakCostDict map[int]float64 // 暴兵消耗表(单个兵) } // Zhghz 指挥官海战模式 Zhghz struct { diff --git a/game/live_logic/zhg_handler.go b/game/live_logic/zhg_handler.go index 8c32e46..11e21f7 100644 --- a/game/live_logic/zhg_handler.go +++ b/game/live_logic/zhg_handler.go @@ -1,6 +1,7 @@ package live_logic import ( + "database/sql" "dcg/app/user_center/usercenter" "dcg/config" "dcg/game/manager" @@ -16,6 +17,7 @@ import ( "git.noahlan.cn/northlan/ntools-go/logger" "github.com/shopspring/decimal" "strconv" + "strings" ) type ZhgGameLogic struct { @@ -24,57 +26,60 @@ type ZhgGameLogic struct { } func NewZhgLiveGameLogic(svcCtx *svc.ServiceContext) *LiveGameLogic { + cmdParser := cmd.NewCMDParser( + cmd.Pattern{ + Prefix: "q", + Alias: []string{"查询"}, + ContentMaxLen: 0, + }, + cmd.Pattern{ + Prefix: "j", + Alias: []string{"加入", "加入游戏"}, + ContentMaxLen: 0, + }, cmd.Pattern{ + Prefix: "c", + Alias: []string{"换兵"}, + ContentMaxLen: 1, + }, cmd.Pattern{ + Prefix: "w", + Alias: []string{"我在哪"}, + ContentMaxLen: 0, + }, cmd.Pattern{ + Prefix: "s", + ContentMaxLen: 4, + Distinct: sql.NullBool{Bool: false, Valid: true}, + }, cmd.Pattern{ + Prefix: "m", + ContentMaxLen: 1, + }, cmd.Pattern{ + Prefix: "r", + ContentMaxLen: 1, + }, cmd.Pattern{ + Prefix: "bq", + Alias: []string{"购买粮草", "买粮草"}, + ContentMaxLen: 2, + }, cmd.Pattern{ + Prefix: "bw", + Alias: []string{"购买精英", "买精英"}, + ContentMaxLen: 2, + }, cmd.Pattern{ + Prefix: "zw", + Alias: []string{"装备精英"}, + ContentMaxLen: 2, + }, cmd.Pattern{ + Prefix: "zz", + Alias: []string{"使用称号"}, + ContentMaxLen: 2, + }, cmd.Pattern{ + Prefix: "结算", + Alias: nil, + ContentMaxLen: 2, + }, + ) + cmdParser.SetDistinct(true) resp := &ZhgGameLogic{ - svcCtx: svcCtx, - LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmd.NewCMDParser( - cmd.Pattern{ - Prefix: "q", - Alias: []string{"查询"}, - ContentMaxLen: 0, - }, - cmd.Pattern{ - Prefix: "j", - Alias: []string{"加入", "加入游戏"}, - ContentMaxLen: 0, - }, cmd.Pattern{ - Prefix: "c", - Alias: []string{"换兵"}, - ContentMaxLen: 1, - }, cmd.Pattern{ - Prefix: "w", - Alias: []string{"我在哪"}, - ContentMaxLen: 0, - }, cmd.Pattern{ - Prefix: "s", - ContentMaxLen: 1, - }, cmd.Pattern{ - Prefix: "m", - ContentMaxLen: 1, - }, cmd.Pattern{ - Prefix: "r", - ContentMaxLen: 1, - }, cmd.Pattern{ - Prefix: "bq", - Alias: []string{"购买粮草", "买粮草"}, - ContentMaxLen: 2, - }, cmd.Pattern{ - Prefix: "bw", - Alias: []string{"购买精英", "买精英"}, - ContentMaxLen: 2, - }, cmd.Pattern{ - Prefix: "zw", - Alias: []string{"装备精英"}, - ContentMaxLen: 2, - }, cmd.Pattern{ - Prefix: "zz", - Alias: []string{"使用称号"}, - ContentMaxLen: 2, - }, cmd.Pattern{ - Prefix: "结算", - Alias: nil, - ContentMaxLen: 2, - }, - )), + svcCtx: svcCtx, + LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmdParser), } resp.RegisterCMDHandler(resp.handleQuery, "q") resp.RegisterCMDHandler(resp.handleJoinGame, "j") @@ -219,26 +224,54 @@ func (h *ZhgGameLogic) handleOutbreakFood(room *manager.Room, content []rune, us if len(content) < 1 { return } + zhgCfg := config.Config.Game.Zhg + // s1,10s2,10s3,10s4,10 11,0 111, + contentStr := string(content) + + var unitTypeStr string + var count int64 + var err error + idxSplit := strings.IndexRune(contentStr, ',') + if idxSplit == -1 { + // 没有分隔符,判断内容位数? + unitTypeStr = string(content) + count = zhgCfg.OutbreakCount + } else { + unitTypeStr = string(content[:idxSplit]) + if idxSplit == len(content)-1 { + count = zhgCfg.OutbreakCount + } else { + count, err = strconv.ParseInt(string(content[idxSplit+1:]), 10, 0) + if err != nil { + return + } + } + if count > zhgCfg.OutbreakMaxCount { + count = zhgCfg.OutbreakMaxCount + } + if count <= 0 { + count = zhgCfg.OutbreakCount + } + } - logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username) - - unitTypeStr := string(content[0]) unitType, err := strconv.Atoi(unitTypeStr) if err != nil { return } - zhgCfg := config.Config.Game.Zhg var cost int64 if unitCost, ok := zhgCfg.OutbreakCostDict[unitType]; ok { - cost = unitCost + // 四舍五入计算 + cost = decimal.NewFromInt(count).Mul(decimal.NewFromFloat(unitCost)).Round(0).IntPart() } else { - cost = zhgCfg.OutbreakBaseCost + return } + logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username) + room.Broadcast(pb.PushZhgOutbreakFood, &pbGameZhg.OutbreakFood{ User: user, UnitType: unitTypeStr, - Count: int32(zhgCfg.OutbreakCount), + Count: int32(count), Cost: cost, }) } diff --git a/pkg/cmd/cmd_parser.go b/pkg/cmd/cmd_parser.go index a9543df..58e6807 100644 --- a/pkg/cmd/cmd_parser.go +++ b/pkg/cmd/cmd_parser.go @@ -1,6 +1,7 @@ package cmd import ( + "database/sql" "git.noahlan.cn/northlan/ntools-go/stringn/ac" "strings" ) @@ -16,16 +17,17 @@ type ( } Parser struct { ac ac.AhoCorasick // ac自动机 - distinct bool // 命令是否去重 + distinct bool // 命令是否去重(总开关) patterns []Pattern // 匹配规则 } Pattern struct { - Prefix string // 前缀 - Alias []string // 前缀别名 - ContentMaxLen int // 内容最大长度,以rune数组长度计算 - isAlias bool // alias - realPattern *Pattern // 作为Alias时指向的实际Pattern + Prefix string // 前缀 + Alias []string // 前缀别名 + ContentMaxLen int // 内容最大长度,以rune数组长度计算 + Distinct sql.NullBool // Distinct 命令是否去重 单个权重大于总开关 + isAlias bool // alias + realPattern *Pattern // 作为Alias时指向的实际Pattern } ) @@ -60,6 +62,7 @@ func (p *Parser) initPattern(patterns []Pattern) []string { Prefix: pattern.Prefix, Alias: pattern.Alias, ContentMaxLen: pattern.ContentMaxLen, + Distinct: pattern.Distinct, }, }) result = append(result, alias) @@ -98,13 +101,22 @@ func (p *Parser) Parse(msg string) CMD { tmpNext := iter.Next() // 避免同类型指令重复 - if p.distinct { + if pattern.Distinct.Valid && pattern.Distinct.Bool { for _, m := range resp.Matches { if m.Prefix == pattern.Prefix { goto end // continue out for } } } + if p.distinct { + if !pattern.Distinct.Valid || pattern.Distinct.Bool { + for _, m := range resp.Matches { + if m.Prefix == pattern.Prefix { + goto end // continue out for + } + } + } + } if tmpNext != nil { //nextPattern := p.patterns[tmpNext.Pattern()] diff --git a/pkg/cmd/cmd_parser_test.go b/pkg/cmd/cmd_parser_test.go index 7c7e719..9d17911 100644 --- a/pkg/cmd/cmd_parser_test.go +++ b/pkg/cmd/cmd_parser_test.go @@ -1,7 +1,11 @@ package cmd import ( + "database/sql" "fmt" + "github.com/shopspring/decimal" + "strconv" + "strings" "testing" ) @@ -19,7 +23,8 @@ var p = NewCMDParser(Pattern{ ContentMaxLen: 0, }, Pattern{ Prefix: "s", - ContentMaxLen: 1, + ContentMaxLen: 4, + Distinct: sql.NullBool{Bool: false, Valid: true}, }, Pattern{ Prefix: "m", ContentMaxLen: 1, @@ -77,8 +82,10 @@ func TestParse(t *testing.T) { } func TestA(t *testing.T) { - p.SetDistinct(false) - cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1") + p.SetDistinct(true) + //cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1s3s5") + //cmd := p.Parse("输入j 加入游戏哦") + cmd := p.Parse("s1#10s2s3") fmt.Println(cmd.IsCMD) for _, match := range cmd.Matches { @@ -86,6 +93,42 @@ func TestA(t *testing.T) { } } +func TestOutbreak(t *testing.T) { + content := []rune("111,") + + contentStr := string(content) + + var unitTypeStr string + var count int64 + var err error + idxSplit := strings.IndexRune(contentStr, ',') + if idxSplit == -1 { + // 没有分隔符,判断内容位数? + unitTypeStr = string(content) + count = 3 + } else { + unitTypeStr = string(content[:idxSplit]) + if idxSplit == len(content)-1 { + count = 3 + } else { + count, err = strconv.ParseInt(string(content[idxSplit+1:]), 10, 0) + if err != nil { + return + } + } + if count > 30 { + count = 30 + } + if count <= 0 { + count = 3 + } + } + + cost := decimal.NewFromInt(count).Mul(decimal.NewFromFloat(1.3)).Round(0).IntPart() + + fmt.Println(unitTypeStr, count, cost) +} + func BenchmarkCmd(b *testing.B) { content := "jc2"