| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744 |
- package handler
- import (
- "math"
- "strconv"
- "strings"
- "time"
- waterpool "bet24.com/servers/micros/waterpool/proto"
- "bet24.com/log"
- "bet24.com/servers/common"
- pb "bet24.com/servers/micros/userlabel/proto"
- )
- const (
- seconds = 600 // 过期时长(秒)
- max_days = 30 // 保留X天数据
- )
- const (
- _ = iota // 0=无效
- tag_login_activeTime // 1=活跃时长(大厅模块)
- tag_charge_Amount // 2=付费金额(充值模块)
- tag_game_love_online // 3=游戏喜好时长(游戏模块:1=游戏时长、2=游戏流水、3=报名次数)
- tag_game_friendRoom // 4=好友房(游戏模块)
- tag_audioRoom_interactive // 5=互动类(语聊房模块)
- tag_task_award // 6=任务类(任务模块)
- tag_chat // 7=聊天类(聊天模块)
- tag_friend // 8=交际类(好友模块)
- tag_register_ipDanger // 9=IP危险(注册模块)
- tag_register_iMeiDanger // 10=IMei危险(注册模块)
- tag_charge_game_loseDanger // 11=输金危险(游戏模块)
- tag_game_cheatingDanger // 12=作弊危险(游戏模块)
- tag_charge_potentialCharge // 13=潜在付费(充值模块)
- tag_charge_passiveCharge // 14=被动付费(充值模块)
- tag_charge_savingsCharge // 15=储蓄付费(充值模块)
- tag_charge_discountCharge // 16=折扣付费(充值模块,主要用于礼包购买)
- tag_login_newbieBehavior // 17=新手行为(大厅模块)
- tag_charge_game_winDanger // 18=赚金危险(游戏模块)
- tag_register_utmsource // 19=注册来源渠道
- tag_login_return // 20=登录回归
- tag_bankruptcy // 21=破产
- tag_game_love_bet // 22=游戏喜好投注
- tag_game_love_match // 23=游戏喜好比赛报名
- tag_charge_frequency // 24=付费频率
- tag_time_love // 25=时间偏好
- )
- // 用户信息
- type userInfo struct {
- userId int // 用户id
- label_list []*pb.LabelInfo // 标签列表
- timeStamp int // 时间戳
- }
- func newUserInfo(userId int) *userInfo {
- ret := new(userInfo)
- ret.userId = userId
- ret.updateTimeStamp()
- ret.loadData()
- return ret
- }
- // 加载数据
- func (this *userInfo) loadData() {
- // TODO:数据库获取
- list := trans_GetInfo(this.userId)
- for i := 0; i < len(list); i++ {
- this.label_list = append(this.label_list, &list[i])
- }
- return
- }
- // 更新时间戳
- func (this *userInfo) updateTimeStamp() {
- this.timeStamp = common.GetTimeStamp() + seconds
- return
- }
- // 是否过期
- func (this *userInfo) isExpire() bool {
- if this.timeStamp < common.GetTimeStamp() {
- return true
- }
- return false
- }
- // 获取标签列表
- func (this *userInfo) getLabelList() []*pb.LabelInfo {
- var ret []*pb.LabelInfo
- for _, v := range this.label_list {
- if v.LabelId == "" {
- continue
- }
- ret = append(ret, v)
- }
- return ret
- }
- // 根据类型获取标签信息
- func (this *userInfo) getLabelInfo(typeId int) *pb.LabelInfo {
- for _, v := range this.label_list {
- if v.TypeId == typeId {
- return v
- }
- }
- return nil
- }
- // 设置标签
- func (this *userInfo) setLabel(typeId, days int, labelId string) {
- // 获取标签信息
- labelInfo := this.getLabelInfo(typeId)
- // 标签不存在
- if labelInfo == nil {
- labelInfo = &pb.LabelInfo{
- TypeId: typeId,
- }
- this.label_list = append(this.label_list, labelInfo)
- }
- // 更新标签
- labelInfo.LabelId = labelId
- // TODO:写入数据库
- go trans_Save(this.userId, days, labelInfo)
- }
- // 分配事件
- func (this *userInfo) dispatch(typeId int, scope pb.Scope) {
- switch typeId {
- case pb.Type_Login: // 登录
- dayIndex := common.GetDayIndex(common.GetTimeStamp())
- // 注册登录
- if scope.IsRegister {
- // 17=新手行为(大厅模块)
- this.handleEvent(tag_login_newbieBehavior, "", dayIndex, dayIndex)
- // 1=活跃时长(大厅模块)
- // this.handleEvent(tag_login_activeTime, "", 0, 0)
- // 2=付费金额(充值模块)
- // this.handleEvent(tag_charge_Amount, "", 0, 0)
- // 9=ip危险(注册模块)
- this.calIPAndIMei(tag_register_ipDanger, scope.IPAddress, "")
- // 10=IMei危险(注册模块)
- this.calIPAndIMei(tag_register_iMeiDanger, "", scope.IMei)
- // 11=注册来源渠道
- this.handleEvent(tag_register_utmsource, scope.UTMSource, dayIndex, dayIndex)
- } else { // 正常登录
- // 在线
- if scope.OnlineSeconds > 0 {
- // 1=活跃时长(大厅模块)
- this.handleEvent(tag_login_activeTime, "", scope.OnlineSeconds, 0)
- timeOfDay := ""
- timeFlag := time.Now().Hour()*100 + time.Now().Minute()
- if timeFlag >= 500 && timeFlag < 900 {
- timeOfDay = "早晨"
- } else if timeFlag >= 900 && timeFlag < 1200 {
- timeOfDay = "上午"
- } else if timeFlag >= 1200 && timeFlag < 1400 {
- timeOfDay = "中午"
- } else if timeFlag >= 1400 && timeFlag < 1800 {
- timeOfDay = "下午"
- } else if timeFlag >= 1800 && timeFlag < 1930 {
- timeOfDay = "黄昏"
- } else if timeFlag >= 1930 && timeFlag < 2200 {
- timeOfDay = "晚上"
- } else if timeFlag < 500 || timeFlag >= 2200 {
- timeOfDay = "夜间"
- }
- // 25=时间偏好(大厅模块)
- this.handleEvent(tag_time_love, timeOfDay, scope.OnlineSeconds, 0)
- }
- // 17=新手行为(大厅模块)
- this.handleEvent(tag_login_newbieBehavior, "", dayIndex, 0)
- // 20=登录回归
- this.handleEvent(tag_login_return, "", 1, 0)
- }
- case pb.Type_Charge: // 充值
- payNum := 0
- // 有实际充值才算
- if scope.PayPrice > 0 {
- payNum = scope.Num
- }
- // 2=付费金额(充值模块)
- this.handleEvent(tag_charge_Amount, "", int(scope.PayPrice), 0)
- // 11=输金危险(游戏模块、充值模块)
- this.handleEvent(tag_charge_game_loseDanger, "", 0, int(scope.PayPrice))
- // 18=赚金危险
- this.handleEvent(tag_charge_game_winDanger, "", 0, int(scope.PayPrice))
- // 13=潜在付费(充值模块)
- this.handleEvent(tag_charge_potentialCharge, "", scope.Num, int(scope.PayPrice))
- // 14=被动付费(充值模块)
- this.handleEvent(tag_charge_passiveCharge, "", scope.GoldAmount, payNum)
- // 15=储蓄付费(充值模块)
- this.handleEvent(tag_charge_savingsCharge, "", scope.GoldAmount, int(scope.PayPrice))
- // 折扣
- if scope.IsDiscount {
- // 16=折扣付费(充值模块,主要用于礼包购买)
- this.handleEvent(tag_charge_discountCharge, "", payNum, payNum)
- } else {
- // 16=折扣付费(充值模块,主要用于礼包购买)
- this.handleEvent(tag_charge_discountCharge, "", 0, payNum)
- }
- // 24=付费频率
- this.handleEvent(tag_charge_frequency, "", payNum, 0)
- case pb.Type_Game: // 游戏
- // 好友房
- if scope.IsFriendRoom {
- // 4=好友房(游戏模块)
- this.handleEvent(tag_game_friendRoom, strconv.Itoa(scope.GameId), scope.Num, 0)
- // 赢金币
- if scope.GoldAmount > 0 {
- // 12=作弊危险(游戏模块、充值模块)
- this.handleEvent(tag_game_cheatingDanger, "", scope.GoldAmount, scope.GoldAmount)
- }
- } else { // 普通游戏
- // 输金币
- if scope.GoldAmount < 0 {
- // 11=输金危险(游戏模块、充值模块)
- this.handleEvent(tag_charge_game_loseDanger, "", -scope.GoldAmount, 0)
- } else if scope.GoldAmount > 0 { // 赢金币
- // 12=作弊危险(游戏模块、充值模块)
- this.handleEvent(tag_game_cheatingDanger, "", 0, scope.GoldAmount)
- // 18=赚金危险
- this.handleEvent(tag_charge_game_winDanger, "", scope.GoldAmount, 0)
- }
- }
- // 游戏喜好(游戏模块:3=游戏时长、22=游戏流水、23=报名次数)
- if scope.OnlineSeconds > 0 {
- this.handleEvent(tag_game_love_online, strconv.Itoa(scope.GameId), scope.OnlineSeconds, 0)
- } else if scope.GoldAmount != 0 {
- gold := int(math.Abs(float64(scope.GoldAmount)))
- this.handleEvent(tag_game_love_bet, strconv.Itoa(scope.GameId), gold, 0)
- }
- case pb.Type_Task: // 任务
- // 6=任务类(任务模块)
- this.handleEvent(tag_task_award, "", scope.Num, 0)
- case pb.Type_Chat: // 聊天
- // 7=聊天类(聊天模块)
- this.handleEvent(tag_chat, "", scope.Num, 0)
- case pb.Type_AudioRoom: // 6=语聊房
- // 5=互动类(语聊房模块)
- this.handleEvent(tag_audioRoom_interactive, "", scope.Num, 0)
- case pb.Type_Friend: // 7=好友
- // 8=交际类(好友模块)
- this.handleEvent(tag_friend, "", scope.Num, 0)
- case pb.Type_Bankruptcy: // 8=破产
- // 21=破产
- this.handleEvent(tag_bankruptcy, "", scope.Num, 0)
- default:
- log.Error("user.dispatch userId=%d typeId=%d scope=%+v is not dealt ", this.userId, typeId, scope)
- }
- return
- }
- // 处理事件
- func (this *userInfo) handleEvent(typeId int, param string, value int, totalValue int) {
- dayIndex := common.GetDayIndex(common.GetTimeStamp())
- var (
- labelInfo *pb.LabelInfo
- dayInfo *pb.DayInfo
- )
- // 标签列表
- for _, v := range this.label_list {
- if v.TypeId != typeId {
- continue
- }
- labelInfo = v
- break
- }
- // 标签不存在
- if labelInfo == nil {
- labelInfo = &pb.LabelInfo{
- TypeId: typeId,
- }
- this.label_list = append(this.label_list, labelInfo)
- }
- // 累计类(如:充值、输金风险、被动付费、储蓄付费、折扣付费、交际类、登录回归)
- if typeId == tag_charge_game_loseDanger || typeId == tag_charge_game_winDanger || typeId == tag_charge_passiveCharge ||
- typeId == tag_charge_savingsCharge || typeId == tag_charge_discountCharge ||
- typeId == tag_friend || typeId == tag_login_return {
- labelInfo.TotalValue += totalValue
- } else if typeId == tag_login_newbieBehavior { // 新手行为
- if totalValue > 0 {
- labelInfo.TotalValue = totalValue
- }
- }
- // 每天数据
- for _, v := range labelInfo.Days {
- // 判断日期
- if v.Index != dayIndex {
- continue
- }
- // 判断游戏ID
- if v.Param != param {
- continue
- }
- dayInfo = v
- }
- // 每天数据不存在
- if dayInfo == nil {
- dayInfo = &pb.DayInfo{
- Index: dayIndex,
- Param: param,
- Value: 0,
- }
- labelInfo.Days = append(labelInfo.Days, dayInfo)
- }
- // 保留 max_days 天数据
- if count := len(labelInfo.Days); count > max_days {
- labelInfo.Days = labelInfo.Days[count-max_days:]
- }
- // 作弊危险
- if typeId == tag_game_cheatingDanger {
- // 获取配置信息
- cfg := mgr.getConfigInfo(labelInfo.TypeId)
- if cfg == nil {
- log.Error("user.triggerCounter userId=%d typeId=%d", this.userId, typeId)
- return
- }
- for _, v := range cfg.Content {
- if value < v.Min && totalValue < v.Min {
- return
- }
- }
- labelInfo.TotalValue += totalValue
- } else if typeId == tag_charge_potentialCharge { // 潜在付费
- dayInfo.ExtValue = totalValue
- }
- // 储蓄付费、交际类、新手行为、登录回归,不累计
- if typeId == tag_charge_savingsCharge || typeId == tag_friend || typeId == tag_login_newbieBehavior || typeId == tag_login_return {
- dayInfo.Value = value
- } else if typeId == tag_charge_passiveCharge { // 被动付费
- // 获取配置信息
- cfg := mgr.getConfigInfo(labelInfo.TypeId)
- if cfg == nil {
- log.Error("user.triggerCounter userId=%d typeId=%d", this.userId, typeId)
- return
- }
- for _, v := range cfg.Content {
- if value <= v.Min {
- dayInfo.Value += totalValue
- break
- }
- }
- } else { // 累计
- dayInfo.Value += value
- }
- go func() {
- var ret pb.CalResult
- // 计算用户标签
- if ret = this.cal(labelInfo, value); ret.Success && labelInfo.LabelId != ret.LabelId {
- // log.Debug("handleEvent userId=%d ret=%+v", this.userId, ret)
- labelInfo.LabelId = ret.LabelId
- if ret.PoolValue != 0 {
- // 触发水池
- go waterpool.GrantUserNewWaterPool(this.userId, ret.PoolValue, ret.LabelName)
- }
- }
- // TODO:存入数据库
- trans_Save(this.userId, ret.Days, labelInfo)
- }()
- }
- // 根据用户数据计算标签
- func (this *userInfo) cal(labelInfo *pb.LabelInfo, value int) pb.CalResult {
- var ret pb.CalResult
- // 获取配置信息
- cfg := mgr.getConfigInfo(labelInfo.TypeId)
- if cfg == nil {
- log.Error("user.cal userId=%d typeId=%d", this.userId, labelInfo.TypeId)
- return ret
- }
- total, totalExt, dayIndex := 0, 0, common.GetDayIndex(common.GetTimeStamp())
- switch labelInfo.TypeId {
- case tag_login_activeTime: // 1=活跃时长
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- total += v.Value
- }
- avg := total / cfg.Days
- for _, v := range cfg.Content {
- if v.Min <= avg && avg <= v.Max {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_charge_Amount: // 2=付费金额
- fallthrough
- case tag_game_friendRoom: // 4=好友房
- fallthrough
- case tag_audioRoom_interactive: // 5=互动类
- fallthrough
- case tag_task_award: // 6=任务类
- fallthrough
- case tag_chat: // 7=聊天类
- fallthrough
- case tag_bankruptcy: // 21=破产
- fallthrough
- case tag_game_love_online: // 3=游戏喜好时长
- fallthrough
- case tag_game_love_bet: // 22=游戏喜好流水
- fallthrough
- case tag_game_love_match: // 23=游戏喜好比赛报名
- fallthrough
- case tag_charge_frequency: // 24=付费频率
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- total += v.Value
- }
- for _, v := range cfg.Content {
- if v.Min <= total && total <= v.Max {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_friend: // 8=交际类
- fallthrough
- case tag_login_return: // 20=登录回归
- for _, v := range cfg.Content {
- if labelInfo.TotalValue >= v.Min {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_charge_potentialCharge: // 13=潜在付费
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- total += v.Value
- totalExt += v.ExtValue
- }
- for _, v := range cfg.Content {
- if v.Min <= total && v.Ext >= totalExt {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_register_ipDanger: // 9=IP危险
- // Nothing(manager已处理)
- case tag_register_iMeiDanger: // 10=IMei危险
- // Nothing(manager已处理)
- case tag_charge_game_loseDanger: // 11=输金危险
- fallthrough
- case tag_charge_game_winDanger: // 18=赚金危险
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- total += v.Value
- }
- for _, v := range cfg.Content {
- if total > 0 && total >= int(float64(labelInfo.TotalValue*v.Ext)*(float64(v.Percentage)/100.00)) && total >= v.Min {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_game_cheatingDanger: // 12=作弊危险
- fallthrough
- case tag_charge_passiveCharge: // 14=被动付费
- fallthrough
- case tag_charge_discountCharge: // 16=折扣付费
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- total += v.Value
- }
- for _, v := range cfg.Content {
- if total > 0 && total >= int(float64(labelInfo.TotalValue)*(float64(v.Percentage)/100.00)) {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_charge_savingsCharge: // 15=储蓄付费
- for _, v := range cfg.Content {
- if value >= int(float64(labelInfo.TotalValue*v.Ext)*(float64(v.Percentage)/100.00)) && value >= v.Min {
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_login_newbieBehavior: // 17=新手行为
- // total = labelInfo.Days[len(labelInfo.Days)-1].Index - labelInfo.TotalValue + 1
- if cfg.Days > 0 && labelInfo.TotalValue < labelInfo.Days[len(labelInfo.Days)-1].Index-cfg.Days {
- ret = pb.CalResult{
- Success: true,
- LabelId: "",
- LabelName: "",
- PoolValue: 0,
- Days: cfg.Days,
- }
- return ret
- }
- total = len(labelInfo.Days)
- for _, v := range cfg.Content {
- if v.Min <= total && total <= v.Max {
- // log.Debug("userId=%d v=%+v", this.userId, v)
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- }
- case tag_register_utmsource: // 19=新注册来源
- utmSource := ""
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- utmSource = strings.ToLower(v.Param)
- }
- for _, v := range cfg.Content {
- if !strings.Contains(utmSource, strings.ToLower(v.LabelName)) {
- continue
- }
- ret = pb.CalResult{
- Success: true,
- LabelId: v.LabelId,
- LabelName: v.LabelName,
- PoolValue: v.PoolValue,
- Days: cfg.Days,
- }
- return ret
- }
- case tag_time_love: // 25=时间偏好
- sum_list := make(map[string]int)
- for _, v := range labelInfo.Days {
- if cfg.Days > 0 && v.Index < dayIndex-cfg.Days {
- continue
- }
- vu, ok := sum_list[v.Param]
- if ok {
- vu += v.Value
- }
- sum_list[v.Param] = vu
- }
- if len(sum_list) <= 0 {
- break
- }
- var (
- max_value int
- max_labelId string
- max_labelName string
- max_poolValue int
- )
- for _, v := range cfg.Content {
- vu, ok := sum_list[v.LabelName]
- if !ok {
- continue
- }
- if vu < max_value {
- continue
- }
- max_value = vu
- max_labelId = v.LabelId
- max_labelName = v.LabelName
- max_poolValue = v.PoolValue
- }
- ret = pb.CalResult{
- Success: true,
- LabelId: max_labelId,
- LabelName: max_labelName,
- PoolValue: max_poolValue,
- Days: cfg.Days,
- }
- return ret
- }
- ret = pb.CalResult{
- Success: true,
- LabelId: "",
- LabelName: "",
- PoolValue: 0,
- Days: cfg.Days,
- }
- return ret
- }
- // IPAddress、IMei 类计算
- func (this *userInfo) calIPAndIMei(typeId int, ipAddress, iMei string) {
- // 获取配置信息
- cfg := mgr.getConfigInfo(typeId)
- if cfg == nil {
- log.Error("user.calIPAndIMei userId=%d typeId=%d ipAddress=%s iMei=%s", this.userId, typeId, ipAddress, iMei)
- return
- }
- for _, v := range cfg.Content {
- // TODO:从数据库查询
- users := trans_GetIPAndIMei(ipAddress, iMei, cfg.Days)
- // 没有达到用户数
- if len(users) < v.Min {
- continue
- }
- // 符合标签的用户
- for _, uId := range users {
- // 获取当前用户
- u := mgr.getUser(uId)
- if u == nil {
- log.Debug("manager.calIPAndIMei userId=%d typeId=%d ipAddress=%s iMei=%s ", uId, typeId, ipAddress, iMei)
- continue
- }
- // 设置标签
- u.setLabel(typeId, cfg.Days, v.LabelId)
- }
- }
- return
- }
|