go_dreamfactory/modules/sociaty/model_sociaty.go
2022-10-31 18:27:07 +08:00

645 lines
16 KiB
Go

package sociaty
import (
"context"
"errors"
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/lego/core"
event_v2 "go_dreamfactory/lego/sys/event/v2"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/modules"
"go_dreamfactory/pb"
cfg "go_dreamfactory/sys/configure/structs"
"go_dreamfactory/utils"
"sort"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
type Tag string
const (
Log_Job Tag = `%s玩家已经将%s玩家设为了%s` //职位变动
Log_Quit Tag = "%s玩家已经退出了公会" //退出
Log_Add Tag = `%s玩家加入了公会` //加入
Log_Upgrade Tag = "公会已经升为%s级" //升级
Log_Discharge Tag = "%s玩家已经将%s玩家逐出了公会" //踢出
)
type ModelSociaty struct {
modules.MCompModel
moduleSociaty *Sociaty
service core.IService
EventApp *event_v2.App
}
type SociatyListen struct {
event_v2.App
sociatyId string
name string
lv int32
activity int32
ctime int64
}
func (this *ModelSociaty) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
this.TableName = comm.TableSociaty
err = this.MCompModel.Init(service, module, comp, options)
this.moduleSociaty = module.(*Sociaty)
this.service = service
this.EventApp = event_v2.NewApp()
this.EventApp.Listen(comm.EventSociatyRankChanged, this.rankDataChanged)
return
}
// 创建公会
func (this *ModelSociaty) create(sociaty *pb.DBSociaty) error {
if sociaty == nil {
return fmt.Errorf("sociaty is nil")
}
_id := primitive.NewObjectID().Hex()
sociaty.Id = _id
sociaty.Ctime = time.Now().Unix()
sociaty.Lv = 1 //默认1级
if sociaty.Icon == "" {
sociaty.Icon = "1000" //默认图标
}
if sociaty.ApplyLv == 0 {
sociaty.ApplyLv = 1 //默认玩家入会等级
}
return this.AddList(comm.RDS_SOCIATY, sociaty.Id, sociaty)
}
// 公会列表
func (this *ModelSociaty) list(uid string, filter pb.SociatyListFilter) (list []*pb.DBSociaty) {
user, err := this.moduleSociaty.ModuleUser.GetRemoteUser(uid)
if err != nil {
return
}
if user == nil {
return
}
switch filter {
case pb.SociatyListFilter_ALL: //所有
if err := this.GetList(comm.RDS_SOCIATY, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return
}
case pb.SociatyListFilter_CONDI: //满足条件
//玩家等级大于等于公会的申请等级限制
if err := this.GetList(comm.RDS_SOCIATY, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return
}
var newList []*pb.DBSociaty
for _, v := range list {
if user.Lv >= v.ApplyLv {
newList = append(newList, v)
}
}
return newList
case pb.SociatyListFilter_NOAPPLY: //无需审批
filter := bson.M{
"isApplyCheck": false,
}
cur, err := this.DB.Find(comm.TableSociaty, filter)
for cur.Next(context.TODO()) {
sociaty := &pb.DBSociaty{}
if err = cur.Decode(sociaty); err == nil {
list = append(list, sociaty)
}
}
case pb.SociatyListFilter_APPLYING: //申请中
if err := this.GetList(comm.RDS_SOCIATY, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return
}
var newList []*pb.DBSociaty
for _, v := range list {
for _, apply := range v.ApplyRecord {
if apply.Uid == uid {
newList = append(newList, v)
}
}
}
return newList
}
return
}
// 搜索公会
func (this *ModelSociaty) findByName(name string) *pb.DBSociaty {
filter := bson.M{
"name": name,
}
sr := this.DB.FindOne(comm.TableSociaty, filter)
sociaty := &pb.DBSociaty{}
if err := sr.Decode(sociaty); err != nil {
if err != mongo.ErrNoDocuments {
return nil
}
}
return sociaty
}
// 获取公会
func (this *ModelSociaty) getSociaty(sociatyId string) (sociaty *pb.DBSociaty) {
sociaty = &pb.DBSociaty{}
if err := this.GetListObj(comm.RDS_SOCIATY, sociatyId, sociaty); err != nil {
this.moduleSociaty.Errorf("sociaty [%s] found err:%v", sociatyId, err)
return
}
return
}
// 获取玩家所在的公会
func (this *ModelSociaty) getUserSociaty(uid string) (sociaty *pb.DBSociaty) {
sociaty = &pb.DBSociaty{}
userEx, err := this.moduleSociaty.ModuleUser.GetRemoteUserExpand(uid)
if err != nil {
return
}
if userEx.SociatyId != "" {
return this.getSociaty(userEx.SociatyId)
}
return
}
// 申请公会
func (this *ModelSociaty) apply(uid string, sociaty *pb.DBSociaty) error {
// 判断公会审批设置
if sociaty.IsApplyCheck { //需要审核
sociaty.ApplyRecord = append(sociaty.ApplyRecord, &pb.ApplyRecord{
Uid: uid,
Ctime: time.Now().Unix(),
})
update := map[string]interface{}{
"applyRecord": sociaty.ApplyRecord,
}
return this.updateSociaty(sociaty.Id, update)
} else { //无需审核直接入会
if err := this.addMember(uid, sociaty); err != nil {
return err
}
//初始玩家公会任务
this.moduleSociaty.modelSociatyTask.initSociatyTask(uid, sociaty.Id)
}
return nil
}
// 设置公会
func (this *ModelSociaty) setting(sociaty *pb.DBSociaty) error {
update := map[string]interface{}{
"icon": sociaty.Icon,
"notice": sociaty.Notice,
"isApplyCheck": sociaty.IsApplyCheck,
"applyLv": sociaty.ApplyLv,
}
return this.updateSociaty(sociaty.Id, update)
}
// 申请撤销
func (this *ModelSociaty) applyCancel(uid, sociatyId string) error {
sociaty := this.getSociaty(sociatyId)
if sociaty.Id == "" {
return fmt.Errorf("sociatyId: %s 公会不存在", sociatyId)
}
return this.delFromApplyRecord(uid, sociaty)
}
// 是否已申请
func (this *ModelSociaty) isApplied(uid string, sociaty *pb.DBSociaty) bool {
for _, v := range sociaty.ApplyRecord {
if v.Uid == uid {
return true
}
}
return false
}
// 申请列表
func (this *ModelSociaty) applyList(sociaty *pb.DBSociaty) (list []*pb.SociatyMemberInfo) {
for _, r := range sociaty.ApplyRecord {
user, err := this.moduleSociaty.ModuleUser.GetRemoteUser(r.Uid)
if err != nil || user.Uid == "" {
continue
}
list = append(list, &pb.SociatyMemberInfo{
Uid: user.Uid,
Name: user.Name,
Avatar: user.Avatar,
Lv: user.Lv,
})
}
return
}
// 是否公会成员
func (this *ModelSociaty) isMember(uid string, sociaty *pb.DBSociaty) bool {
for _, m := range sociaty.Members {
if m.Uid == uid {
return true
}
}
return false
}
func (this *ModelSociaty) isInJobs(job pb.SociatyJob, jobs ...pb.SociatyJob) bool {
for _, j := range jobs {
if j == job {
return true
}
}
return false
}
// 是否有执行权限
func (this *ModelSociaty) isRight(uid string, sociaty *pb.DBSociaty, jobs ...pb.SociatyJob) bool {
for _, m := range sociaty.Members {
if m.Uid == uid {
return this.isInJobs(m.Job, jobs...)
}
}
return false
}
// 更新公会
func (this *ModelSociaty) updateSociaty(sociatyId string, update map[string]interface{}) error {
return this.ChangeList(comm.RDS_SOCIATY, sociatyId, update)
}
// 退出公会
func (this *ModelSociaty) quit(uid string, sociaty *pb.DBSociaty) error {
for i, m := range sociaty.Members {
if m.Uid == uid {
sociaty.Members = append(sociaty.Members[:i], sociaty.Members[i+1:]...)
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return this.updateSociaty(sociaty.Id, update)
}
// 解散公会
func (this *ModelSociaty) dismiss(sociaty *pb.DBSociaty) error {
err := this.DelListlds(comm.RDS_SOCIATY, sociaty.Id)
return err
}
//删除请求记录
func (this *ModelSociaty) delFromApplyRecord(uid string, sociaty *pb.DBSociaty) error {
for i, ar := range sociaty.ApplyRecord {
if ar.Uid == uid {
sociaty.ApplyRecord = append(sociaty.ApplyRecord[:i], sociaty.ApplyRecord[i+1:]...)
}
}
update := map[string]interface{}{
"applyRecord": sociaty.ApplyRecord,
}
return this.updateSociaty(sociaty.Id, update)
}
//添加成员
func (this *ModelSociaty) addMember(uid string, sociaty *pb.DBSociaty) error {
defer this.moduleSociaty.modelSociatyLog.addLog(Log_Add, sociaty.Id, uid)
sociaty.Members = append(sociaty.Members, &pb.SociatyMember{
Uid: uid,
Job: pb.SociatyJob_MEMBER,
Ctime: time.Now().Unix(),
})
update := map[string]interface{}{
"members": sociaty.Members,
}
if err := this.updateSociaty(sociaty.Id, update); err != nil {
return err
}
// 更新玩家公会
updateEx := map[string]interface{}{
"sociatyId": sociaty.Id,
}
return this.moduleSociaty.ModuleUser.ChangeRemoteUserExpand(uid, updateEx)
}
// 成员列表
func (this *ModelSociaty) members(sociaty *pb.DBSociaty) (list []*pb.SociatyMemberInfo) {
for _, m := range sociaty.Members {
user, err := this.moduleSociaty.ModuleUser.GetRemoteUser(m.Uid)
if err != nil || user.Uid == "" {
continue
}
list = append(list, &pb.SociatyMemberInfo{
Uid: user.Uid,
Name: user.Name,
Avatar: user.Avatar,
Lv: user.Lv,
Job: m.Job,
OfflineTime: user.Offlinetime,
})
}
return
}
// 同意
func (this *ModelSociaty) agree(uid string, sociaty *pb.DBSociaty) error {
if this.isMember(uid, sociaty) {
return fmt.Errorf("已是该公会成员 uid:%s sociatyId:%s", uid, sociaty.Id)
}
//删除申请记录
if err := this.delFromApplyRecord(uid, sociaty); err != nil {
return err
}
//添加成员
if err := this.addMember(uid, sociaty); err != nil {
return err
}
//初始玩家公会任务
return this.moduleSociaty.modelSociatyTask.initSociatyTask(uid, sociaty.Id)
}
//拒绝
func (this *ModelSociaty) refuse(uid string, sociaty *pb.DBSociaty) error {
if this.isMember(uid, sociaty) {
return fmt.Errorf("已是该公会成员 uid:%s sociatyId:%s", uid, sociaty.Id)
}
return this.delFromApplyRecord(uid, sociaty)
}
// 转让公会
// targetId 目标玩家ID
// srcId 玩家ID 会长
func (this *ModelSociaty) assign(srcId, targetId string, sociaty *pb.DBSociaty) error {
if !this.isMember(targetId, sociaty) {
return fmt.Errorf("不是该公会成员 uid:%s sociatyId:%s", targetId, sociaty.Id)
}
for _, m := range sociaty.Members {
if m.Uid == srcId {
m.Uid = targetId
} else if m.Uid == targetId {
m.Uid = srcId
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return this.updateSociaty(sociaty.Id, update)
}
// 踢出公会
// targetId 踢出目标
// 不允许踢出会长
func (this *ModelSociaty) discharge(targetId string, sociaty *pb.DBSociaty) error {
for i, m := range sociaty.Members {
if m.Uid == targetId {
if m.Job == pb.SociatyJob_PRESIDENT {
return fmt.Errorf("会长 %s 不可以被踢出", targetId)
}
sociaty.Members = append(sociaty.Members[:i], sociaty.Members[i+1:]...)
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return this.updateSociaty(sociaty.Id, update)
}
//获取职位数
func (this *ModelSociaty) getJobCount(job pb.SociatyJob, sociaty *pb.DBSociaty) (count int) {
for _, m := range sociaty.Members {
if m.Job == job {
count++
}
}
return
}
// 设置职位
func (this *ModelSociaty) settingJob(targetId string, job pb.SociatyJob, sociaty *pb.DBSociaty) error {
for _, m := range sociaty.Members {
if m.Uid == targetId {
m.Job = job
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return this.updateSociaty(sociaty.Id, update)
}
// 获取会长信息
func (this *ModelSociaty) getMasterInfo(sociaty *pb.DBSociaty) *pb.SociatyMemberInfo {
for _, m := range sociaty.Members {
if m.Job == pb.SociatyJob_PRESIDENT {
user, err := this.moduleSociaty.ModuleUser.GetRemoteUser(m.Uid)
if err != nil || user.Uid == "" {
continue
}
return &pb.SociatyMemberInfo{
Uid: user.Uid,
Name: user.Name,
Lv: user.Lv,
Avatar: user.Avatar,
OfflineTime: user.Offlinetime,
}
}
}
return nil
}
// 弹劾会长
func (this *ModelSociaty) accuse(sociaty *pb.DBSociaty) error {
master := this.getMasterInfo(sociaty)
if master == nil {
return errors.New("会长不存在")
}
user, err := this.moduleSociaty.ModuleUser.GetRemoteUser(master.Uid)
if err != nil {
return err
}
//会长离线时间
now := time.Now().Unix()
left := now - user.Offlinetime
if left < 7*3600 || user.Offlinetime == 0 {
return errors.New("会长很称职,无需弹劾")
}
return nil
}
// 签到
func (this *ModelSociaty) sign(uid string, sociaty *pb.DBSociaty) error {
if !this.isMember(uid, sociaty) {
return fmt.Errorf("不是该公会成员 uid:%s sociatyId:%s", uid, sociaty.Id)
}
sociaty.SignIds = append(sociaty.SignIds, uid)
update := map[string]interface{}{
"signIds": sociaty.SignIds,
}
return this.updateSociaty(sociaty.Id, update)
}
// 是否已签到
func (this *ModelSociaty) IsSign(uid string, sociaty *pb.DBSociaty) bool {
if _, ok := utils.Findx(sociaty.SignIds, uid); ok {
return ok
}
return false
}
// 获取玩家任务列表
func (this *ModelSociaty) getUserTaskList(uid, sociatyId string) (sociatyTask *pb.DBSociatyTask) {
sociatyTask = &pb.DBSociatyTask{}
this.moduleSociaty.modelSociatyTask.GetListObj(sociatyId, uid, sociatyTask)
return
}
// 更新公会资源 活跃度、经验
func (this *ModelSociaty) updateResourceFromTask(sociaty *pb.DBSociaty, conf *cfg.GameGuildTaskData) error {
if conf == nil {
return errors.New("配置未找到")
}
exp := sociaty.Exp //经验
activity := sociaty.Activity //活跃度
for _, v := range conf.SociatyReward {
if v.T == "guildactive" {
activity += v.N
} else if v.T == "guildexp" {
exp += v.N
}
}
update := map[string]interface{}{
"exp": exp,
"activity": activity,
}
return this.updateSociaty(sociaty.Id, update)
}
// 更新经验
func (this *ModelSociaty) updateSociatyExp(val int32, sociaty *pb.DBSociaty) error {
exp := sociaty.Exp //经验
exp += val
update := map[string]interface{}{
"exp": exp,
}
return this.updateSociaty(sociaty.Id, update)
}
// 更新成员贡献值
// 任务领取时更新
func (this *ModelSociaty) updateMemberContribution(uid string, val int32, sociaty *pb.DBSociaty) error {
for _, m := range sociaty.Members {
if m.Uid == uid {
m.Contribution += val
}
}
update := map[string]interface{}{
"members": sociaty.Members,
}
return this.updateSociaty(sociaty.Id, update)
}
func (this *ModelSociaty) sort(list []*pb.DBSociatyRank) []*pb.DBSociatyRank {
sort.SliceStable(list, func(i, j int) bool {
if list[i].Lv == list[j].Lv {
if list[i].Activity == list[j].Activity {
return list[i].Ctime > list[j].Ctime
} else {
return list[i].Activity < list[j].Activity
}
}
return list[i].Lv < list[j].Lv
})
return list
}
// 公会等级变化
// 更新排行榜
func (this *ModelSociaty) rankDataChanged(event interface{}, next func(event interface{})) {
var list []*pb.DBSociatyRank
if err := this.GetList(comm.RDS_SOCIATYRANK, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return
}
data := event.(*SociatyListen)
newRank := &pb.DBSociatyRank{
SociatyId: data.sociatyId,
Name: data.name,
Lv: data.lv,
Activity: data.activity,
Ctime: data.ctime,
}
if len(list) == 0 || len(list) > 0 && len(list) < 20 {
if data != nil {
this.AddList(comm.RDS_SOCIATYRANK, data.sociatyId, newRank)
}
} else {
this.AddList(comm.RDS_SOCIATYRANK, data.sociatyId, newRank)
if err := this.GetList(comm.RDS_SOCIATYRANK, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return
}
// 排名
tmp := this.sort(list)
//找出20条之后的数据
lastData := append(tmp[:19], tmp[len(tmp)-1:]...)
//删除20之后的数据
delIds := []string{}
for _, v := range lastData {
delIds = append(delIds, v.SociatyId)
}
this.DelListlds(comm.RDS_SOCIATYRANK, delIds...)
}
}
// 排行榜
func (this *ModelSociaty) rank() (rank []*pb.DBSociatyRank) {
var list []*pb.DBSociaty
if err := this.GetList(comm.RDS_SOCIATYRANK, &list); err != nil {
log.Errorf("sociaty list err:%v", err)
return nil
}
for _, v := range list {
rank = append(rank, &pb.DBSociatyRank{
Name: v.Name,
Lv: v.Lv,
Activity: v.Activity,
Ctime: v.Ctime,
})
}
rank = this.sort(rank)
rank = append(rank[:0], rank[19:]...)
return
}
func (this *ModelSociaty) isInCDHour(userCdTime int64) bool {
if userCdTime == 0 {
return false
}
return time.Now().Unix() < userCdTime
}