package game

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"math"
	"server/conf"
	activityCfg "server/conf/activity"
	cardCfg "server/conf/card"
	chargeCfg "server/conf/charge"
	guesscolorCfg "server/conf/guess_color"
	itemCfg "server/conf/item"
	limitedTimeEventCfg "server/conf/limited_time_event"
	mergeDataCfg "server/conf/merge_data"
	miningCfg "server/conf/mining"
	playroomCfg "server/conf/playroom"
	"server/db"
	"server/ga"
	"server/game/mod/activity"
	"server/game/mod/friend"
	"server/game/mod/item"
	limitedTimeEvent "server/game/mod/limited_time_event"
	MsgMod "server/game/mod/msg"
	"server/game/mod/order"
	"server/game/mod/playroom"
	"server/game/mod/quest"
	GoUtil "server/game_util"
	"server/msg"
	telog "server/thinkdata"
	"strconv"
	"sync"
	"time"

	"server/pkg/github.com/name5566/leaf/gate"
	"server/pkg/github.com/name5566/leaf/log"
	"server/pkg/github.com/name5566/leaf/timer"

	"github.com/robfig/cron/v3"

	"google.golang.org/protobuf/proto"
)

// import "reflect"

//"fmt"

type Player struct {
	PlayerBaseMod *PlayerBaseData
	PlayMod       PlayerMod
	M_DwUin       int64
	agent         gate.Agent
	lock          sync.Mutex
	stopSignal    chan bool
	Msg           []PlayerMsg
	Trigger       []*quest.Trigger
	MDispatr      *timer.Dispatcher
	McronSave     *cron.Cron
	McronSaveID   cron.EntryID
	msgChan       chan *MsgMod.Msg
	args          map[string]interface{}
	timerList     map[string]*timer.Timer
	activity      map[int]*ActivityInfo
	stop          bool
	wg            sync.WaitGroup
	func_time     int
}

type PlayerBackUp struct {
	Data    msg.ResPlayerBaseInfo
	PlayMod []byte
}

type PlayerMsg struct {
	F string
	B []byte
}

func (p *Player) Stop() {
	select {
	case <-p.stopSignal:
		// 通道已经关闭
		return
	default:
		p.wg.Wait()
		close(p.stopSignal)
		close(p.msgChan)
	}
	p.McronSave.Stop()
	p.stop = true
}

func (p *Player) CallEvent(Duration time.Duration, F func(), Label string) {
	if v, ok := p.timerList[Label]; ok {
		v.Stop()
	}
	t := p.MDispatr.AfterFunc(Duration, F)
	p.timerList[Label] = t
}

// 异步请求
func (p *Player) Send(m *MsgMod.Msg) error {
	if m == nil {
		return nil
	}
	p.wg.Add(1)
	p.msgChan <- m
	return nil
}

func (p *Player) Call(m MsgMod.Msg) {
	p.HandleMsg(m.Clone())
}

func (p *Player) SendClientRes() {
	for _, v := range p.Msg {
		G_GameLogicPtr.PackResInfo(p.GetAgent(), v.F, v.B)
	}
	p.Msg = make([]PlayerMsg, 0)
}

func (p *Player) PushClientRes(m proto.Message) {
	key := GetStructName(m)
	buff, _ := proto.Marshal(m)
	p.Msg = append(p.Msg, PlayerMsg{
		F: key,
		B: buff,
	})
}

func (p *Player) PushAndSendClienRes(m proto.Message) {
	key := GetStructName(m)
	buff, _ := proto.Marshal(m)
	G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff)
}

func (p *Player) SendErrClienRes(m proto.Message) {
	key := GetStructName(m)
	buff, _ := proto.Marshal(m)
	G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff)
}

func (p *Player) QuestTrigger(tr *quest.Trigger) {
	p.Trigger = append(p.Trigger, tr)
}

func (p *Player) QuestTriggerList(tr []*quest.Trigger) {
	p.Trigger = append(p.Trigger, tr...)
}

func (p *Player) ProcessTrigger() {
	IsDailyBack := false
	DailyTaskMod := p.PlayMod.getDailyTaskMod()
	MailMod := p.PlayMod.getMailMod()
	PlayroomMod := p.PlayMod.getPlayroomMod()
	GuideTaskMod := p.PlayMod.getGuideTaskMod()
	IsPlayroomBack := false
	IsMailBack := false
	IsGuideTask := false
	for _, tr := range p.Trigger {
		if DailyTaskMod.Trigger(tr) {
			IsDailyBack = true
		}
		if p.MailTrigger(tr) {
			IsMailBack = true
		}
		if PlayroomMod.QuestTrigger(tr) {
			IsPlayroomBack = true
		}
		if GuideTaskMod.Trigger(tr) {
			IsGuideTask = true
		}
	}

	if IsDailyBack {
		p.PushClientRes(DailyTaskMod.BackData())
	}
	if IsMailBack {
		p.PushClientRes(MailMod.BackData())
	}
	if IsPlayroomBack {
		p.NotifyPlayroomTask()
	}
	if IsGuideTask {
		p.PushClientRes(GuideTaskMod.BackData())
	}
	p.Trigger = make([]*quest.Trigger, 0)
}

// 接口请求之前备份数据
func (p *Player) BackUp() *PlayerBackUp {
	BackUp := PlayerBackUp{}
	p.PlayMod.BackUp(&BackUp)
	BackUp.Data = p.GetPlayerBaseMod().BackUp()
	return &BackUp
}

// 接口发生错误时 还原数据
func (p *Player) Recover(backUp *PlayerBackUp) {
	// p.GetPlayerBaseMod().Data = backUp.Data
	p.PlayMod.Recover(backUp)
	p.Msg = make([]PlayerMsg, 0)
}

func (p *Player) InitPlayer(UserName string) error {
	p.lock.Lock()
	defer p.lock.Unlock()
	p.msgChan = make(chan *MsgMod.Msg, 100)
	p.Msg = make([]PlayerMsg, 0)
	p.args = make(map[string]interface{})
	p.timerList = make(map[string]*timer.Timer)
	p.MDispatr = timer.NewDispatcher(100)
	p.stopSignal = make(chan bool)
	Base := &PlayerBaseData{p: p}

	// 玩家基础数据
	ok := Base.LoadDataFromDB(UserName)
	if !ok {
		log.Debug("load PlayerBaseData failed:%s", UserName)
		return errors.New("load PlayerBaseData failed")
	}
	p.PlayerBaseMod = Base
	p.M_DwUin = Base.Data.DwUin

	// 棋盘数据

	// 玩家模块数据
	modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)}
	ok = modData.LoadDataFromDB(Base.Data.DwUin)
	if !ok {
		log.Debug("load PlayerModData failed:%s", UserName)
		return errors.New("load PlayerModData failed")
	}
	IsUpdate, err := modData.InitMod(p)
	if err != nil {
		log.Debug("InitMod failed:", err)
		return err
	}
	p.PlayMod.mod_list = modData.ModList
	p.PlayMod.is_update = IsUpdate
	// 启动定时器
	p.DispatcherHandle()
	p.McronSave = cron.New()
	_, err = p.McronSave.AddFunc("@every 1m", p.AutoSaveData)
	if err != nil {
		log.Debug("AddFunc failed:", err)
	}
	p.McronSave.Start()
	p.initAcitivity()
	p.ZeroUpdate(nil)
	p.NoonUpdate(nil)
	p.Login()
	p.OrderShip()
	p.UpdateUserInfo()
	// fix bug
	ChargeMod := p.PlayMod.getChargeMod()
	ChessMod := p.PlayMod.getChessMod()
	ChargeMod.FixBug(ChessMod.GetEmitList())
	p.FixOrderBug()
	p.FixDecorate()
	return nil
}

func (p *Player) InitPlayerByUid(Uid int) error {
	p.lock.Lock()
	defer p.lock.Unlock()
	p.msgChan = make(chan *MsgMod.Msg, 100)
	p.Msg = make([]PlayerMsg, 0)
	p.args = make(map[string]interface{})
	p.timerList = make(map[string]*timer.Timer)
	p.MDispatr = timer.NewDispatcher(100)
	p.stopSignal = make(chan bool)
	Base := &PlayerBaseData{p: p}

	// 玩家基础数据
	ok := Base.LoadDataFromDBByUid(Uid)
	if !ok {
		log.Debug("load PlayerBaseData failed:%d", Uid)
		return errors.New("load PlayerBaseData failed")
	}
	p.PlayerBaseMod = Base
	p.M_DwUin = Base.Data.DwUin

	// 棋盘数据

	// 玩家模块数据
	modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)}
	ok = modData.LoadDataFromDB(Base.Data.DwUin)
	if !ok {
		log.Debug("load PlayerModData failed:%d", Uid)
		return errors.New("load PlayerModData failed")
	}
	IsUpdate, err := modData.InitMod(p)
	if err != nil {
		log.Debug("InitMod failed:", err)
		return err
	}
	p.PlayMod.mod_list = modData.ModList
	p.PlayMod.is_update = IsUpdate
	// 启动定时器
	p.DispatcherHandle()
	p.McronSave = cron.New()
	_, err = p.McronSave.AddFunc("@every 1m", p.AutoSaveData)
	if err != nil {
		log.Debug("AddFunc failed:", err)
	}
	p.McronSave.Start()
	p.initAcitivity()
	p.ZeroUpdate(nil)
	p.NoonUpdate(nil)
	p.Login()
	p.OrderShip()
	p.UpdateUserInfo()
	// fix bug
	ChargeMod := p.PlayMod.getChargeMod()
	ChessMod := p.PlayMod.getChessMod()
	ChargeMod.FixBug(ChessMod.GetEmitList())
	p.FixOrderBug()
	p.FixDecorate()
	return nil
}

func (p *Player) OrderShip() {
	OrderList, err := db.GetPlayerChargeDataList(int(p.M_DwUin))
	if err != nil {
		return
	}
	// 避免为每个订单创建 goroutine，改为批量处理或同步处理
	for _, OrderInfo := range OrderList {
		// 直接同步处理，避免创建过多 goroutine
		go p.TriggerShippingOrderOrigin(&msg.ReqShippingOrder{
			OrderSn: OrderInfo.OrderId,
		})
	}
}

// 零点更新
func (p *Player) ZeroUpdate(a []interface{}) {
	VarMod := p.PlayMod.getVarMod()
	zeroTimestamp := GoUtil.ZeroTimestamp()
	PlayerBaseMod := p.GetPlayerBaseMod()
	// 零点更新
	if VarMod.DailyResetTime < zeroTimestamp {
		VarMod.DailyResetTime = zeroTimestamp
		VarMod.DailyVar = make(map[int]interface{})
		//卡牌 赛季结束补发图鉴奖励
		HandbookItem := p.PlayMod.getCardMod().ZeroUpdate(G_GameLogicPtr.SeverInfo.OpenTime)
		p.HandleItem(HandbookItem, msg.ITEM_POP_LABEL_AllCollectRewardHB.String())
		p.PushClientRes(p.PlayMod.getCardMod().BackData())

		// 每日任务
		p.PlayMod.getDailyTaskMod().ZeroUpdate(p.GetPlayerBaseMod().GetLevel(), p.PlayMod.getDecorateMod().GetAreaId())
		p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData())

		// 能量商店
		p.PlayMod.getBaseMod().ZeroUpdate()
		p.PushClientRes(p.PlayMod.getBaseMod().BackData())

		// 七日签到
		p.PlayMod.getSevenLoginMod().ZeroUpdate(PlayerBaseMod.GetSevenLoginAdd(), PlayerBaseMod.GetLastLoginTime())
		p.PushClientRes(p.PlayMod.getSevenLoginMod().BackData())

		// 礼包充值
		ChessMod := p.PlayMod.getChessMod()
		ChargeMod := p.PlayMod.getChargeMod()
		ChargeMod.ZeroUpdate(ChessMod.GetEmitList())
		p.ChargeBackData()

		// 无尽礼包
		p.PlayMod.getEndlessMod().ZeroUpdate(p.PlayMod.getChargeMod().GetMaxCharge(), p.PlayMod.getBaseMod().GetLevel())
		p.PushClientRes(p.PlayMod.getEndlessMod().BackData())

		// 宠物宝箱
		p.PlayMod.getFriendTreasureMod().ZeroUpdate()
		// p.PushClientRes(p.PlayMod.getFriendTreasureMod().BackData())

		// 好友功能
		p.PlayMod.getFriendMod().ZeroUpdate()

		p.PlayMod.getLimitedTimeEventMod().ZeroUpdate(p.GetPlayerBaseMod().GetLevel())
		// playroom
		PlayroomMod := p.PlayMod.getPlayroomMod()
		PlayroomMod.ZeroUpdate()
		if ChargeMod.IsWeeklyDiscountDay() {
			PlayroomMod.ResetWeeklyDiscount()
		}
		p.PlayroomBackData()
		p.PlayMod.getChampshipMod().ZeroUpdate()
		p.initAcitivity()
		p.ActivityZeroUpdate()
		p.QuestTrigger(&quest.Trigger{Label: quest.TRIGGER_LABEL_LOGIN})
		p.PlayMod.save()
	}
	// 周更新
	weekZeroTimestamp := GoUtil.WeekZeroTimestamp()
	if VarMod.WeeklyResetTime < weekZeroTimestamp {
		VarMod.WeeklyResetTime = weekZeroTimestamp
		VarMod.WeeklyVar = make(map[int]interface{})
		p.PlayMod.getDailyTaskMod().WeekUpdate()
		p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData())

		p.PlayMod.getLimitedTimeEventMod().WeekUpdate()

		p.PlayMod.save()
	}
}

// 十二点更新
func (p *Player) NoonUpdate(a []interface{}) {
	VarMod := p.PlayMod.getVarMod()
	noonTimestamp := GoUtil.NoonTimestamp()
	// 零点更新
	if VarMod.NoonResetTime < noonTimestamp {
		VarMod.NoonResetTime = noonTimestamp
		ChessMod := p.PlayMod.getChessMod()
		// 礼包充值
		p.PlayMod.getChargeMod().NoonUpdate(ChessMod.GetEmitList())
		p.ChargeBackData()
		p.PlayMod.save()
	}

}

func (p *Player) Login() {
	// 添加定时器
	// 限时事件触发
	p.LimitedTimeEventTrigger(0)
	// 猪猪银行触发
	p.LimitedTimePiggyBankTrigger()
	BaseMod := p.PlayMod.getBaseMod()
	FaceMod := p.PlayMod.getFaceMod()
	ChargeMod := p.PlayMod.getChargeMod()
	AvatarMod := p.PlayMod.getAvatarMod()
	PlayBaseMod := p.GetPlayerBaseMod()
	GuideTaskMod := p.PlayMod.getGuideTaskMod()
	// playroom触发
	p.LimitedTimePlayroomTrigger()    // playroom数值变化
	LimitedTimePlayroomWorkTrigger(p) // playroom打工
	LimitedTimeEnergyAdd(p)           // 能量定时处理
	p.ActivityLogin()                 // 活动登录
	p.Compensation()
	SyncMailMsg(p) // 同步邮件
	Duration := BaseMod.Login()
	ChargeMod.Login(Duration)
	GuideTaskMod.Login()
	FaceMod.Login(PlayBaseMod.GetRegisterTime())
	AvatarMod.Login(PlayBaseMod.GetRegisterTime())
	HandbookItem := p.PlayMod.getCardMod().Login(G_GameLogicPtr.SeverInfo.OpenTime)
	p.HandleItem(HandbookItem, msg.ITEM_POP_LABEL_AllCollectRewardHB.String())
	// 每周优惠特殊处理
	WeeklyStartTime, WeeklyEndTime := chargeCfg.GetWeeklyDiscountStartEnd()
	now := GoUtil.Now()
	if now >= WeeklyStartTime && now <= WeeklyEndTime {
		ChargeMod.WeeklyEndTime = WeeklyEndTime
	}
	if WeeklyStartTime > now {
		p.CallEvent(time.Duration(WeeklyStartTime-now)*time.Second, func() {
			ChargeMod.WeeklyEndTime = WeeklyEndTime
			ChargeMod.ResetWeeklyDiscount()
			PlayroomMod := p.PlayMod.getPlayroomMod()
			PlayroomMod.ResetWeeklyDiscount()
			p.ChargeBackData()
			p.PlayroomBackData()
		}, "WeeklyDiscountStart")
	}
	if WeeklyEndTime > now {
		p.CallEvent(time.Duration(WeeklyEndTime-now)*time.Second, func() {
			ChargeMod.WeeklyEndTime = 0
			p.ChargeBackData()
			p.PlayroomBackData()
			LimitEventMod := p.PlayMod.getLimitedTimeEventMod()
			LimitEventMod.EndCatDaySale()
			p.PushClientRes(LimitEventMod.BackData())
		}, "WeeklyDiscountEnd")
	}
	if Duration > 604800 {
		FriendMod := p.PlayMod.getFriendMod()
		FriendMod.AddActLog(friend.ACT_LOG_TYPE_LOST_USER_RETURN, "")
		p.UpdateUserInfo()
	}

}

func (p *Player) Outline() {
	PlayroomMod := p.PlayMod.getPlayroomMod()
	PlayroomMod.Outline()

	PlayerBaseMod := p.GetPlayerBaseMod()
	Now := GoUtil.Now()
	Cacumulative := Now - PlayerBaseMod.GetLoginTime()
	BaseMod := p.PlayMod.getBaseMod()
	BaseMod.Outline(int(Cacumulative))
	p.PlayMod.save()
	type orderLogout struct {
		Id    int
		Order order.Order
	}
	orderList := []orderLogout{}
	for id, order := range p.PlayMod.getOrderMod().GetOrderList() {
		orderList = append(orderList, orderLogout{
			Id:    id,
			Order: order,
		})
	}
	p.TeLog("logout", map[string]interface{}{
		"caccumulative": Cacumulative,
		"order_list":    orderList,
		"after_level":   p.PlayMod.getBaseMod().GetLevel(),
		"tmp_diamond":   p.PlayMod.getBaseMod().GetDiamond(),
		"tmp_energy":    p.PlayMod.getBaseMod().GetEnergy(),
	})
	p.UpdateUserInfo()
}

// 离线 保存数据
func (p *Player) ClearData() {
	log.Release("uid: %d, outline save data", p.M_DwUin)
	p.Outline()
	ctx := context.Background()
	txOptions := &sql.TxOptions{}
	tx, err := db.SqlDb.BeginTx(ctx, txOptions)
	if err != nil {
		log.Debug("ClearData BeginTx failed:", err)
		return
	}
	Uid := int(p.M_DwUin)
	p.PlayerBaseMod.ClearData()
	p.PlayMod.ClearData(p)
	tx.Commit()
	p.Stop()
	G_GameLogicPtr.DelPlayer(p)
	SendMsgToCenterAsync(&MsgMod.Msg{
		From:       Uid,
		HandleType: MsgMod.HANDLE_MDO_PLAYER_LOGOUT,
	})
}

func (p *Player) AutoSaveData() {
	p.lock.Lock()
	defer p.lock.Unlock()
	//保存数据
	ctx := context.Background()
	txOptions := &sql.TxOptions{}
	tx, err := db.SqlDb.BeginTx(ctx, txOptions)
	if err != nil {
		log.Debug("AutoSaveData BeginTx failed:", err)
		return
	}

	p.PlayerBaseMod.SaveDataFromDB("")
	p.PlayMod.ClearData(p)
	err = tx.Commit()
	if err != nil {
		log.Debug("AutoSaveData Commit failed:", err)
	}

}

// 重新连接
func (p *Player) Reconnect() {

}

// 获取conn连接
func (p *Player) GetAgent() gate.Agent {
	return p.agent
}

// 设置conn连接
func (p *Player) SetAgent(a gate.Agent) {
	p.agent = a
}

func (p *Player) GetPlayerBaseMod() *PlayerBaseData {
	return p.PlayerBaseMod
}

func (p *Player) GetAgentByPlayer() gate.Agent {
	return p.agent
}

// 处理物品
func (p *Player) HandleLoseItem(itemList []*item.Item, Label string) error {
	for _, v := range itemList {
		if v.Num > 0 {
			v.Num = -v.Num
		}
	}
	return p.HandleItem(itemList, Label)
}
func (p *Player) HandleItem(itemList []*item.Item, Label string) error {
	if len(itemList) == 0 {
		return nil
	}
	is_update := false
	ResCard := make([]*msg.CardPack, 0)
	ResItem := make([]*msg.ItemInfo, 0)
	ItemMod := p.PlayMod.getItemMod()
	AvatarMod := p.PlayMod.getAvatarMod()
	EmojiMod := p.PlayMod.getEmojiMod()
	FaceMod := p.PlayMod.getFaceMod()
	BackDataType := map[int]struct{}{}
	for _, v := range itemList {
		if v.Num == 0 {
			continue
		}
		if v.Num > 0 && Label != "" {
			ResItem = append(ResItem, &msg.ItemInfo{Id: int32(v.Id), Num: int32(v.Num)})
		}
		var change_type string
		if v.Num < 0 {
			change_type = "consume"
		} else {
			change_type = "gain"
		}
		IType := itemCfg.GetItemType(v.Id)
		if IType == 0 {
			return errors.New("item type error, item id :" + strconv.Itoa(v.Id))
		}
		switch IType {
		case item.ITEM_TYPE_ENERGY: // 能量
			err := p.GetPlayerBaseMod().AddEnergy(p, v.Num)
			p.TeLog("asset_change", map[string]interface{}{
				"item_id":       v.Id,
				"change_type":   change_type,
				"change_num":    math.Abs(float64(v.Num)),
				"change_after":  p.GetPlayerBaseMod().GetEnergy(),
				"change_reason": Label,
			})
			is_update = true
			if err != nil {
				return err
			}
		case item.ITEM_TYPE_STAR: // 星星
			err := p.GetPlayerBaseMod().AddStar(p, v.Num)
			is_update = true
			if err != nil {
				return err
			}
			p.TeLog("asset_change", map[string]interface{}{
				"item_id":       v.Id,
				"change_type":   change_type,
				"change_num":    math.Abs(float64(v.Num)),
				"change_after":  p.GetPlayerBaseMod().GetStar(),
				"change_reason": Label,
			})
		case item.ITEM_TYPE_DIAMOND: // 钻石
			err := p.GetPlayerBaseMod().AddDiamond(v.Num)
			is_update = true
			if err != nil {
				return err
			}
			if v.Num < 0 {
				p.QuestTrigger(&quest.Trigger{Label: quest.TRIGGER_LABEL_DIAMOND, A: []interface{}{-v.Num}})
			}
			p.TeLog("asset_change", map[string]interface{}{
				"item_id":       v.Id,
				"change_type":   change_type,
				"change_num":    math.Abs(float64(v.Num)),
				"change_after":  p.GetPlayerBaseMod().GetDiamond(),
				"change_reason": Label,
			})
		case item.ITEM_TYPE_CARD: // 卡牌
			Effect := itemCfg.GetItemEffect(v.Id)
			p.AddCard(Effect)
		case item.ITEM_TYPE_CARD_PACK: // 卡包
			CardMod := p.PlayMod.getCardMod()
			Effect := itemCfg.GetItemEffect(v.Id)
			for i := 0; i < v.Num; i++ {
				NewCard, err := CardMod.OpenCardPack(Effect)
				if err != nil {
					return err
				}
				ResCard = append(ResCard, &msg.CardPack{Id: int32(v.Id), Card: GoUtil.SliceIntToInt32(NewCard)})

				IsGold := false
				IsRepeat := false
				Sticker := 0
				for _, v := range NewCard {
					Gold := cardCfg.CheckCardIsGold(v)
					if Gold {
						IsGold = true
					}
					if CardMod.GetCardNum(v) > 1 {
						IsRepeat = true
						Sticker++
					} else {
						p.TeLog("get_new_card", map[string]interface{}{
							"season_id":        CardMod.EndTime,
							"card_id":          v,
							"card_typenumbers": len(CardMod.CardList),
						})
					}
				}
				p.TeLog("card_pack_open", map[string]interface{}{
					"season_id":        CardMod.EndTime,
					"card_pack_type":   v.Id,
					"card_number":      len(NewCard),
					"card_list":        NewCard,
					"income_from":      Label,
					"is_goldcard":      IsGold,
					"is_repeat":        IsRepeat,
					"is_card_festival": CardMod.GetCardFestival(),
					"sticker_number":   Sticker,
				})
			}
		case item.ITEM_TYPE_MASTER_CARD: // 万能卡
			CardMod := p.PlayMod.getCardMod()
			Effect := itemCfg.GetItemEffect(v.Id)
			for i := 0; i < v.Num; i++ {
				CardMod.AddMasterCard(Effect)
			}

		case item.ITEM_TYPE_CHESS: // 棋子
			ChessMod := p.PlayMod.getChessMod()
			if v.Num < 0 {
				err := ChessMod.LosePart(v.Id, -v.Num)
				if err != nil {
					return err
				}
				p.TeLog("chess_part_consume", map[string]interface{}{
					"chess_id":     v.Id,
					"chess_name":   mergeDataCfg.GetNameById(v.Id),
					"consume_num":  -v.Num,
					"remain_num":   ChessMod.PartBag.List[v.Id].Num,
					"consume_from": Label,
				})
				continue
			}
			for i := 0; i < v.Num; i++ {
				ChessMod.AddChessBuff(v.Id)
			}
			Type := mergeDataCfg.GetTypeById(v.Id)
			if Type == "Chest" || Type == "Gift" {
				p.TeLog("get_chest", map[string]interface{}{
					"chest_id":   v.Id,
					"chest_name": mergeDataCfg.GetNameById(v.Id),
					"get_source": Label,
				})
			}

			p.PushClientRes(ChessMod.BackData())
		case item.ITEM_TYPE_LIMITED_TIME_EVENT: // 限时事件
			EffectList := itemCfg.GetItemEffectList(v.Id)
			LimitedTimeEventMod := p.PlayMod.getLimitedTimeEventMod()
			if len(EffectList) < 2 {
				log.Debug("Effect List error;item id :%d", v.Id)
				continue
			}
			EndTime := LimitedTimeEventMod.AddEvent(EffectList[0], EffectList[1])
			p.PushClientRes(&msg.LimitEventNotify{
				Id:      int32(EffectList[0]),
				Type:    limitedTimeEvent.EVENT_NOTIFY_TYPE_ADD,
				EndTime: int32(EndTime),
				Cd:      int32(EffectList[1]),
			})
			// 触发订单事件 生成超级订单 卡牌节
			p.LimitedTimeEventTrigger(EffectList[0])
			p.TeLog("time_limited_event_enable", map[string]interface{}{
				"event_type":  limitedTimeEventCfg.GetEventName(EffectList[0]),
				"enable_type": Label,
			})
		case item.ITEM_TYPE_PIGGY_BANK: // 猪猪银行
			PiggyBankMod := p.PlayMod.getPiggyBankMod()
			Effect := itemCfg.GetItemEffect(v.Id)
			PiggyBankMod.AddPiggyBank(Effect)
			p.LimitedTimePiggyBankTrigger()
			p.PushClientRes(PiggyBankMod.BackData())
			p.TeLog("piggy_bank_income", map[string]interface{}{
				"piggy_bank_type": Effect,
				"income_from":     Label,
			})
		case item.ITEM_TYPE_AVATAR: // 头像框
			Effect := itemCfg.GetItemEffectList(v.Id)
			AvatarMod.Unlock(Effect[0], Effect[1])
			p.TeLog("avatarIcon_income", map[string]interface{}{
				"avatar_id":   Effect[0],
				"income_from": Label,
			})
			FriendMod := p.PlayMod.getFriendMod()
			FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_AVATAR_FRAME, "")
			p.UpdateUserInfo()
			p.PlayerDecoLog("avatar", Effect[0], Label)
			BackDataType[item.ITEM_TYPE_AVATAR] = struct{}{}
		case item.ITEM_TYPE_EMOJI: // 表情
			Effect := itemCfg.GetItemEffectList(v.Id)
			EmojiMod.Unlock(Effect[0], Effect[1])
			p.TeLog("emoji_income", map[string]interface{}{
				"emoji_id":    Effect[0],
				"income_from": Label,
			})
			FriendMod := p.PlayMod.getFriendMod()
			FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_EMOTION, "")
			p.UpdateUserInfo()
			p.PlayerDecoLog("emoji", Effect[0], Label)
			BackDataType[item.ITEM_TYPE_EMOJI] = struct{}{}
		case item.ITEM_TYPE_FACE: // 头像
			Effect := itemCfg.GetItemEffectList(v.Id)
			FaceMod.Unlock(Effect[0], Effect[1])
			p.TeLog("face_income", map[string]interface{}{
				"face_id":     Effect[0],
				"income_from": Label,
			})
			FriendMod := p.PlayMod.getFriendMod()
			FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_AVATAR, "")
			p.UpdateUserInfo()
			p.PlayerDecoLog("face", Effect[0], Label)
			BackDataType[item.ITEM_TYPE_FACE] = struct{}{}
		case item.ITEM_TYPE_ACTIVITY_RACE: // 活动竞速
			ActivityInfo := p.GetActivityInfo(activity.ACT_TYPE_RACE)
			if ActivityInfo == nil {
				continue
			}
			RaceMod := p.PlayMod.getRaceMod()
			RaceMod.AddCoin(v.Num)
			p.RaceBackData()
		case item.ITEM_TYPE_PLAYROOM_VISIT: // 拜访玩家
			Target := p.GetVisitorPlayer()
			playroomMod := p.PlayMod.getPlayroomMod()
			playroomMod.Target = Target
			playroomMod.Status = playroom.STATUS_VISIT
			// PlayroomVisit(p, Target)
			p.PlayroomBackData()
		case item.ITEM_TYPE_PLAYROOM_DECORATION: // playroom装饰
			Effect := itemCfg.GetItemEffect(v.Id)
			PlayroomMod := p.PlayMod.getPlayroomMod()
			PlayroomMod.AddCollect(Effect, Label)
			BackDataType[item.ITEM_TYPE_PLAYROOM_DECORATION] = struct{}{}
			Type, Name := playroomCfg.GetDecoInfo(Effect)
			FriendMod := p.PlayMod.getFriendMod()
			FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_DECORATION, "")
			p.UpdateUserInfo()
			p.TeLog("room_deco_get", map[string]interface{}{
				"room_deco_type":     Type,
				"room_deco_name":     Name,
				"room_deco_get_type": Label,
			})
		case item.ITEM_TYPE_PLAYROOM_DRESS: // playroom服饰
			Effect := itemCfg.GetItemEffect(v.Id)
			PlayroomMod := p.PlayMod.getPlayroomMod()
			PlayroomMod.AddDress(Effect, Label)
			BackDataType[item.ITEM_TYPE_PLAYROOM_DRESS] = struct{}{}
			Type := playroomCfg.GetDressPart(Effect)
			Name := playroomCfg.GetDressName(Effect)
			FriendMod := p.PlayMod.getFriendMod()
			FriendMod.AddActLog(friend.ACT_LOG_TYPE_GET_NEW_COSTUME, "")
			p.UpdateUserInfo()
			p.TeLog("pet_deco_get", map[string]interface{}{
				"pet_deco_type":     Type,
				"pet_deco_name":     Name,
				"pet_deco_get_type": Label,
			})
		case item.ITEM_TYPE_PLAYROOM_DECORATION_SET: // playroom装饰套装
			Effect := itemCfg.GetItemEffectList(v.Id)
			PlayroomMod := p.PlayMod.getPlayroomMod()
			for _, v := range Effect {
				if v == 0 {
					continue
				}
				PlayroomMod.AddCollect(v, Label)
				Type, Name := playroomCfg.GetDecoInfo(v)
				p.TeLog("room_deco_get", map[string]interface{}{
					"room_deco_type":     Type,
					"room_deco_name":     Name,
					"room_deco_get_type": Label,
				})
			}
			BackDataType[item.ITEM_TYPE_PLAYROOM_DECORATION_SET] = struct{}{}
		case item.ITEM_TYPE_PLAYROOM_DRESS_SET: // playroom服饰套装
			Effect := itemCfg.GetItemEffectList(v.Id)
			PlayroomMod := p.PlayMod.getPlayroomMod()
			for _, v := range Effect {
				if v == 0 {
					continue
				}
				PlayroomMod.AddDress(v, Label)
				Name := playroomCfg.GetDressName(v)
				Type := playroomCfg.GetDressPart(v)
				p.TeLog("pet_deco_get", map[string]interface{}{
					"pet_deco_type":     Type,
					"pet_deco_name":     Name,
					"pet_deco_get_type": Label,
				})
			}
			BackDataType[item.ITEM_TYPE_PLAYROOM_DRESS_SET] = struct{}{}
		case item.ITEM_TYPE_ACT_PASS: // 活动通行证
			ActivityInfo := p.GetActivityInfo(activity.ACT_TYPE_PASS)
			if ActivityInfo == nil {
				continue
			}
			PassMod := p.PlayMod.getPassMod()
			PassMod.AddExp(v.Num)
			p.ActPassBackData()
		default:
			err := ItemMod.AddItem(v.Id, v.Num)
			p.TeLog("asset_change", map[string]interface{}{
				"item_id":       v.Id,
				"change_type":   change_type,
				"change_num":    math.Abs(float64(v.Num)),
				"change_after":  ItemMod.GetItem(v.Id),
				"change_reason": Label,
			})
			if err != nil {
				return err
			}
		}
	}
	ResItemPopId := 0
	if v, ok := p.args["ResItemPopId"]; ok {
		ResItemPopId = GoUtil.Int(v)
	}
	if len(ResItem) != 0 || len(ResCard) != 0 {
		p.PushClientRes(&msg.ResItemPop{
			Id:        int32(ResItemPopId),
			Items:     ResItem,
			CardPacks: ResCard,
			Lable:     Label,
		})
	}
	for k := range BackDataType {
		switch k {
		case item.ITEM_TYPE_AVATAR:
			p.BackUserInfo()
		case item.ITEM_TYPE_EMOJI:
			p.BackUserInfo()
		case item.ITEM_TYPE_FACE:
			p.BackUserInfo()
		case item.ITEM_TYPE_PLAYROOM_DECORATION,
			item.ITEM_TYPE_PLAYROOM_DRESS,
			item.ITEM_TYPE_PLAYROOM_DECORATION_SET,
			item.ITEM_TYPE_PLAYROOM_DRESS_SET:
			p.PlayroomBackData()
		}
	}
	p.PetItemUseLog(itemList)
	CardMod := p.PlayMod.getCardMod()
	p.PushClientRes(CardMod.NotifyCard())
	p.PushClientRes(ItemMod.NotifyItem())
	p.PlayMod.save()
	if is_update {
		p.PushClientRes(p.GetPlayerBaseMod().BackAsset())
	}
	return nil
}

// 登录返回数据
func (p *Player) LoginBackData() {
	SendMsgToCenterSync(&MsgMod.Msg{
		From:       int(p.M_DwUin),
		HandleType: MsgMod.HANDLE_MOD_PLAYER_LOGIN,
		Extra:      conf.Server.ServerID,
	})
	SetFriendApplyNotification(int(p.M_DwUin), 0)
	p.PushClientRes(p.PlayMod.mod_list.Base.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Handbook.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Base.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Chess.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Order.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Card.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Decorate.BackData())
	p.PushClientRes(p.PlayMod.mod_list.DailyTask.BackData())
	p.PushClientRes(p.PlayMod.mod_list.SevenLogin.BackData())
	p.PushClientRes(p.PlayMod.mod_list.LimitedTimeEvent.ProgressBackData())
	p.PushClientRes(p.PlayMod.mod_list.Charge.PetWorkBackData())
	p.PushClientRes(p.PlayMod.mod_list.Endless.BackData())
	p.PushClientRes(p.PlayMod.mod_list.PiggyBank.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Item.BackData())
	p.PushClientRes(p.GetPlayerBaseMod().BackAsset())
	p.PushClientRes(p.PlayMod.mod_list.Kv.BackData())
	p.PushClientRes(p.PlayMod.mod_list.GuideTask.BackData())
	p.PushClientRes(p.PlayMod.mod_list.Friend.BubbleBackData())
	p.PushClientRes(p.PlayMod.mod_list.Guide.BackData())
	p.BackDataActivity()
	p.ChargeBackData()
	p.BackChampship()
	p.BackUserInfo()
}

func (p *Player) InitPlayerOnly() {
	p.lock.Lock()
	defer p.lock.Unlock()
	p.Msg = make([]PlayerMsg, 0)
	p.args = make(map[string]interface{})
	p.timerList = make(map[string]*timer.Timer)
	p.MDispatr = timer.NewDispatcher(10)
	p.stopSignal = make(chan bool)

	Base := &PlayerBaseData{p: p}

	// 玩家基础数据
	ok := Base.GetDataByUid(p.M_DwUin)
	if !ok {
		return
	}
	p.PlayerBaseMod = Base
	p.M_DwUin = Base.Data.DwUin

	// 玩家模块数据
	modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)}
	ok = modData.LoadDataFromDB(Base.Data.DwUin)
	if !ok {
		return
	}
	modData.InitMod(p)
	p.PlayMod.mod_list = modData.ModList
}

// 获取玩家简单数据
func (p *Player) GetSimpleData(Uid int, simple *PlayerSimpleData) error {
	p.M_DwUin = int64(Uid)
	p.InitPlayerOnly()
	Base := p.GetPlayerBaseMod()
	if Base == nil {
		return errors.New("GetSimpleData failed")
	}
	simple.Name = p.PlayMod.getBaseMod().NickName
	simple.Avatar = p.PlayMod.getAvatarMod().SetId
	simple.Face = p.PlayMod.getFaceMod().SetId
	simple.Level = p.GetPlayerBaseMod().GetLevel()
	simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum
	simple.Login = int64(Base.Data.LoginTime)
	simple.Star = p.GetPlayerBaseMod().GetStar()
	simple.Loginout = int64(Base.Data.LogoutTime)
	simple.FaceBook = Base.Data.FaceBookId
	simple.FaceBookPic = p.PlayMod.getBaseMod().FacebookUrl
	simple.Playroom = p.PlayMod.getPlayroomMod().Room
	simple.Chess = p.PlayMod.getChessMod().GetUnlockChessList()
	simple.WorkStart = p.PlayMod.getPlayroomMod().Starttime
	simple.Chip = p.PlayMod.getPlayroomMod().GetChip()
	simple.PetName = p.PlayMod.getBaseMod().PetName
	simple.Emoji = p.PlayMod.getEmojiMod().Set
	return nil
}

func (p *Player) UpdateUserInfo() {
	simple := &PlayerSimpleData{}
	Base := p.GetPlayerBaseMod()
	CardMod := p.PlayMod.getCardMod()
	BaseMod := p.PlayMod.getBaseMod()
	simple.Name = p.PlayMod.getBaseMod().NickName
	simple.Avatar = p.PlayMod.getAvatarMod().SetId
	simple.Uid = int(p.M_DwUin)
	simple.Star = p.GetPlayerBaseMod().GetStar()
	simple.Face = p.PlayMod.getFaceMod().SetId
	simple.Level = p.GetPlayerBaseMod().GetLevel()
	simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum
	simple.Login = int64(BaseMod.LoginTime)
	simple.Loginout = int64(BaseMod.LogoutTime)
	simple.FaceBook = Base.Data.FaceBookId
	simple.FaceBookPic = p.PlayMod.getBaseMod().FacebookUrl
	simple.Playroom = p.PlayMod.getPlayroomMod().Room
	simple.Chess = p.PlayMod.getChessMod().GetUnlockChessList()
	simple.WorkStart = p.PlayMod.getPlayroomMod().Starttime
	simple.Chip = p.PlayMod.getPlayroomMod().GetChip()
	simple.PetName = p.PlayMod.getBaseMod().PetName
	simple.Emoji = p.PlayMod.getEmojiMod().Set
	simple.Friend = p.PlayMod.getFriendMod().GetSimpleFriendList()
	simple.Upvote = p.PlayMod.getPlayroomMod().Upvote
	simple.DressSet = p.PlayMod.getPlayroomMod().DressSet
	simple.CardInfo = CardMod.GetCardList()
	simple.ActLog = p.PlayMod.getFriendMod().GetActLogLast()
	simple.Physiology = p.PlayMod.getPlayroomMod().GetPhysiologyList()
	simple.Lang = int(p.PlayMod.getBaseMod().Lang)
	simple.Account = p.PlayMod.getBaseMod().Account
	//TODO 存储到redis 在新版本中将优化成gob进行压缩
	value, _ := json.Marshal(simple)
	IdStr := GoUtil.String(p.M_DwUin)
	go db.RedisSetKeyBytes(IdStr, value, 0)
}

func (p *Player) HandleInUserRank() {
	DecorateMod := p.PlayMod.getDecorateMod()
	Score := float64(DecorateMod.GetDecorateNum())
	BaseMod := p.PlayMod.getBaseMod()
	Score += float64(BaseMod.GetLevel()) * 1000000 // 等级加成
	// 更新排行榜
	m := &MsgMod.Msg{
		Type:  MsgMod.HANDLE_TYPE_RANK,
		SendT: GoUtil.Now(),
		Extra: RankMsg{
			Uid:      int(p.M_DwUin),
			Score:    float64(Score),
			RankType: RANK_TYPE_USER,
		},
	}
	G_GameLogicPtr.RankMgrSend(m)
}

func (p *Player) HandleInChampshipRank() {
	ChampshipMod := p.PlayMod.getChampshipMod()
	Score := float64(ChampshipMod.GetScore())
	if Score <= 0 {
		return
	}
	// 更新排行榜
	m := &MsgMod.Msg{
		Type:  MsgMod.HANDLE_TYPE_CHAMPSHIP_INRANK,
		SendT: GoUtil.Now(),
		Extra: CRank{
			Uid:   int(p.M_DwUin),
			Score: Score,
			H:     ChampshipMod.GetH(),
			N:     ChampshipMod.GetN(),
		},
		End:        GoUtil.ZeroTimestamp() + 86400, // 第二天零点删除
		HandleType: MsgMod.HANDLE_MDO_CHAMPSHIP_INRANK,
	}
	SendMsgToCenterAsync(m)
}

func (p *Player) AddLog(Uid int, Type int, Param string, Time int64) {
	FriendMod := p.PlayMod.getFriendMod()
	Id := FriendMod.AddLog(Uid, Type, Param)
	p.PlayMod.save()
	p.PushClientRes(&msg.NotifyFriendLog{
		Info: &msg.ResFriendLog{
			Player: G_GameLogicPtr.GetResSimplePlayerByUid(Uid),
			Type:   int32(Type),
			Param:  Param,
			Id:     int32(Id),
			Time:   int32(Time),
		},
		Bubble: FriendMod.GetBubble(Id),
	})
}

func (p *Player) TeLog(Type string, Param map[string]interface{}) {
	agent := p.GetAgent()
	if Param == nil {
		Param = make(map[string]interface{})
	}
	if agent != nil && Param != nil {
		Param["Ip"] = agent.RemoteAddr().String()
	}
	//Param["#zone_offset"] = -5
	// 游戏内TE日志
	BaseMod := p.PlayMod.getBaseMod()
	UidStr := GoUtil.String(p.M_DwUin)
	go telog.Te.Track(BaseMod.Account, UidStr, Type, Param)
	//途游GA
	go ga.GAlogEvent(Type, BaseMod.Account, "", Param)
}

// 初始化活动
func (p *Player) initAcitivity() {
	p.activity = make(map[int]*ActivityInfo)
	ActivityList := activityCfg.GetActivityList()
	Level := p.GetPlayerBaseMod().GetLevel()
	ActivityMod := p.PlayMod.getActivityMod()
	for _, v := range ActivityList {
		if v.Level > Level {
			continue
		}
		Status := ActivityMod.GetActivityStatus(v)
		if Status == 0 {
			continue
		}
		p.activity[v.Id] = &ActivityInfo{
			StartT: v.StartTime,
			EndT:   v.EndTime,
			Id:     v.Id,
			Type:   v.Type,
			Status: Status,
			Title:  v.Title,
		}
	}
}

func (p *Player) BackDataActivity() {
	ResActivityList := make([]*msg.ActivityInfo, 0)
	for _, v := range p.activity {
		Red := p.GetRed(v)
		ResActivityList = append(ResActivityList, &msg.ActivityInfo{
			Id:        int32(v.Id),
			Type:      int32(v.Type),
			StartTime: int32(v.StartT),
			EndTime:   int32(v.EndT),
			Status:    int32(v.Status),
			Title:     v.Title,
			Red:       int32(Red),
		})
	}

	p.PushClientRes(&msg.ResActivity{
		ActiveList: ResActivityList,
	})
}

func (p *Player) GetRed(AI *ActivityInfo) int {
	Status := p.GetActivityStatus(AI.Type)
	if Status != ACT_STATUS_START {
		return 0
	}
	// 限时活动红点
	if AI.Type == activity.ACT_TYPE_MINING {
		ItemId := miningCfg.GetActivityItemId(AI.Id)
		return p.PlayMod.getItemMod().GetItem(ItemId)
	}
	if AI.Type == activity.ACT_TYPE_GUESS_COLOR {
		ItemId := guesscolorCfg.GetActivityItemId(AI.Id)
		return p.PlayMod.getItemMod().GetItem(ItemId)
	}
	return 0
}

func (p *Player) NotifyRed(actType int) {
	ActivityInfo := p.GetActivityInfo(actType)
	Status := p.GetActivityStatus(actType)
	if Status != ACT_STATUS_START {
		return
	}
	if ActivityInfo == nil {
		return
	}
	Red := p.GetRed(ActivityInfo)
	p.PushClientRes(&msg.NotifyActRed{
		Id:  int32(ActivityInfo.Id),
		Red: int32(Red),
	})
}

func (p *Player) AddCard(Id int) {
	CardMod := p.PlayMod.getCardMod()
	CardMod.AddCard(Id)
	p.TeLog("asset_change", map[string]interface{}{
		"item_id":       Id,
		"change_type":   "gain",
		"change_num":    1,
		"change_after":  CardMod.CardList[Id],
		"change_reason": "exchange_card",
	})
}

func (p *Player) SubCard(Id int) error {
	CardMod := p.PlayMod.getCardMod()
	err := CardMod.SubCard(Id)
	if err != nil {
		return err
	}
	p.TeLog("asset_change", map[string]interface{}{
		"item_id":       Id,
		"change_type":   "gain",
		"change_num":    1,
		"change_after":  CardMod.CardList[Id],
		"change_reason": "exchange_card",
	})
	return nil
}

func (p *Player) GetIp() string {
	if p.GetAgent() == nil {
		return ""
	}
	return p.GetAgent().RemoteAddr().String()
}

// TODO func_exec_add 需要优化成令牌桶算法，目前的实现可能存在性能问题
func (p *Player) func_exec_add() error {
	now := time.Now().Unix()

	// 如果是新的一秒，重置计数
	if now != int64(p.func_time) {
		p.func_time = int(now)
		p.args["func_exec_count"] = 1
		return nil
	}

	// 获取当前秒内的调用次数
	count := 0
	if v, ok := p.args["func_exec_count"]; ok {
		count = GoUtil.Int(v)
	}

	// 检查是否超过限制
	if count >= 20 {
		return errors.New("func_exec_add: call limit exceeded (20 times per second)")
	}

	// 增加计数
	p.args["func_exec_count"] = count + 1
	return nil
}

func (p *Player) DispatcherHandle() {
	go func() {
		var cb *timer.Timer
		for {
			select {
			case <-p.stopSignal:
				return
			case cb = <-p.MDispatr.ChanTimer:
				if cb != nil {
					cb.Cb()
				} else {
					log.Debug("Timer callback or Timer is nil")
				}
			case msg := <-p.msgChan:
				if msg != nil {
					p.wg.Done()
					now := time.Now()
					// 直接在当前 goroutine 中处理，避免创建过多 goroutine
					p.HandleMsg(msg.Clone())
					log.Debug("player %d recive msg %v;handle time %v", p.M_DwUin, msg, time.Since(now))
				}
			}
		}
	}()
}

func CheckPlayerLose(Uid int) bool {
	FriendSimpleData := G_GameLogicPtr.GetSimplePlayerByUid(Uid)
	if FriendSimpleData == nil {
		return true
	}
	now := GoUtil.Now()
	if now-FriendSimpleData.Loginout > sevendays {
		return true
	}
	return false
}
