package handler import ( "encoding/json" "fmt" "strconv" "time" "bet24.com/log" "bet24.com/redis" "bet24.com/servers/common" pb "bet24.com/servers/micros/dotservice/proto" ) // 用户信息 type userInfo struct { userId string // 用户id pb.DotScope dot_list []*pb.DotInfo // 打点数据 timeStamp int // 时间戳 } func newUserInfo(userId string) *userInfo { u := new(userInfo) u.userId = userId u.timeStamp = common.GetTimeStamp() + 300 go u.loadRedisData() return u } // redis key func (this *userInfo) getRedisKey() string { return fmt.Sprintf("%s:%s", "dotservice", this.userId) } // 获取redis数据 func (this *userInfo) loadRedisData() { key := this.getRedisKey() value, ok := redis.String_Get(key) if !ok || value == "" { return } err := json.Unmarshal([]byte(value), &this.DotScope) if err != nil { log.Error("user.loadRedisData json unmarshal userId=%s value ==> %v", this.userId, value) } return } // 处理过期 func (this *userInfo) dealExpire() bool { if this.timeStamp >= common.GetTimeStamp() { return false } // 保存并清理数据 this.saveAndClearData() return true } // 保存并清理数据 func (this *userInfo) saveAndClearData() { for _, v := range this.dot_list { // TODO:存入数据库 go trans_insert(this.userId, *v) } // 保存临时数据到redis buf, _ := json.Marshal(this.DotScope) redis.String_SetEx(this.getRedisKey(), string(buf), 3600) return } // 添加打点 func (this *userInfo) add(scope pb.DotScope) { // 判断游戏是否有效 if !this.isGameValid(scope) { return } // 热更启动场景处理 if scope.Scene == pb.Scene_HotUpdate { scope = this.hotUpdate(scope) } // 今天日期 dateFlag := time.Now().Format("2006-01-02") for _, v := range mgr.getConfigList() { if v.Scene != scope.Scene { continue } // 启动场景 if scope.Scene == pb.Scene_HotUpdate { nowSeconds, _ := strconv.Atoi(scope.Extra) cfgSeconds, _ := strconv.Atoi(v.Extra) // 超过一定时间为点击 if nowSeconds >= cfgSeconds { scope.Action = pb.Action_Click } else { scope.Action = pb.Action_Complete } scope.Extra = strconv.Itoa(common.GetTimeStamp()) this.DotScope = scope } else { // 其他场景 if v.Extra != "" && v.Extra != scope.Extra && "BL_"+v.Extra != scope.Extra { continue } } // 获取打点信息 info := this.getDotInfo(dateFlag, v.Scene, v.Event, scope.Action) if info != nil { info.Times++ continue } info = &pb.DotInfo{ DateFlag: dateFlag, Scene: scope.Scene, Event: v.Event, Action: scope.Action, Times: 1, } this.dot_list = append(this.dot_list, info) } return } // 游戏是否有效 func (this *userInfo) isGameValid(scope pb.DotScope) bool { // 游戏、赛事场景才需要判断 if scope.Scene != pb.Scene_Game && scope.Scene != pb.Scene_Match { return true } // 点击事件,直接返回 if scope.Action == pb.Action_Click { this.DotScope = scope return true } // 完成事件,同场景且之前是点击事件 if this.DotScope.Scene == scope.Scene && this.DotScope.Action == pb.Action_Click && scope.Action == pb.Action_Complete { this.DotScope = scope return true } this.DotScope = scope return false } // 热更处理 func (this *userInfo) hotUpdate(scope pb.DotScope) pb.DotScope { // 缓存里没有热更场景 if this.DotScope.Scene != scope.Scene { this.DotScope = scope return scope } // 有缓存处理 cache, _ := strconv.Atoi(this.DotScope.Extra) now, _ := strconv.Atoi(scope.Extra) scope.Extra = strconv.Itoa(now - cache) return scope } // 获取今天打点信息 func (this *userInfo) getDotInfo(dateFlag, scene, event string, action int) *pb.DotInfo { for _, v := range this.dot_list { if v.DateFlag == dateFlag && v.Scene == scene && v.Event == event && v.Action == action { return v } } return nil }