feat: 指令支持单独distinct配置,为zhg的s指令添加快捷方式s1,10(最大10)

main
NorthLan 3 years ago
parent 12bf4d3bed
commit fb7c0d4e63

@ -34,12 +34,13 @@ Game:
# 1元=10 Coin (1元40个步兵) # 1元=10 Coin (1元40个步兵)
CoinFoodRatio: 4 CoinFoodRatio: 4
OutbreakCount: 3 OutbreakCount: 3
OutbreakMaxCount: 10 # 3x10=30
OutbreakBaseCost: 5 OutbreakBaseCost: 5
OutbreakCostDict: OutbreakCostDict:
1: 3 # 步兵 1: 1 # 步兵
2: 7 # 骑兵 2: 2.333 # 骑兵
3: 4 # 弓箭手 3: 1.333 # 弓箭手
4: 3 # 法师 4: 1 # 法师
Zhghz: Zhghz:
Zhgfb: Zhgfb:
Zhgzd: Zhgzd:

@ -40,10 +40,11 @@ type (
AdminUserId []int64 // 管理员ID AdminUserId []int64 // 管理员ID
// Zhg 指挥官PvP模式 // Zhg 指挥官PvP模式
Zhg struct { Zhg struct {
CoinFoodRatio float32 // 硬币到粮草的转换系数(乘) CoinFoodRatio float32 // 硬币到粮草的转换系数(乘)
OutbreakCount int64 // 每次暴兵数量 OutbreakCount int64 // 默认暴兵指令每次暴兵数量
OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种) OutbreakMaxCount int64 // 单次暴兵数量最大限制
OutbreakCostDict map[int]int64 // 暴兵消耗表 OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种)
OutbreakCostDict map[int]float64 // 暴兵消耗表(单个兵)
} }
// Zhghz 指挥官海战模式 // Zhghz 指挥官海战模式
Zhghz struct { Zhghz struct {

@ -1,6 +1,7 @@
package live_logic package live_logic
import ( import (
"database/sql"
"dcg/app/user_center/usercenter" "dcg/app/user_center/usercenter"
"dcg/config" "dcg/config"
"dcg/game/manager" "dcg/game/manager"
@ -16,6 +17,7 @@ import (
"git.noahlan.cn/northlan/ntools-go/logger" "git.noahlan.cn/northlan/ntools-go/logger"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"strconv" "strconv"
"strings"
) )
type ZhgGameLogic struct { type ZhgGameLogic struct {
@ -24,57 +26,60 @@ type ZhgGameLogic struct {
} }
func NewZhgLiveGameLogic(svcCtx *svc.ServiceContext) *LiveGameLogic { 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{ resp := &ZhgGameLogic{
svcCtx: svcCtx, svcCtx: svcCtx,
LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmd.NewCMDParser( LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmdParser),
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,
},
)),
} }
resp.RegisterCMDHandler(resp.handleQuery, "q") resp.RegisterCMDHandler(resp.handleQuery, "q")
resp.RegisterCMDHandler(resp.handleJoinGame, "j") resp.RegisterCMDHandler(resp.handleJoinGame, "j")
@ -219,26 +224,54 @@ func (h *ZhgGameLogic) handleOutbreakFood(room *manager.Room, content []rune, us
if len(content) < 1 { if len(content) < 1 {
return 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) unitType, err := strconv.Atoi(unitTypeStr)
if err != nil { if err != nil {
return return
} }
zhgCfg := config.Config.Game.Zhg
var cost int64 var cost int64
if unitCost, ok := zhgCfg.OutbreakCostDict[unitType]; ok { if unitCost, ok := zhgCfg.OutbreakCostDict[unitType]; ok {
cost = unitCost // 四舍五入计算
cost = decimal.NewFromInt(count).Mul(decimal.NewFromFloat(unitCost)).Round(0).IntPart()
} else { } else {
cost = zhgCfg.OutbreakBaseCost return
} }
logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username)
room.Broadcast(pb.PushZhgOutbreakFood, &pbGameZhg.OutbreakFood{ room.Broadcast(pb.PushZhgOutbreakFood, &pbGameZhg.OutbreakFood{
User: user, User: user,
UnitType: unitTypeStr, UnitType: unitTypeStr,
Count: int32(zhgCfg.OutbreakCount), Count: int32(count),
Cost: cost, Cost: cost,
}) })
} }

@ -1,6 +1,7 @@
package cmd package cmd
import ( import (
"database/sql"
"git.noahlan.cn/northlan/ntools-go/stringn/ac" "git.noahlan.cn/northlan/ntools-go/stringn/ac"
"strings" "strings"
) )
@ -16,16 +17,17 @@ type (
} }
Parser struct { Parser struct {
ac ac.AhoCorasick // ac自动机 ac ac.AhoCorasick // ac自动机
distinct bool // 命令是否去重 distinct bool // 命令是否去重(总开关)
patterns []Pattern // 匹配规则 patterns []Pattern // 匹配规则
} }
Pattern struct { Pattern struct {
Prefix string // 前缀 Prefix string // 前缀
Alias []string // 前缀别名 Alias []string // 前缀别名
ContentMaxLen int // 内容最大长度,以rune数组长度计算 ContentMaxLen int // 内容最大长度,以rune数组长度计算
isAlias bool // alias Distinct sql.NullBool // Distinct 命令是否去重 单个权重大于总开关
realPattern *Pattern // 作为Alias时指向的实际Pattern isAlias bool // alias
realPattern *Pattern // 作为Alias时指向的实际Pattern
} }
) )
@ -60,6 +62,7 @@ func (p *Parser) initPattern(patterns []Pattern) []string {
Prefix: pattern.Prefix, Prefix: pattern.Prefix,
Alias: pattern.Alias, Alias: pattern.Alias,
ContentMaxLen: pattern.ContentMaxLen, ContentMaxLen: pattern.ContentMaxLen,
Distinct: pattern.Distinct,
}, },
}) })
result = append(result, alias) result = append(result, alias)
@ -98,13 +101,22 @@ func (p *Parser) Parse(msg string) CMD {
tmpNext := iter.Next() tmpNext := iter.Next()
// 避免同类型指令重复 // 避免同类型指令重复
if p.distinct { if pattern.Distinct.Valid && pattern.Distinct.Bool {
for _, m := range resp.Matches { for _, m := range resp.Matches {
if m.Prefix == pattern.Prefix { if m.Prefix == pattern.Prefix {
goto end // continue out for 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 { if tmpNext != nil {
//nextPattern := p.patterns[tmpNext.Pattern()] //nextPattern := p.patterns[tmpNext.Pattern()]

@ -1,7 +1,11 @@
package cmd package cmd
import ( import (
"database/sql"
"fmt" "fmt"
"github.com/shopspring/decimal"
"strconv"
"strings"
"testing" "testing"
) )
@ -19,7 +23,8 @@ var p = NewCMDParser(Pattern{
ContentMaxLen: 0, ContentMaxLen: 0,
}, Pattern{ }, Pattern{
Prefix: "s", Prefix: "s",
ContentMaxLen: 1, ContentMaxLen: 4,
Distinct: sql.NullBool{Bool: false, Valid: true},
}, Pattern{ }, Pattern{
Prefix: "m", Prefix: "m",
ContentMaxLen: 1, ContentMaxLen: 1,
@ -77,8 +82,10 @@ func TestParse(t *testing.T) {
} }
func TestA(t *testing.T) { func TestA(t *testing.T) {
p.SetDistinct(false) p.SetDistinct(true)
cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1") //cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1s3s5")
//cmd := p.Parse("输入j 加入游戏哦")
cmd := p.Parse("s1#10s2s3")
fmt.Println(cmd.IsCMD) fmt.Println(cmd.IsCMD)
for _, match := range cmd.Matches { 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) { func BenchmarkCmd(b *testing.B) {
content := "jc2" content := "jc2"

Loading…
Cancel
Save