Merge branches 'meixiongfeng' and 'dev' of http://git.legu.cc/liwei_3d/go_dreamfactory into meixiongfeng

This commit is contained in:
meixiongfeng 2022-08-29 11:47:00 +08:00
commit fe868ea764
16 changed files with 1159 additions and 26 deletions

View File

@ -114,6 +114,7 @@ func (this *appTerm) LazyInit(obs observer.Observer) error {
//excute //excute
excuteBtn := &widget.Button{Text: "执行", Icon: theme.ConfirmIcon()} excuteBtn := &widget.Button{Text: "执行", Icon: theme.ConfirmIcon()}
excuteBtn.TypedKey(&fyne.KeyEvent{Name: fyne.KeyEnter})
excuteBtn.OnTapped = func() { excuteBtn.OnTapped = func() {
output.Text = "" output.Text = ""
excuteBtn.Disable() excuteBtn.Disable()
@ -136,7 +137,7 @@ func (this *appTerm) LazyInit(obs observer.Observer) error {
split := container.NewVSplit(container.NewGridWithColumns(2, split := container.NewVSplit(container.NewGridWithColumns(2,
cmdLast, cmdLast,
container.NewBorder(configForm, btns, widget.NewSeparator(), nil)), output) container.NewBorder(configForm, btns, widget.NewSeparator(), nil)), output)
split.Offset = 0.3 split.Offset = 0.25
content.Objects = append(content.Objects, split) content.Objects = append(content.Objects, split)
this.tabItem.Content = content this.tabItem.Content = content

View File

@ -115,6 +115,11 @@ func (this *MCompModel) GetListObj(uid string, id string, data interface{}) (err
return this.DBModel.GetListObj(uid, id, data) return this.DBModel.GetListObj(uid, id, data)
} }
//批量读取列表中多个数据
func (this *MCompModel) GetListObjs(uid string, ids []string, data interface{}) (err error) {
return this.DBModel.GetListObjs(uid, ids, data)
}
//删除用户数据 //删除用户数据
func (this *MCompModel) Del(uid string, opt ...db.DBOption) (err error) { func (this *MCompModel) Del(uid string, opt ...db.DBOption) (err error) {
return this.DBModel.Del(uid, opt...) return this.DBModel.Del(uid, opt...)

View File

@ -0,0 +1,35 @@
package equipment
import (
"go_dreamfactory/comm"
"go_dreamfactory/pb"
"google.golang.org/protobuf/proto"
)
//参数校验
func (this *apiComp) LockCheck(session comm.IUserSession, req *pb.EquipmentLockReq) (code pb.ErrorCode) {
if req.EquipmentId == "" {
code = pb.ErrorCode_ReqParameterError
}
return
}
///获取用户装备列表
func (this *apiComp) Lock(session comm.IUserSession, req *pb.EquipmentLockReq) (code pb.ErrorCode, data proto.Message) {
var (
err error
equipment *pb.DB_Equipment
)
if code = this.LockCheck(session, req); code != pb.ErrorCode_Success {
return
}
if equipment, err = this.module.modelEquipment.QueryUserEquipmentsById(session.GetUserId(), req.EquipmentId); err != nil {
this.module.Errorf("Equip_Check err:%v", err)
code = pb.ErrorCode_EquipmentOnFoundEquipment
return
}
equipment.Lock = req.IsLock
session.SendMsg(string(this.module.GetType()), "getlist", &pb.EquipmentLockResp{IsSucc: true, EquipmentId: req.EquipmentId, IsLock: req.IsLock})
return
}

View File

@ -0,0 +1,62 @@
package equipment
import (
"go_dreamfactory/comm"
"go_dreamfactory/pb"
cfg "go_dreamfactory/sys/configure/structs"
"google.golang.org/protobuf/proto"
)
//参数校验
func (this *apiComp) SellCheck(session comm.IUserSession, req *pb.EquipmentSellReq) (code pb.ErrorCode) {
if req.EquipIds == nil || len(req.EquipIds) == 0 {
code = pb.ErrorCode_ReqParameterError
}
return
}
//出售
func (this *apiComp) Sell(session comm.IUserSession, req *pb.EquipmentSellReq) (code pb.ErrorCode, data proto.Message) {
var (
err error
equipments []*pb.DB_Equipment
confs []*cfg.GameEquipData
sale []*cfg.Gameatn
)
if code = this.SellCheck(session, req); code != pb.ErrorCode_Success {
return
}
if equipments, err = this.module.modelEquipment.QueryUserEquipmentsByIds(session.GetUserId(), req.EquipIds); err != nil {
code = pb.ErrorCode_ReqParameterError
return
}
confs = make([]*cfg.GameEquipData, len(equipments))
for i, v := range equipments {
if v.HeroId != "" || v.Lock {
code = pb.ErrorCode_EquipmentNoCanSell
this.module.Errorf("NoCanSell %v", v)
return
}
if confs[i], err = this.module.configure.GetEquipmentConfigureById(v.CId); err != nil {
this.module.Errorln(err)
code = pb.ErrorCode_EquipmentOnFoundEquipment
return
}
}
sale = make([]*cfg.Gameatn, 0)
for _, v := range confs {
for _, s := range v.Sale {
sale = append(sale, s)
}
}
if code = this.module.DispenseRes(session, sale, true); code != pb.ErrorCode_Success {
return
}
if code = this.module.DelEquipments(session, req.EquipIds, true); code != pb.ErrorCode_Success {
return
}
session.SendMsg(string(this.module.GetType()), "sell", &pb.ItemsUseItemResp{Issucc: true})
return
}

View File

@ -70,6 +70,30 @@ func (this *configureComp) GetEquipmentConfigureById(equipmentId string) (config
return return
} }
//获取装备配置数据
func (this *configureComp) GetEquipmentConfigureByIds(equipmentId []string) (configure []*cfg.GameEquipData, err error) {
var (
t interface{}
c *cfg.GameEquipData
ok bool
)
if t, err = this.GetConfigure(game_equip); err != nil {
this.module.Errorf("err:%v", err)
return
} else {
configure = make([]*cfg.GameEquipData, len(equipmentId))
for i, v := range equipmentId {
if c, ok = t.(*cfg.GameEquip).GetDataMap()[v]; ok {
configure[i] = c
return
}
}
}
return
}
//获取装备属性表 //获取装备属性表
func (this *configureComp) GetEquipmentAttrlibraryConfigure() (configure *cfg.GameEquipAttrlibrary, err error) { func (this *configureComp) GetEquipmentAttrlibraryConfigure() (configure *cfg.GameEquipAttrlibrary, err error) {
var ( var (

View File

@ -40,6 +40,13 @@ func (this *modelEquipmentComp) QueryUserEquipmentsById(uId, id string) (equipme
return return
} }
//查询用户装备数据
func (this *modelEquipmentComp) QueryUserEquipmentsByIds(uId string, ids []string) (equipments []*pb.DB_Equipment, err error) {
equipments = []*pb.DB_Equipment{}
err = this.GetListObjs(uId, ids, &equipments)
return
}
///查询用户的武器背包 ///查询用户的武器背包
func (this *modelEquipmentComp) QueryUserEquipments(uId string) (equipments []*pb.DB_Equipment, err error) { func (this *modelEquipmentComp) QueryUserEquipments(uId string) (equipments []*pb.DB_Equipment, err error) {
equipments = make([]*pb.DB_Equipment, 0) equipments = make([]*pb.DB_Equipment, 0)
@ -123,6 +130,23 @@ func (this *modelEquipmentComp) AddEquipments(uId string, cIds map[string]uint32
return return
} }
//删除装备
func (this *modelEquipmentComp) DelEquipments(uId string, eIds []string) (change []*pb.DB_Equipment, err error) {
change = make([]*pb.DB_Equipment, 0)
if err = this.DelListlds(uId, eIds...); err != nil {
this.module.Errorln(err)
return
}
for _, v := range eIds {
change = append(change, &pb.DB_Equipment{
Id: v,
UId: uId,
OverlayNum: 0,
})
}
return
}
//更新武器挂载信息 //更新武器挂载信息
func (this *modelEquipmentComp) UpdateByHeroId(uid string, equipments ...*pb.DB_Equipment) (err error) { func (this *modelEquipmentComp) UpdateByHeroId(uid string, equipments ...*pb.DB_Equipment) (err error) {
for _, v := range equipments { for _, v := range equipments {

View File

@ -104,11 +104,26 @@ func (this *Equipment) AddNewEquipments(source *comm.ModuleCallSource, session c
return return
} }
//删除武器
func (this *Equipment) DelEquipments(session comm.IUserSession, equipIds []string, bPush bool) (code pb.ErrorCode) {
var (
err error
change []*pb.DB_Equipment
)
if change, err = this.modelEquipment.DelEquipments(session.GetUserId(), equipIds); err != nil {
this.Errorf("err%v", err)
code = pb.ErrorCode_SystemError
return
}
if len(change) > 0 && bPush {
this.equipmentsChangePush(session, change)
}
return
}
//Evens-------------------------------------------------------------------------------------------------------------------------------- //Evens--------------------------------------------------------------------------------------------------------------------------------
//推送道具变化消息 //推送道具变化消息
func (this *Equipment) equipmentsChangePush(session comm.IUserSession, items []*pb.DB_Equipment) (err error) { func (this *Equipment) equipmentsChangePush(session comm.IUserSession, items []*pb.DB_Equipment) (err error) {
session.SendMsg(string(this.GetType()), "change", &pb.EquipmentChangePush{Equipments: items}) session.SendMsg(string(this.GetType()), "change", &pb.EquipmentChangePush{Equipments: items})
return return
} }

View File

@ -41,7 +41,7 @@ func (this *modelMartialhall) queryUserMartialhall(uid string) (result *pb.DBMar
Id: primitive.NewObjectID().Hex(), Id: primitive.NewObjectID().Hex(),
Uid: uid, Uid: uid,
Lv: 1, Lv: 1,
Pillar1: &pb.DBPillar{Index: 1}, Pillar1: &pb.DBPillar{Index: 1, Isunlock: true},
Pillar2: &pb.DBPillar{Index: 2}, Pillar2: &pb.DBPillar{Index: 2},
Pillar3: &pb.DBPillar{Index: 3}, Pillar3: &pb.DBPillar{Index: 3},
Pillar4: &pb.DBPillar{Index: 4}, Pillar4: &pb.DBPillar{Index: 4},

View File

@ -52,8 +52,10 @@ func (this *ModuleTask) Start() (err error) {
} }
//初始化日常、周常、成就 //初始化日常、周常、成就
func (this *ModuleTask) InitTask(uid string, taskTag comm.TaskTag) { func (this *ModuleTask) InitTaskAll(uid string) {
this.modelTask.initTask(uid, taskTag) this.modelTask.initTask(uid, comm.TASK_DAILY)
this.modelTask.initTask(uid, comm.TASK_WEEKLY)
this.modelTask.initTask(uid, comm.TASK_ACHIEVE)
this.modelTaskActive.initActiveReward(uid) this.modelTaskActive.initActiveReward(uid)
} }
@ -96,7 +98,7 @@ func (this *ModuleTask) ResetTask(uid string, taskTag comm.TaskTag) {
this.resetActive(uid, taskTag) this.resetActive(uid, taskTag)
this.modelTask.clearTask(uid, taskTag) this.modelTask.clearTask(uid, taskTag)
this.modelTaskActive.clearTask(uid, taskTag) this.modelTaskActive.clearTask(uid, taskTag)
this.InitTask(uid, taskTag) this.InitTaskAll(uid)
} }
//任务处理 //任务处理

View File

@ -116,6 +116,7 @@ type DB_Equipment struct {
AdverbEntry []*EquipmentAttributeEntry `protobuf:"bytes,9,rep,name=adverbEntry,proto3" json:"adverbEntry" bson:"adverbEntry"` //装备副词条 AdverbEntry []*EquipmentAttributeEntry `protobuf:"bytes,9,rep,name=adverbEntry,proto3" json:"adverbEntry" bson:"adverbEntry"` //装备副词条
OverlayNum uint32 `protobuf:"varint,10,opt,name=overlayNum,proto3" json:"overlayNum" bson:"overlayNum"` //叠加数量 OverlayNum uint32 `protobuf:"varint,10,opt,name=overlayNum,proto3" json:"overlayNum" bson:"overlayNum"` //叠加数量
IsInitialState bool `protobuf:"varint,11,opt,name=isInitialState,proto3" json:"isInitialState" bson:"isInitialState"` //是否初始状态 IsInitialState bool `protobuf:"varint,11,opt,name=isInitialState,proto3" json:"isInitialState" bson:"isInitialState"` //是否初始状态
Lock bool `protobuf:"varint,12,opt,name=lock,proto3" json:"lock" bson:"lock"` //是否锁
} }
func (x *DB_Equipment) Reset() { func (x *DB_Equipment) Reset() {
@ -220,6 +221,13 @@ func (x *DB_Equipment) GetIsInitialState() bool {
return false return false
} }
func (x *DB_Equipment) GetLock() bool {
if x != nil {
return x.Lock
}
return false
}
var File_equipment_equipment_db_proto protoreflect.FileDescriptor var File_equipment_equipment_db_proto protoreflect.FileDescriptor
var file_equipment_equipment_db_proto_rawDesc = []byte{ var file_equipment_equipment_db_proto_rawDesc = []byte{
@ -233,7 +241,7 @@ var file_equipment_equipment_db_proto_rawDesc = []byte{
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, 0x74, 0x74, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, 0x74, 0x74, 0x72,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x4c, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x4c, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x4c, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x52, 0x02, 0x4c, 0x76, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc8, 0x02, 0x0a, 0x0c, 0x44, 0x01, 0x28, 0x05, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xdc, 0x02, 0x0a, 0x0c, 0x44,
0x42, 0x5f, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x42, 0x5f, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x63,
0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x49, 0x64, 0x12, 0x10, 0x0a,
@ -254,8 +262,9 @@ var file_equipment_equipment_db_proto_rawDesc = []byte{
0x0d, 0x52, 0x0a, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x4e, 0x75, 0x6d, 0x12, 0x26, 0x0a, 0x0d, 0x52, 0x0a, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x4e, 0x75, 0x6d, 0x12, 0x26, 0x0a,
0x0e, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0e, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18,
0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20,
0x72, 0x6f, 0x74, 0x6f, 0x33, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70,
0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -307,14 +307,15 @@ func (x *EquipmentUpgradeReq) GetEquipmentId() string {
return "" return ""
} }
//装备升级 回应 //装备升级 回应 由于装备可以叠加 升级后会创建一个新的装备出来
//所以可能影响两个装备
type EquipmentUpgradeResp struct { type EquipmentUpgradeResp struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
IsSucc bool `protobuf:"varint,1,opt,name=IsSucc,proto3" json:"IsSucc"` IsSucc bool `protobuf:"varint,1,opt,name=IsSucc,proto3" json:"IsSucc"`
Equipment []*DB_Equipment `protobuf:"bytes,2,rep,name=Equipment,proto3" json:"Equipment"` //由于装备可以叠加 升级后会创建一个新的装备出来 所以可能影响两个装备 Equipment []*DB_Equipment `protobuf:"bytes,2,rep,name=Equipment,proto3" json:"Equipment"`
} }
func (x *EquipmentUpgradeResp) Reset() { func (x *EquipmentUpgradeResp) Reset() {
@ -363,6 +364,222 @@ func (x *EquipmentUpgradeResp) GetEquipment() []*DB_Equipment {
return nil return nil
} }
//出售道具请求sailitem
type EquipmentLockReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
EquipmentId string `protobuf:"bytes,1,opt,name=EquipmentId,proto3" json:"EquipmentId"` //装备的唯一id
IsLock bool `protobuf:"varint,2,opt,name=IsLock,proto3" json:"IsLock"` //是否锁
}
func (x *EquipmentLockReq) Reset() {
*x = EquipmentLockReq{}
if protoimpl.UnsafeEnabled {
mi := &file_equipment_equipment_msg_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EquipmentLockReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EquipmentLockReq) ProtoMessage() {}
func (x *EquipmentLockReq) ProtoReflect() protoreflect.Message {
mi := &file_equipment_equipment_msg_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EquipmentLockReq.ProtoReflect.Descriptor instead.
func (*EquipmentLockReq) Descriptor() ([]byte, []int) {
return file_equipment_equipment_msg_proto_rawDescGZIP(), []int{7}
}
func (x *EquipmentLockReq) GetEquipmentId() string {
if x != nil {
return x.EquipmentId
}
return ""
}
func (x *EquipmentLockReq) GetIsLock() bool {
if x != nil {
return x.IsLock
}
return false
}
//出售道具请求 回应
type EquipmentLockResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
IsSucc bool `protobuf:"varint,1,opt,name=IsSucc,proto3" json:"IsSucc"`
EquipmentId string `protobuf:"bytes,2,opt,name=EquipmentId,proto3" json:"EquipmentId"`
IsLock bool `protobuf:"varint,3,opt,name=IsLock,proto3" json:"IsLock"`
}
func (x *EquipmentLockResp) Reset() {
*x = EquipmentLockResp{}
if protoimpl.UnsafeEnabled {
mi := &file_equipment_equipment_msg_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EquipmentLockResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EquipmentLockResp) ProtoMessage() {}
func (x *EquipmentLockResp) ProtoReflect() protoreflect.Message {
mi := &file_equipment_equipment_msg_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EquipmentLockResp.ProtoReflect.Descriptor instead.
func (*EquipmentLockResp) Descriptor() ([]byte, []int) {
return file_equipment_equipment_msg_proto_rawDescGZIP(), []int{8}
}
func (x *EquipmentLockResp) GetIsSucc() bool {
if x != nil {
return x.IsSucc
}
return false
}
func (x *EquipmentLockResp) GetEquipmentId() string {
if x != nil {
return x.EquipmentId
}
return ""
}
func (x *EquipmentLockResp) GetIsLock() bool {
if x != nil {
return x.IsLock
}
return false
}
//出售道具请求sailitem
type EquipmentSellReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
EquipIds []string `protobuf:"bytes,1,rep,name=EquipIds,proto3" json:"EquipIds"`
}
func (x *EquipmentSellReq) Reset() {
*x = EquipmentSellReq{}
if protoimpl.UnsafeEnabled {
mi := &file_equipment_equipment_msg_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EquipmentSellReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EquipmentSellReq) ProtoMessage() {}
func (x *EquipmentSellReq) ProtoReflect() protoreflect.Message {
mi := &file_equipment_equipment_msg_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EquipmentSellReq.ProtoReflect.Descriptor instead.
func (*EquipmentSellReq) Descriptor() ([]byte, []int) {
return file_equipment_equipment_msg_proto_rawDescGZIP(), []int{9}
}
func (x *EquipmentSellReq) GetEquipIds() []string {
if x != nil {
return x.EquipIds
}
return nil
}
//出售道具请求 回应
type EquipmentSellResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
IsSucc bool `protobuf:"varint,1,opt,name=IsSucc,proto3" json:"IsSucc"`
}
func (x *EquipmentSellResp) Reset() {
*x = EquipmentSellResp{}
if protoimpl.UnsafeEnabled {
mi := &file_equipment_equipment_msg_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EquipmentSellResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EquipmentSellResp) ProtoMessage() {}
func (x *EquipmentSellResp) ProtoReflect() protoreflect.Message {
mi := &file_equipment_equipment_msg_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EquipmentSellResp.ProtoReflect.Descriptor instead.
func (*EquipmentSellResp) Descriptor() ([]byte, []int) {
return file_equipment_equipment_msg_proto_rawDescGZIP(), []int{10}
}
func (x *EquipmentSellResp) GetIsSucc() bool {
if x != nil {
return x.IsSucc
}
return false
}
var File_equipment_equipment_msg_proto protoreflect.FileDescriptor var File_equipment_equipment_msg_proto protoreflect.FileDescriptor
var file_equipment_equipment_msg_proto_rawDesc = []byte{ var file_equipment_equipment_msg_proto_rawDesc = []byte{
@ -399,8 +616,25 @@ var file_equipment_equipment_msg_proto_rawDesc = []byte{
0x49, 0x73, 0x53, 0x75, 0x63, 0x63, 0x12, 0x2b, 0x0a, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x49, 0x73, 0x53, 0x75, 0x63, 0x63, 0x12, 0x2b, 0x0a, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d,
0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x44, 0x42, 0x5f, 0x45, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x44, 0x42, 0x5f, 0x45,
0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d,
0x65, 0x6e, 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x65, 0x6e, 0x74, 0x22, 0x4c, 0x0a, 0x10, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74,
0x74, 0x6f, 0x33, 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x71, 0x75, 0x69, 0x70,
0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x71,
0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x4c,
0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x73, 0x4c, 0x6f, 0x63,
0x6b, 0x22, 0x65, 0x0a, 0x11, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x6f,
0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x53, 0x75, 0x63, 0x63,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x73, 0x53, 0x75, 0x63, 0x63, 0x12, 0x20,
0x0a, 0x0b, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
0x52, 0x06, 0x49, 0x73, 0x4c, 0x6f, 0x63, 0x6b, 0x22, 0x2e, 0x0a, 0x10, 0x45, 0x71, 0x75, 0x69,
0x70, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08,
0x45, 0x71, 0x75, 0x69, 0x70, 0x49, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08,
0x45, 0x71, 0x75, 0x69, 0x70, 0x49, 0x64, 0x73, 0x22, 0x2b, 0x0a, 0x11, 0x45, 0x71, 0x75, 0x69,
0x70, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a,
0x06, 0x49, 0x73, 0x53, 0x75, 0x63, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49,
0x73, 0x53, 0x75, 0x63, 0x63, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -415,7 +649,7 @@ func file_equipment_equipment_msg_proto_rawDescGZIP() []byte {
return file_equipment_equipment_msg_proto_rawDescData return file_equipment_equipment_msg_proto_rawDescData
} }
var file_equipment_equipment_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_equipment_equipment_msg_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_equipment_equipment_msg_proto_goTypes = []interface{}{ var file_equipment_equipment_msg_proto_goTypes = []interface{}{
(*EquipmentGetListReq)(nil), // 0: EquipmentGetListReq (*EquipmentGetListReq)(nil), // 0: EquipmentGetListReq
(*EquipmentGetListResp)(nil), // 1: EquipmentGetListResp (*EquipmentGetListResp)(nil), // 1: EquipmentGetListResp
@ -424,13 +658,17 @@ var file_equipment_equipment_msg_proto_goTypes = []interface{}{
(*EquipmentEquipResp)(nil), // 4: EquipmentEquipResp (*EquipmentEquipResp)(nil), // 4: EquipmentEquipResp
(*EquipmentUpgradeReq)(nil), // 5: EquipmentUpgradeReq (*EquipmentUpgradeReq)(nil), // 5: EquipmentUpgradeReq
(*EquipmentUpgradeResp)(nil), // 6: EquipmentUpgradeResp (*EquipmentUpgradeResp)(nil), // 6: EquipmentUpgradeResp
(*DB_Equipment)(nil), // 7: DB_Equipment (*EquipmentLockReq)(nil), // 7: EquipmentLockReq
(*EquipmentLockResp)(nil), // 8: EquipmentLockResp
(*EquipmentSellReq)(nil), // 9: EquipmentSellReq
(*EquipmentSellResp)(nil), // 10: EquipmentSellResp
(*DB_Equipment)(nil), // 11: DB_Equipment
} }
var file_equipment_equipment_msg_proto_depIdxs = []int32{ var file_equipment_equipment_msg_proto_depIdxs = []int32{
7, // 0: EquipmentGetListResp.Equipments:type_name -> DB_Equipment 11, // 0: EquipmentGetListResp.Equipments:type_name -> DB_Equipment
7, // 1: EquipmentChangePush.Equipments:type_name -> DB_Equipment 11, // 1: EquipmentChangePush.Equipments:type_name -> DB_Equipment
7, // 2: EquipmentEquipResp.Equipments:type_name -> DB_Equipment 11, // 2: EquipmentEquipResp.Equipments:type_name -> DB_Equipment
7, // 3: EquipmentUpgradeResp.Equipment:type_name -> DB_Equipment 11, // 3: EquipmentUpgradeResp.Equipment:type_name -> DB_Equipment
4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension type_name
@ -529,6 +767,54 @@ func file_equipment_equipment_msg_proto_init() {
return nil return nil
} }
} }
file_equipment_equipment_msg_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EquipmentLockReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_equipment_equipment_msg_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EquipmentLockResp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_equipment_equipment_msg_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EquipmentSellReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_equipment_equipment_msg_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EquipmentSellResp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@ -536,7 +822,7 @@ func file_equipment_equipment_msg_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_equipment_equipment_msg_proto_rawDesc, RawDescriptor: file_equipment_equipment_msg_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 7, NumMessages: 11,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@ -8,6 +8,7 @@ import (
"go_dreamfactory/lego/sys/log" "go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/mgo" "go_dreamfactory/lego/sys/mgo"
lgredis "go_dreamfactory/lego/sys/redis" lgredis "go_dreamfactory/lego/sys/redis"
"go_dreamfactory/lego/sys/redis/pipe"
"go_dreamfactory/lego/utils/codec" "go_dreamfactory/lego/utils/codec"
"go_dreamfactory/lego/utils/codec/codecore" "go_dreamfactory/lego/utils/codec/codecore"
"go_dreamfactory/lego/utils/codec/json" "go_dreamfactory/lego/utils/codec/json"
@ -631,6 +632,118 @@ func (this *DBModel) GetListObj(uid string, id string, data interface{}) (err er
return return
} }
//读取列表数据中单个数据
func (this *DBModel) GetListObjs(uid string, ids []string, data interface{}) (err error) {
var (
dtype reflect2.Type
dkind reflect.Kind
sType reflect2.Type
sliceType *reflect2.UnsafeSliceType
sliceelemType reflect2.Type
decoder codecore.IDecoderMapJson
encoder codecore.IEncoderMapJson
dptr unsafe.Pointer
elemPtr unsafe.Pointer
n int
ok bool
keys map[string]string = make(map[string]string)
tempdata map[string]string
onfound []string = make([]string, 0, len(ids))
pipe *pipe.RedisPipe = this.Redis.RedisPipe(context.TODO())
result []*redis.StringStringMapCmd = make([]*redis.StringStringMapCmd, len(ids))
c *mongo.Cursor
)
dptr = reflect2.PtrOf(data)
dtype = reflect2.TypeOf(data)
dkind = dtype.Kind()
if dkind != reflect.Ptr {
err = fmt.Errorf("MCompModel: GetList(non-pointer %T)", data)
return
}
sType = dtype.(*reflect2.UnsafePtrType).Elem()
if sType.Kind() != reflect.Slice {
err = fmt.Errorf("MCompModel: GetList(data no slice %T)", data)
return
}
sliceType = sType.(*reflect2.UnsafeSliceType)
sliceelemType = sliceType.Elem()
if sliceelemType.Kind() != reflect.Ptr {
err = fmt.Errorf("MCompModel: GetList(sliceelemType non-pointer %T)", data)
return
}
if decoder, ok = codec.DecoderOf(sliceelemType, defconf).(codecore.IDecoderMapJson); !ok {
err = fmt.Errorf("MCompModel: GetList(data not support MarshalMapJson %T)", data)
return
}
sliceelemType = sliceelemType.(*reflect2.UnsafePtrType).Elem()
for i, v := range ids {
result[i] = pipe.HGetAllToMapString(this.ukeylist(uid, v))
}
if _, err = pipe.Exec(); err == nil {
for i, v := range result {
if tempdata, err = v.Result(); err == nil {
sliceType.UnsafeGrow(dptr, n+1)
elemPtr = sliceType.UnsafeGetIndex(dptr, n)
if *((*unsafe.Pointer)(elemPtr)) == nil {
newPtr := sliceelemType.UnsafeNew()
if err = decoder.DecodeForMapJson(newPtr, json.GetReader([]byte{}), tempdata); err != nil {
log.Errorf("err:%v", err)
return
}
*((*unsafe.Pointer)(elemPtr)) = newPtr
} else {
decoder.DecodeForMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetReader([]byte{}), tempdata)
}
n++
} else {
onfound = append(onfound, ids[i])
}
}
} else {
onfound = ids
}
if err == lgredis.RedisNil {
if c, err = this.DB.Find(core.SqlTable(this.TableName), bson.M{"uid": uid}); err != nil {
return err
} else {
pipe := this.Redis.RedisPipe(context.TODO())
for c.Next(context.Background()) {
_id := c.Current.Lookup("_id").StringValue()
sliceType.UnsafeGrow(dptr, n+1)
elemPtr = sliceType.UnsafeGetIndex(dptr, n)
if *((*unsafe.Pointer)(elemPtr)) == nil {
newPtr := sliceelemType.UnsafeNew()
*((*unsafe.Pointer)(elemPtr)) = newPtr
}
elem := sliceType.GetIndex(data, n)
if err = c.Decode(elem); err != nil {
return
}
if tempdata, err = encoder.EncodeToMapJson(*((*unsafe.Pointer)(elemPtr)), json.GetWriter()); err != nil {
return
}
key := this.ukeylist(uid, _id)
pipe.HMSetForMap(key, tempdata)
keys[_id] = key
n++
}
if len(keys) > 0 {
pipe.HMSetForMap(this.ukey(uid), keys)
_, err = pipe.Exec()
}
}
}
if this.Expired > 0 {
childs := make(map[string]struct{}, len(keys))
for _, v := range keys {
childs[v] = struct{}{}
}
UpDateModelExpired(this.ukey(uid), childs, this.Expired)
}
return
}
//删除用户数据 //删除用户数据
func (this *DBModel) Del(uid string, opt ...DBOption) (err error) { func (this *DBModel) Del(uid string, opt ...DBOption) (err error) {
err = this.Redis.Delete(this.ukey(uid)) err = this.Redis.Delete(this.ukey(uid))

119
sys/wordfilter/core.go Normal file
View File

@ -0,0 +1,119 @@
package wordfilter
import "io"
/*
系统:单词守卫
描述:DFA 算法实践敏感词过滤 敏感词 过滤 验证 替换
*/
type (
ISys interface {
//加载文件
LoadWordDict(path string) error
//加载网络数据
LoadNetWordDict(url string) error
///加载
Load(rd io.Reader) error
///添加敏感词
AddWord(words ...string)
///删除敏感词
DelWord(words ...string)
///过滤敏感词
Filter(text string) string
///和谐敏感词
Replace(text string, repl rune) string
///检测敏感词
FindIn(text string) (bool, string)
///找到所有匹配词
FindAll(text string) []string
///检测字符串是否合法
Validate(text string) (bool, string)
///去除空格等噪音
RemoveNoise(text string) string
///更新去噪模式
UpdateNoisePattern(pattern string)
}
)
var (
defsys ISys
)
func OnInit(config map[string]interface{}, opt ...Option) (err error) {
var option *Options
if option, err = newOptions(config, opt...); err != nil {
return
}
defsys, err = newSys(option)
return
}
func NewSys(opt ...Option) (sys ISys, err error) {
var option *Options
if option, err = newOptionsByOption(opt...); err != nil {
return
}
sys, err = newSys(option)
return
}
//加载文件
func LoadWordDict(path string) error {
return defsys.LoadWordDict(path)
}
//加载网络数据
func LoadNetWordDict(url string) error {
return defsys.LoadNetWordDict(url)
}
///加载
func Load(rd io.Reader) error {
return defsys.Load(rd)
}
///添加敏感词
func AddWord(words ...string) {
defsys.AddWord(words...)
}
///删除敏感词
func DelWord(words ...string) {
defsys.DelWord(words...)
}
///过滤敏感词
func Filter(text string) string {
return defsys.Filter(text)
}
///和谐敏感词
func Replace(text string, repl rune) string {
return defsys.Replace(text, repl)
}
///检测敏感词
func FindIn(text string) (bool, string) {
return defsys.FindIn(text)
}
///找到所有匹配词
func FindAll(text string) []string {
return defsys.FindAll(text)
}
///检测字符串是否合法
func Validate(text string) (bool, string) {
return defsys.Validate(text)
}
///去除空格等噪音
func RemoveNoise(text string) string {
return defsys.RemoveNoise(text)
}
///更新去噪模式
func UpdateNoisePattern(pattern string) {
defsys.UpdateNoisePattern(pattern)
}

53
sys/wordfilter/options.go Normal file
View File

@ -0,0 +1,53 @@
package wordfilter
import (
"errors"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/utils/mapstructure"
)
type Option func(*Options)
type Options struct {
Debug bool //日志是否开启
Log log.Ilogf
}
func SetDebug(v bool) Option {
return func(o *Options) {
o.Debug = v
}
}
func SetLog(v log.Ilogf) Option {
return func(o *Options) {
o.Log = v
}
}
func newOptions(config map[string]interface{}, opts ...Option) (options *Options, err error) {
options = &Options{}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(options)
}
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.Blockcache", 2)); options.Log == nil {
err = errors.New("log is nil")
}
return
}
func newOptionsByOption(opts ...Option) (options *Options, err error) {
options = &Options{}
for _, o := range opts {
o(options)
}
if options.Log = log.NewTurnlog(options.Debug, log.Clone("sys.Blockcache", 2)); options.Log == nil {
err = errors.New("log is nil")
}
return
}

113
sys/wordfilter/sys.go Normal file
View File

@ -0,0 +1,113 @@
package wordfilter
import (
"bufio"
"io"
"net/http"
"os"
"regexp"
"time"
)
func newSys(options *Options) (sys *Sys, err error) {
sys = &Sys{
options: options,
trie: NewTrie(),
noise: regexp.MustCompile(`[\|\s&%$@*]+`),
}
return
}
type Sys struct {
options *Options
trie *Trie
noise *regexp.Regexp
}
// UpdateNoisePattern 更新去噪模式
func (Sys *Sys) UpdateNoisePattern(pattern string) {
Sys.noise = regexp.MustCompile(pattern)
}
// LoadWordDict 加载敏感词字典
func (Sys *Sys) LoadWordDict(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
return Sys.Load(f)
}
// LoadNetWordDict 加载网络敏感词字典
func (Sys *Sys) LoadNetWordDict(url string) error {
c := http.Client{
Timeout: 5 * time.Second,
}
rsp, err := c.Get(url)
if err != nil {
return err
}
defer rsp.Body.Close()
return Sys.Load(rsp.Body)
}
// Load common method to add words
func (Sys *Sys) Load(rd io.Reader) error {
buf := bufio.NewReader(rd)
for {
line, _, err := buf.ReadLine()
if err != nil {
if err != io.EOF {
return err
}
break
}
Sys.trie.Add(string(line))
}
return nil
}
// AddWord 添加敏感词
func (Sys *Sys) AddWord(words ...string) {
Sys.trie.Add(words...)
}
// DelWord 删除敏感词
func (Sys *Sys) DelWord(words ...string) {
Sys.trie.Del(words...)
}
// Sys 过滤敏感词
func (Sys *Sys) Filter(text string) string {
return Sys.trie.Filter(text)
}
// Replace 和谐敏感词
func (Sys *Sys) Replace(text string, repl rune) string {
return Sys.trie.Replace(text, repl)
}
// FindIn 检测敏感词
func (Sys *Sys) FindIn(text string) (bool, string) {
text = Sys.RemoveNoise(text)
return Sys.trie.FindIn(text)
}
// FindAll 找到所有匹配词
func (Sys *Sys) FindAll(text string) []string {
return Sys.trie.FindAll(text)
}
// Validate 检测字符串是否合法
func (Sys *Sys) Validate(text string) (bool, string) {
text = Sys.RemoveNoise(text)
return Sys.trie.Validate(text)
}
// RemoveNoise 去除空格等噪音
func (Sys *Sys) RemoveNoise(text string) string {
return Sys.noise.ReplaceAllString(text, "")
}

272
sys/wordfilter/trie.go Normal file
View File

@ -0,0 +1,272 @@
package wordfilter
// Node Trie树上的一个节点.
type Node struct {
isRootNode bool
isPathEnd bool
Character rune
Children map[rune]*Node
}
// Trie 短语组成的Trie树.
type Trie struct {
Root *Node
}
// NewTrie 新建一棵Trie
func NewTrie() *Trie {
return &Trie{
Root: NewRootNode(0),
}
}
// Add 添加若干个词
func (tree *Trie) Add(words ...string) {
for _, word := range words {
tree.add(word)
}
}
func (tree *Trie) add(word string) {
var current = tree.Root
var runes = []rune(word)
for position := 0; position < len(runes); position++ {
r := runes[position]
if next, ok := current.Children[r]; ok {
current = next
} else {
newNode := NewNode(r)
current.Children[r] = newNode
current = newNode
}
if position == len(runes)-1 {
current.isPathEnd = true
}
}
}
func (tree *Trie) Del(words ...string) {
for _, word := range words {
tree.del(word)
}
}
func (tree *Trie) del(word string) {
var current = tree.Root
var runes = []rune(word)
for position := 0; position < len(runes); position++ {
r := runes[position]
if next, ok := current.Children[r]; !ok {
return
} else {
current = next
}
if position == len(runes)-1 {
current.SoftDel()
}
}
}
// Replace 词语替换
func (tree *Trie) Replace(text string, character rune) string {
var (
parent = tree.Root
current *Node
runes = []rune(text)
length = len(runes)
left = 0
found bool
)
for position := 0; position < len(runes); position++ {
current, found = parent.Children[runes[position]]
if !found || (!current.IsPathEnd() && position == length-1) {
parent = tree.Root
position = left
left++
continue
}
// println(string(current.Character), current.IsPathEnd(), left)
if current.IsPathEnd() && left <= position {
for i := left; i <= position; i++ {
runes[i] = character
}
}
parent = current
}
return string(runes)
}
// Filter 直接过滤掉字符串中的敏感词
func (tree *Trie) Filter(text string) string {
var (
parent = tree.Root
current *Node
left = 0
found bool
runes = []rune(text)
length = len(runes)
resultRunes = make([]rune, 0, length)
)
for position := 0; position < length; position++ {
current, found = parent.Children[runes[position]]
if !found || (!current.IsPathEnd() && position == length-1) {
resultRunes = append(resultRunes, runes[left])
parent = tree.Root
position = left
left++
continue
}
if current.IsPathEnd() {
left = position + 1
parent = tree.Root
} else {
parent = current
}
}
resultRunes = append(resultRunes, runes[left:]...)
return string(resultRunes)
}
// Validate 验证字符串是否合法如不合法则返回false和检测到
// 的第一个敏感词
func (tree *Trie) Validate(text string) (bool, string) {
const (
Empty = ""
)
var (
parent = tree.Root
current *Node
runes = []rune(text)
length = len(runes)
left = 0
found bool
)
for position := 0; position < len(runes); position++ {
current, found = parent.Children[runes[position]]
if !found || (!current.IsPathEnd() && position == length-1) {
parent = tree.Root
position = left
left++
continue
}
if current.IsPathEnd() && left <= position {
return false, string(runes[left : position+1])
}
parent = current
}
return true, Empty
}
// FindIn 判断text中是否含有词库中的词
func (tree *Trie) FindIn(text string) (bool, string) {
validated, first := tree.Validate(text)
return !validated, first
}
// FindAll 找有所有包含在词库中的词
func (tree *Trie) FindAll(text string) []string {
var matches []string
var (
parent = tree.Root
current *Node
runes = []rune(text)
length = len(runes)
left = 0
found bool
)
for position := 0; position < length; position++ {
current, found = parent.Children[runes[position]]
if !found {
parent = tree.Root
position = left
left++
continue
}
if current.IsPathEnd() && left <= position {
matches = append(matches, string(runes[left:position+1]))
}
if position == length-1 {
parent = tree.Root
position = left
left++
continue
}
parent = current
}
var i = 0
if count := len(matches); count > 0 {
set := make(map[string]struct{})
for i < count {
_, ok := set[matches[i]]
if !ok {
set[matches[i]] = struct{}{}
i++
continue
}
count--
copy(matches[i:], matches[i+1:])
}
return matches[:count]
}
return nil
}
// NewNode 新建子节点
func NewNode(character rune) *Node {
return &Node{
Character: character,
Children: make(map[rune]*Node, 0),
}
}
// NewRootNode 新建根节点
func NewRootNode(character rune) *Node {
return &Node{
isRootNode: true,
Character: character,
Children: make(map[rune]*Node, 0),
}
}
// IsLeafNode 判断是否叶子节点
func (node *Node) IsLeafNode() bool {
return len(node.Children) == 0
}
// IsRootNode 判断是否为根节点
func (node *Node) IsRootNode() bool {
return node.isRootNode
}
// IsPathEnd 判断是否为某个路径的结束
func (node *Node) IsPathEnd() bool {
return node.isPathEnd
}
// SoftDel 置软删除状态
func (node *Node) SoftDel() {
node.isPathEnd = false
}