Spark学习笔记(19)—— 游戏日志分析

1 数据

0  管理员登录
1 首次登录
2 上线
3 下线
1|2016年2月1日,星期一,10:01:08|10.51.4.168|李明克星|法师|男|1|0|0/800000000
1|2016年2月1日,星期一,10:01:12|10.117.45.20|风道|道士|男|1|0|0/800000000
4|2016年2月1日,星期一,10:01:27|10.51.4.168|李明克星|法师|男|2|0|0/800000000
4|2016年2月1日,星期一,10:01:30|10.117.45.20|风道|道士|男|2|0|0/800000000
4|2016年2月1日,星期一,10:01:35|10.51.4.168|李明克星|法师|男|3|0|273/800000000
1|2016年2月1日,星期一,10:01:37|10.171.198.176|主宰|武士|男|1|0|0/800000000
4|2016年2月1日,星期一,10:01:37|10.117.45.20|风道|道士|男|3|0|0/800000000
4|2016年2月1日,星期一,10:01:42|10.51.4.168|李明克星|法师|男|4|0|538/800000000
4|2016年2月1日,星期一,10:01:45|10.117.45.20|风道|道士|男|4|0|157/800000000
4|2016年2月1日,星期一,10:01:47|10.51.4.168|李明克星|法师|男|5|0|750/800000000
1|2016年2月1日,星期一,10:01:49|10.168.8.103|潮流哥|法师|男|1|0|0/800000000
4|2016年2月1日,星期一,10:01:54|10.51.4.168|李明克星|法师|男|6|0|872/800000000
4|2016年2月1日,星期一,10:01:54|10.117.45.20|风道|道士|男|5|0|340/800000000
4|2016年2月1日,星期一,10:02:00|10.51.4.168|李明克星|法师|男|7|0|987/800000000
4|2016年2月1日,星期一,10:02:01|10.117.45.20|风道|道士|男|6|0|453/800000000
4|2016年2月1日,星期一,10:02:05|10.51.4.168|李明克星|法师|男|8|0|1243/800000000
4|2016年2月1日,星期一,10:02:06|10.117.45.20|风道|道士|男|7|0|684/800000000
4|2016年2月1日,星期一,10:02:14|10.51.4.168|李明克星|法师|男|9|0|1375/800000000
4|2016年2月1日,星期一,10:02:16|10.117.45.20|风道|道士|男|8|0|905/800000000
1|2016年2月1日,星期一,10:02:22|10.168.8.103|潮流锅|武士|男|1|0|0/800000000
4|2016年2月1日,星期一,10:02:23|10.117.45.20|风道|道士|男|9|0|1120/800000000
4|2016年2月1日,星期一,10:02:24|10.51.4.168|李明克星|法师|男|10|0|1500/800000000
........

2 代码

TimeUtils .scala

package gamelog

import java.text.SimpleDateFormat
import java.util.Calendar

object TimeUtils {

  val simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
  val calendar = Calendar.getInstance()

  def apply(time: String) = {
    calendar.setTime(simpleDateFormat.parse(time))
    calendar.getTimeInMillis
  }

  def getCertainDayTime(amount: Int): Long ={
    calendar.add(Calendar.DATE, amount)
    val time = calendar.getTimeInMillis
    calendar.add(Calendar.DATE, -amount)
    time
  }
  

}

package gamelog

/**
  * 事件类型枚举
  * 0 管理员登陆
  * 1 首次登陆
  * 2 上线
  * 3 下线
  * 4 升级
  */
object EventType {

  val REGISTER = "1"

  val LOGIN = "2"

  val LOGOUT = "3"

  val UPGRADE = "4"

}

FilterUtils.scala

package gamelog

import org.apache.commons.lang3.time.FastDateFormat

object FilterUtils {

  val dateFormat = FastDateFormat.getInstance("yyyy年MM月dd日,E,HH:mm:ss")

  def filterByTime(fields: Array[String], startTime: Long, endTime: Long): Boolean = {
    val time = fields(1)
    val logTime = dateFormat.parse(time).getTime

    logTime >= startTime && logTime < endTime
  }

  def filterByType(fields: Array[String], evenType: String): Boolean = {
    val _type = fields(0)
    evenType == _type
  }

  def filterByTypes(fields: Array[String], eventTypes: String*): Boolean = {
    val _type = fields(0)
    for(et <- eventTypes){
      if(_type==et)
        return true
    }
    false
  }

  def filterByTypeAndTime(fields: Array[String], eventType: String, beginTime: Long, endTime: Long): Boolean = {
    val _type = fields(0)
    val _time = fields(1)
    val logTime = dateFormat.parse(_time).getTime
    eventType == _type && logTime >= beginTime && logTime < endTime
  }


}

2.1 新增用户

package gamelog

import org.apache.spark.{SparkConf, SparkContext}

object GameKPI {
  def main(args: Array[String]): Unit = {

    val queryTime = "2016-02-01 00:00:00"
    val beginTime = TimeUtils(queryTime)
    val endTime = TimeUtils.getCertainDayTime(+1)

    val conf = new SparkConf().setAppName("GameKPI").setMaster("local[*]")
    val sc = new SparkContext(conf)

    //切分后的数据
    val splitedLogs =  sc.textFile("d://Gamelog.txt").map(_.split("\\|"))

    //过滤后并缓存
    val filteredLogs =  splitedLogs.filter(fields => FilterUtils.filterByTime(fields,beginTime,endTime))
      .cache()

    //日新增用户
    val dnu = filteredLogs.filter(fields => FilterUtils.filterByType(fields,EventType.REGISTER))
      .count()
    println(dnu)

    //

    sc.stop()

  }
}

在这里插入图片描述

2.2 活跃用户

  //Daily Active Users
    val dau =  filteredLogs.filter(fields => FilterUtils.filterByTypes(fields,EventType.REGISTER,EventType.LOGIN))
        .map(_(3))
        .distinct()
        .count()
    println(dau)

    sc.stop()

在这里插入图片描述

2.3 留存率

  //  留存率:某段时间的新增用户数记为A,经过一段时间后,仍然使用的用户占新增用户A的比例即为留存率
    //  次日留存率(Day 1 Retention Ratio) Retention Ratio
    //  日新增用户在+1日登陆的用户占新增用户的比例
    val t1 = TimeUtils.getCertainDayTime(-1)
    val lastDayRegUser = splitedLogs.filter(fields => FilterUtils.filterByTypeAndTime(fields, EventType.REGISTER, t1, beginTime))
      .map(x => (x(3), 1))
    val todayLoginUser = filteredLogs.filter(fields => FilterUtils.filterByType(fields, EventType.LOGIN))
      .map(x => (x(3), 1))
      .distinct()

    val d1r: Double = lastDayRegUser.join(todayLoginUser).count()
    println(d1r)
    val d1rr = d1r / lastDayRegUser.count()
    println(d1rr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值