实现要点
1、基于jquery.slider 动态设置series,数据基于前台动态渲染。
2、legend的动态创建。
效果图:
JSP页面源码:
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%long version = java.lang.System.currentTimeMillis();%>
APP统计 | 神州专车
查询条件
用户新鲜度
/**
* 用户新鲜度模块
* @author 石冬冬
* @date 2016/12/1
*/
var Freshness = {
Cts:{
charts:{
render:null,
viewData:null,
totals:[]
},
limit:[0,31],
rs:null
},
/**
* 初始化
*/
init:function(){
this.initEvts();
this.initVals();
this.initSlideBar(false);
this.initData();
this.renderCharts();
},
/**
* 初始化事件
*/
initEvts:function(){
var _this = Freshness;
$('#btnQuery').off().live('click',function(){
_this.initData();
_this.renderCharts();
});
//选项卡切换
$('a[eleType=tab]').off().live('click',function(){
var dataType = $(this).attr('dataType');
$('#dataType').val(dataType);
_this.initData();
_this.renderCharts();
});
$('#slideBarCheckbox').off().live('click',function(){
var checked = $(this).attr('checked');
var enabled = checked=='checked';
_this.initSlideBar(enabled);
});
},
/**
* 初始化相关元素的值
*/
initVals:function(){
var appVersion = $('#appVersionList').val();
if(appVersion){
appVersion = eval('('+appVersion+')');
loadData(appVersion);
}
},
/**
* 初始化标尺滚动条
* @param enabled
* API:http://demo.htmleaf.com/1502/201502041438/index.html
* http://blog.csdn.net/u011127019/article/details/52992654
*/
initSlideBar:function(enabled){
var _this = Freshness;
//初始化配置项
$("#slideBar").slider({
handle:'round',
min:0,
max:31,
step:1,
value:[0,31],
tooltip_split:true,
formatter: function(value) {
var start = value[0];
var end = value[1];
if(start==0){
start = '当天';
}else{
start+='天前';
}
if(end==31){
end = '31天+前';
}else{
end+='天前';
}
var tips = start+'至'+end+'新增';
if(value && $.isArray(value) && value.length==2){
$('#slideBarTips').text(tips);
}
return value;
}
});
//监听滑动事件
$("#slideBar").on("change", function() {
var value = this.value.split(",");
if(value){
_this.Cts.limit=value;
_this.renderCharts();//刷新加载echarts
}
});
//根据可用多选框设置控件是否可用
if(enabled){
$('#slideBarTips').show();
$("#slideBar").slider("enable");
}else{
$('#slideBarTips').hide();
$("#slideBar").slider("setValue",[0,31]);
$("#slideBar").slider("disable");
_this.Cts.limit=[0,31];
_this.renderCharts();//刷新加载echarts
}
},
/**
* 初始化报表
* @param args 对象
* @param xAxisData x坐标数组
*/
initCharts:function(args,xAxisData){
var dataType = $('#dataType').val();
var _yAxis = [
{
type : 'value',
boundaryGap : false
}
];
if(dataType=='BFB'){
_yAxis = [
{
type : 'value',
max:'100',
axisLabel: {
show: true,
interval: 'auto',
formatter: '{value} %'
},
boundaryGap : false
}
];
}
var _this = Freshness;
var series = args.seriesData;
var legendData = args.legendData;
var myChart = echarts.init(document.getElementById("chart_div"), 'line');
this.Cts.charts.render = myChart;
var option = {
title : {
},
tooltip : {
trigger: 'axis',
formatter:function (params,ticket,callback) {
var tips = '';
if(dataType=='JDZ'){
var seriesName = params.seriesName;
var value = params.value;
var name = params.name;
var total = _this.findTotal(name);
var ratio = 0;
if(total!=0){
ratio = ((value / total)*100).toFixed(2);
}
tips = name + '
在' + seriesName + '新增(占当日活跃比):
'+ value + '('+ratio+'%)' + '
当日全部活跃:'+total;
}
if(dataType=='BFB'){
var seriesName = params.seriesName;
var name = params.name;
var total = _this.findTotal(name);
var value = params.value;
value = value/100*total;
var ratio = 0;
if(total!=0){
ratio = ((value / total)*100).toFixed(2);
}
tips = name + '
在' + seriesName + '新增(占当日活跃比):
'+ value + '('+ratio+'%)' + '
当日全部活跃:'+total;
}
return tips;
}
},
legend: {
show:false,
width:'80%',
padding: [5,100,5,100],
itemGap: 10,
data : legendData
},
dataZoom:{},
toolbox: {
show : true,
feature : {
mark : {show: false},
dataView : {show: true, readOnly: false},
magicType: {show: true, type: ['line','bar','stack', 'tiled']},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : [{
type:'category',
interval:0,
boundaryGap:false,
data:xAxisData
}],
yAxis : _yAxis,
series : series
};
myChart.setOption(option);
},
/**
* 根据series的datas构建seriesData和legendData
* @param datas
*/
initSeries:function(datas){
var _this = Freshness;
var limit = _this.Cts.limit;
console.log('limit=%s',JSON.stringify(limit));
var from = Number(limit[0]) ;
var to = Number(limit[1]);
var legendData = [];
var series = [];
for(var i=to;i>=from;i--){
var name = i+'天前';
if(i==0){
name = '当天';
}
if(i==31){
name = '30+天前';
}
legendData.push(name);
var vo = {
name: name,
type: 'line',
stack:'1',
tooltip : {
show : true,
trigger: 'item'
},
areaStyle: {normal: {}},
data: datas[i]
};
series.push(vo);
}
return {
seriesData:series,
legendData:legendData
};
},
/**
* 初始化数据
*/
initData:function(){
var params = $('#searchForm').serialize();
var _this = Freshness;
$.ajax({
type : "post",
url : BATH_PATH + "retentionAnalysis/loadForFreshness",
data: params,
dataType : "json",
async : false,
error : function(xhr, status, err) {
//alert(err);
},
success : function(rs) {
_this.Cts.rs = rs;
}
});
},
/**
* 根据容量构建二维数组
* @returns {Array} 二维数组
*/
initArrays:function(){
var capacity = 31;
var arrays = [];
for(var i = 0;i<=capacity;i++){
arrays.push([]);
}
return arrays;
},
/**
* 根据xAxisName 查询对应的 活跃总数
* @param xAxisName
*/
findTotal:function(xAxisName){
var totals = this.Cts.charts.totals;
var total = 0;
if(totals){
$.each(totals,function(index){
//console.log('key=%s,val=%s',totals[index].key,val);
if(totals[index].key == xAxisName){
total = totals[index].total;
return;
}
});
}
return total;
},
/**
* 渲染Charts
* @param rs
*/
renderCharts:function(){
var _this = Freshness;
var rs = _this.Cts.rs;
var dataType = $('#dataType').val();
var xAxisData = [];
var datas = this.initArrays();
var totals = [];
if(rs){
var data = rs.dataMap;
//======================绝对值=============================
if(dataType=='JDZ'){
$.each(data,function(key,vo){
xAxisData.push(key);
totals.push({key:key,total:vo.total});
//console.log('key=%s,total=%s',key,vo.total);
$.each(vo.groupMap,function(index,val){
datas[index].push(val);
});
});
//console.info("arrays=%s",JSON.stringify(datas));
}
//======================百分比=============================
if(dataType=='BFB'){
$.each(data,function(key,vo){
xAxisData.push(key);
var total = vo.total;
totals.push({key:key,total:total});
//console.log('key=%s,total=%s',key,vo.total);
$.each(vo.groupMap,function(index,val){
var percent = (val==0)?0:((val/total)*100).toFixed(2);
datas[index].push(percent);
});
});
}
}
//console.log('totals=%s',JSON.stringify(totals));
_this.Cts.charts.totals = totals;
//console.log('totals=%s',JSON.stringify(_this.Cts.charts.totals));
var args = _this.initSeries(datas);
_this.initCharts(args,xAxisData);
}
};
Freshness.init();
package com.ucar.appcount.web.controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ucar.appcount.common.Common;
import com.ucar.appcount.common.vo.SearchObject;
import com.ucar.appcount.service.AdminManagerServiceNew;
import com.ucar.appcount.service.RetentionAnalysisService;
import com.zuche.framework.utils.StringUtils;
/**
* 留存分析
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-28 下午6:53:41
*/
@Controller
@RequestMapping("retentionAnalysis")
public class RetentionAnalysisController {
private static final Logger logger = Logger.getLogger(RetentionAnalysisController.class);
@Autowired
private AdminManagerServiceNew adminManagerServiceNew;
@Autowired
private RetentionAnalysisService retentionAnalysisService;
private final String PAGE_PREFIX = "retention/";
/**
* 留存用户|页面
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-28 下午7:01:07
* @param model
* @param searchObj
* @return
*/
@RequestMapping("retention")
public String retention(Model model,SearchObject searchObj){
try {
List appChannel = adminManagerServiceNew.getAppChannel();
List appVersion = adminManagerServiceNew.getAppVersion();
String timeType = searchObj.getTimeType();
String columnTitleSuffix = "天后";
if(StringUtils.isEmpty(timeType)){
timeType = Common.DATATYPE.DAY;
}
initSearchObj(searchObj);
if(Common.DATATYPE.DAY.equals(timeType)){
model.addAttribute("columns", RetentionAnalysisService.ReportTitle.DAILY);
columnTitleSuffix = "天后";
}
if(Common.DATATYPE.WEEK.equals(timeType)){
model.addAttribute("columns", RetentionAnalysisService.ReportTitle.WEEK);
columnTitleSuffix = "周后";
}
if(Common.DATATYPE.MONTH.equals(timeType)){
model.addAttribute("columns", RetentionAnalysisService.ReportTitle.MONTH);
columnTitleSuffix = "月后";
}
model.addAttribute("columnTitleSuffix", columnTitleSuffix);
model.addAttribute("searchObj", searchObj);
model.addAttribute("appChannel",appChannel);
model.addAttribute("appVersion", appVersion);
} catch (Exception e) {
logger.error("留存用户初始化异常",e);
}
return PAGE_PREFIX.concat("retention");
}
/**
* 用户新鲜度
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-12-1 下午2:00:31
* @param model
* @param searchObj
* @return
*/
@RequestMapping("freshness")
public String freshness(Model model,SearchObject searchObj){
try {
List appChannel = adminManagerServiceNew.getAppChannel();
List appVersion = adminManagerServiceNew.getAppVersion();
String timeType = searchObj.getTimeType();
if(StringUtils.isEmpty(timeType)){
timeType = Common.DATATYPE.DAY;
}
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//开始时间为空则取三个月前
if(StringUtils.isBlank(searchObj.getBeginTime())){
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.MONTH,-1);
searchObj.setBeginTime(sdf.format(calendar.getTime()));
}
if(StringUtils.isBlank(searchObj.getEndTime())){
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,-1);
searchObj.setEndTime(sdf.format(calendar.getTime()));
}
searchObj.setDataType("JDZ");//默认 绝对值
model.addAttribute("searchObj", searchObj);
model.addAttribute("appChannel",appChannel);
model.addAttribute("appVersion", appVersion);
} catch (Exception e) {
logger.error("留存用户初始化异常",e);
}
return PAGE_PREFIX.concat("freshness");
}
/**
* 留存用户
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-29 上午9:53:00
* @param searchObj
* @return
*/
@RequestMapping("loadForRetention")
@ResponseBody
public Object loadForRetention(SearchObject searchObj){
Map dataMap = new HashMap();
if(!StringUtils.isBlank(searchObj.getTimeType())){
Map> result = this.retentionAnalysisService.retention(searchObj);
dataMap.put("data", result);
}
return dataMap;
}
/**
* 用户新鲜度
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-29 上午9:53:00
* @param searchObj
* @return
*/
@RequestMapping("loadForFreshness")
@ResponseBody
public Object loadForFreshness(SearchObject searchObj){
return this.retentionAnalysisService.freshness(searchObj);
}
@RequestMapping("activeDegree")
public String toActiveDegree(Model model,SearchObject searchObj){
List appChannel = adminManagerServiceNew.getAppChannel();
List appVersion = adminManagerServiceNew.getAppVersion();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//开始时间为空则取三个月前
if(StringUtils.isBlank(searchObj.getBeginTime())){
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.MONTH,-1);
searchObj.setBeginTime(sdf.format(calendar.getTime()));
}
if(StringUtils.isBlank(searchObj.getEndTime())){
Calendar calendar=Calendar.getInstance();
//calendar.add(Calendar.DAY_OF_YEAR,-1);
searchObj.setEndTime(sdf.format(calendar.getTime()));
}
model.addAttribute("searchObj", searchObj);
model.addAttribute("appChannel",appChannel);
model.addAttribute("appVersion", appVersion);
return PAGE_PREFIX+"/activeDegree";
}
@RequestMapping("loadActiveDegree")
@ResponseBody
public Object loadActiveDegree(SearchObject searchObj){
initSearchObj(searchObj);
Map> map=new HashMap>();
try {
map=retentionAnalysisService.getActiveDegree(searchObj);
} catch (ParseException e) {
e.printStackTrace();
}
return map;
}
@RequestMapping("loadActive15Degree")
@ResponseBody
public Object loadActive15Degree(SearchObject searchObj){
initSearchObj(searchObj);
Map> map=new HashMap>();
try {
map=retentionAnalysisService.getActive15Degree(searchObj);
} catch (ParseException e) {
e.printStackTrace();
}
return map;
}
private void initSearchObj(SearchObject seachObj) {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//开始时间为空则取三个月前
if(StringUtils.isBlank(seachObj.getBeginTime())){
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.WEEK_OF_YEAR,-1);
seachObj.setBeginTime(sdf.format(calendar.getTime()));
}
if(StringUtils.isBlank(seachObj.getEndTime())){
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,-1);
seachObj.setEndTime(sdf.format(calendar.getTime()));
}
}
}
package com.ucar.appcount.service.impl;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.hadoop.hbase.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.ucar.appcount.common.Common;
import com.ucar.appcount.common.CommonUtils;
import com.ucar.appcount.common.DateFormatUtil;
import com.ucar.appcount.common.vo.RetentionFreshnessVo;
import com.ucar.appcount.common.vo.SearchObject;
import com.ucar.appcount.component.SearchComponent;
import com.ucar.appcount.hbase.service.DevActive15DegreeTabServiceNew;
import com.ucar.appcount.hbase.service.DevActiveDegreeTabServiceNew;
import com.ucar.appcount.hbase.service.impl.BaseOperator;
import com.ucar.appcount.service.DevUserServiceNew;
import com.ucar.appcount.service.RetentionAnalysisDailyTabService;
import com.ucar.appcount.service.RetentionAnalysisMonthTabService;
import com.ucar.appcount.service.RetentionAnalysisService;
import com.ucar.appcount.service.RetentionAnalysisWeekTabService;
import com.ucar.appcount.service.RetentionFreshnessDailyTabService;
import com.zuche.framework.nosql.hbase098.vo.Column;
import com.zuche.framework.nosql.hbase098.vo.RowVo;
import com.zuche.framework.utils.StringUtils;
@Service
public class RetentionAnalysisServiceImpl extends BaseOperator implements RetentionAnalysisService {
private static final Logger logger = LoggerFactory.getLogger(RetentionAnalysisServiceImpl.class);
@Autowired
private SearchComponent searchComponent;
@Autowired
private RetentionAnalysisDailyTabService retentionAnalysisDailyTabService;
@Autowired
private RetentionAnalysisWeekTabService retentionAnalysisWeekTabService;
@Autowired
private RetentionAnalysisMonthTabService retentionAnalysisMonthTabService;
@Autowired
private RetentionFreshnessDailyTabService retentionFreshnessDailyTabService;
@Autowired
private DevActiveDegreeTabServiceNew activeDegreeTabService;
@Autowired
private DevActive15DegreeTabServiceNew active15DegreeTabService;
@Autowired
private DevUserServiceNew devUserServiceNew;
@Override
public List queryRowVoList(SearchObject searchObj,String filterList){
List rs = Collections.emptyList();
String timeType= searchObj.getTimeType();
if(Common.DATATYPE.DAY.equals(timeType)){
rs = this.retentionAnalysisDailyTabService.queryRetentionRows(searchObj, filterList);
}
if(Common.DATATYPE.WEEK.equals(timeType)){
rs = this.retentionAnalysisWeekTabService.queryRetentionRows(searchObj, filterList);
}
if(Common.DATATYPE.MONTH.equals(timeType)){
rs = this.retentionAnalysisMonthTabService.queryRetentionRows(searchObj, filterList);
}
return rs;
}
@Override
public Map> retention(SearchObject searchObj) {
Map> dataMap = new LinkedHashMap>();
try {
String timeType= searchObj.getTimeType();
final boolean byDay = Common.DATATYPE.DAY.equals(timeType);
final boolean byWeek = Common.DATATYPE.WEEK.equals(timeType);
final boolean byMonth = Common.DATATYPE.MONTH.equals(timeType);
/*****************************************************************/
/**
* 如果是按月统计:对开始时间 和 结束时间 逻辑控制
* 开始时间如果非开始时间当月的第一天,需要重置为下个月的第一天。
* 结束时间如果非结束时间当月的第一条,需要重置为上个月的第一天。
*/
/*****************************************************************/
RetentionHandler.resetSearchTimeForByMonth(byMonth,searchObj);
if(byMonth){
Date start = DateFormatUtil.convertToDate(searchObj.getBeginTime(), DateFormatUtil.FORMAT_DATE_DISPLAY);
Date end = DateFormatUtil.convertToDate(searchObj.getEndTime(), DateFormatUtil.FORMAT_DATE_DISPLAY);
if(start.getTime()!=end.getTime()&&!end.after(start)){
return dataMap;
}
}
//1、构建查询结果Map
this.searchComponent.initDataMapForRetention(dataMap,searchObj);
String filterList = this.searchComponent.initFilterList(searchObj);
//2、获取新增用户Map
Map userAddMap = this.devUserServiceNew.getNewUserNum(searchObj);
//2.1、按时间装载新增用户数
Set>> entrySet = dataMap.entrySet();
for(Entry> entry : entrySet){
String dataKey = entry.getKey();
if(userAddMap.containsKey(dataKey)){
Map columnMap = entry.getValue();
Double addUsers = Double.valueOf(userAddMap.get(dataKey).doubleValue());
columnMap.put(0, addUsers);
}
}
/*****************************************************************/
/**
* rowkey特殊规则说明:新增日期#APP类型#APP版本#下载渠道#统计日期
* 按天:(20161125#M_android#600340#360shoujizhushou#20161128)
* 按周:(20161128#M_android#600340#360shoujizhushou#20161130)
* 按月:(20161101#M_android#600340#360shoujizhushou#20161201)
*/
/*****************************************************************/
//3、获取留存用户
List rs = this.queryRowVoList(searchObj, filterList);
for(RowVo row : rs){
String key = row.getRowKey();//新增日期
String rowKey = row.getRowKey();
String tjrq = rowKey.substring(rowKey.lastIndexOf("#")+1);
key = key.substring(0,key.indexOf("#",0));
key = CommonUtils.handlerTime(key, timeType);
tjrq = CommonUtils.handlerTime(tjrq, timeType);//统计日期
if(byWeek){//按周统计,把日期都转换成这个星期的第一天
key = DateFormatUtil.getFirstDayOfWeek(key);
key = key + "~" + DateFormatUtil.getLastDayOfWeek(key);
}
int days = 0;//天数
if(byDay||byWeek){
days=Long.valueOf(DateFormatUtil.getTwoDateDifference(key,tjrq)).intValue();
}else{
String s=key.concat("-01");
String e=tjrq.concat("-01");
days=Long.valueOf(DateFormatUtil.getTwoDateDifference(s,e)).intValue();
}
List columns = row.getColumns();
Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count")));
if(dataMap.containsKey(key)){
Map columnMap = dataMap.get(key);
int columnIndex = RetentionHandler.getColumnIndexForRetention(timeType, days);//获取时间类型(天/周/月)对列索引
Double retention = columnMap.get(columnIndex);
logger.error("留存用户载入:retention={},columnMap={}",retention,columnMap);
if(null!=columnMap && null!=retention){
columnMap.put(columnIndex, count+retention);
}
dataMap.put(key, columnMap);
}
}
logger.error("留存用户加载数据:dataMap={}",JSON.toJSONString(dataMap));
} catch (Exception e) {
logger.error("留存用户加载数据异常:dataMap={}",JSON.toJSONString(dataMap),e);
}
return dataMap;
}
@Override
public Map freshness(SearchObject searchObj){
Map resultMap = new HashMap();
try {
Map dataMap = new LinkedHashMap();
String timeType = searchObj.getTimeType();
Integer from = searchObj.getFrom();
Integer to = searchObj.getTo();
String filterList = this.searchComponent.initFilterList(searchObj);
//2、获取用户新鲜度
List rs = this.retentionFreshnessDailyTabService.queryFreshnessRows(searchObj, filterList);
for(RowVo row : rs){
String key = row.getRowKey();//登录日期
String rowKey = row.getRowKey();
String xzrq = rowKey.substring(rowKey.lastIndexOf("#")+1);
key = key.substring(0,key.indexOf("#",0));
key = CommonUtils.handlerTime(key, timeType);
xzrq = CommonUtils.handlerTime(xzrq, timeType);//新增日期
List columns = row.getColumns();
Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count")));
if(dataMap.containsKey(key)){
RetentionFreshnessVo freshnessVo = dataMap.get(key);
int orig = freshnessVo.getTotal();
freshnessVo.setTotal(orig + count);
int duration = RetentionHandler.getColumnIndexForFreshness(key, xzrq,to);
if(duration groupMap = freshnessVo.getGroupMap();
groupMap.put(duration, count + groupMap.get(duration));
dataMap.put(key, freshnessVo);
}else{
RetentionFreshnessVo freshnessVo = new RetentionFreshnessVo();
Map groupMap = new LinkedHashMap();
for(int d=to;d>=from;d--){
groupMap.put(d, 0);
}
freshnessVo.setGroupMap(groupMap);
dataMap.put(key, freshnessVo);
}
}
logger.error("用户新鲜度加载数据:dataMap={}",JSON.toJSONString(dataMap));
resultMap.put("dataMap", dataMap);
} catch (Exception e) {
logger.error("用户新鲜度加载数据异常:dataMap={}",JSON.toJSONString(resultMap),e);
}
return resultMap;
}
/**
* 获取用户活跃度数据
*
* @param searchObj
* @return
*/
@Override
public Map> getActiveDegree(SearchObject searchObj) throws ParseException {
Map> map=new LinkedHashMap>();
//20161113#M_android#600221#360shoujizhushou#2
String filterList = ".*";
if(!StringUtils.isEmpty(searchObj.getAppType())){
filterList += "#"+searchObj.getAppType();
}else{
filterList += "#.*";
}
if(!StringUtils.isEmpty(searchObj.getAppVersion())){
filterList += "#"+searchObj.getAppVersion();
}else{
filterList += "#.*";
}
if(!StringUtils.isEmpty(searchObj.getAppChannel())){
filterList += "#"+searchObj.getAppChannel()+".*";
}else{
filterList += "#.*";
}
//20160828#M_android#600171#SGCM 01#1
searchObj.setTimeType(Common.DATATYPE.DAY);
//结束时间默认加一天
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateFormat.parse(searchObj.getEndTime()));
calendar.add(Calendar.DATE, 1);
searchObj.setEndTime(dateFormat.format(calendar.getTime()));
List activeList = activeDegreeTabService.getActiveDegree(searchObj, filterList);
for(RowVo r : activeList){
String key = r.getRowKey();
Integer days=Integer.valueOf(key.substring(key.lastIndexOf("#") + 1));
key = key.substring(0, key.indexOf("#", 0));
key = CommonUtils.handlerTime(key, searchObj.getTimeType());
List columns = r.getColumns();
Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count")));
if(map.containsKey(key)){
if(map.get(key).containsKey(days)) {
map.get(key).put(days, map.get(key).get(days)+count);
}else{
map.get(key).put(days,count);
}
}else{
Map tempMap=new HashMap();
tempMap.put(days,count);
map.put(key,tempMap);
}
}
return map;
}
/**
* 获取用户活跃度数据
*
* @param searchObj
* @return
*/
@Override
public Map> getActive15Degree(SearchObject searchObj) throws ParseException {
Map> map=new LinkedHashMap>();
//20161113#M_android#600221#360shoujizhushou#2
String filterList = ".*";
if(!StringUtils.isEmpty(searchObj.getAppType())){
filterList += "#"+searchObj.getAppType();
}else{
filterList += "#.*";
}
if(!StringUtils.isEmpty(searchObj.getAppVersion())){
filterList += "#"+searchObj.getAppVersion();
}else{
filterList += "#.*";
}
if(!StringUtils.isEmpty(searchObj.getAppChannel())){
filterList += "#"+searchObj.getAppChannel()+".*";
}else{
filterList += "#.*";
}
//20160828#M_android#600171#SGCM 01#1
searchObj.setTimeType(Common.DATATYPE.DAY);
//结束时间默认加一天
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateFormat.parse(searchObj.getEndTime()));
calendar.add(Calendar.DATE,1);
searchObj.setEndTime(dateFormat.format(calendar.getTime()));
List activeList = active15DegreeTabService.getActiveDegree(searchObj, filterList);
for(RowVo r : activeList){
String key = r.getRowKey();
key = key.substring(0, key.indexOf("#", 0));
key = CommonUtils.handlerTime(key, searchObj.getTimeType());
Integer days=Integer.valueOf(key.substring(key.lastIndexOf("#") + 1));
List columns = r.getColumns();
Integer count = Integer.valueOf(getValue(columns,Bytes.toBytes("statistical"), Bytes.toBytes("count")));
if(map.containsKey(key)){
if(map.get(key).containsKey(days)) {
map.get(key).put(days, map.get(key).get(days)+count);
}else{
map.get(key).put(days,count);
}
}else{
Map tempMap=new HashMap();
tempMap.put(days,count);
map.put(key,tempMap);
}
}
return map;
}
/**
* 留存用户数据处理类
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-30 上午9:54:17
*/
public static class RetentionHandler{
/**
* 根据时间类型(日|周|月)获取对应列头对应的索引
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-11-29 下午3:48:35
* @param timeType 时间类型
* @param days 差异天数
* @return
*/
public static int getColumnIndexForRetention(String timeType,int days){
int columnIndex = 0;
if(days==0){
return -1;
}
if(Common.DATATYPE.DAY.equals(timeType)){
if(days==0){
return -1;
}
if(days<7){
columnIndex = ReportTitle.DAILY[days-1];
}else if(days==14){
columnIndex = ReportTitle.DAILY[7];
}else if(days==30){
columnIndex = ReportTitle.DAILY[8];
}
}
if(Common.DATATYPE.WEEK.equals(timeType)){
int week = (days/7)-1;
if(week<0){
return -1;
}
columnIndex = ReportTitle.WEEK[week];
}
if(Common.DATATYPE.MONTH.equals(timeType)){
int month = (days/30)-1;
if(month<0){
return -1;
}
columnIndex = ReportTitle.MONTH[month];
}
return columnIndex;
}
/**
* 用户新鲜度|获取登录日期与新增日期的差异天数
* @author 石冬冬-Heil Hilter([email protected])
* @date 2016-12-1 下午3:01:57
* @param dlrq 登录日期
* @param xzrq 新增日期
* @return
*/
public static int getColumnIndexForFreshness(String dlrq,String xzrq,Integer to){
int duration = 0;
duration = Long.valueOf(DateFormatUtil.getTwoDateDifference(xzrq,dlrq)).intValue();
if(duration>=to){
return to;
}
return duration;
}
/*****************************************************************/
/**
* 如果是按月统计:对开始时间 和 结束时间 逻辑控制
* 开始时间如果非开始时间当月的第一天,需要重置为下个月的第一天。
* 结束时间如果非结束时间当月的第一条,需要重置为上个月的第一天。
*/
/*****************************************************************/
public static void resetSearchTimeForByMonth(boolean byMonth,SearchObject searchObj){
if(!byMonth){
return;
}
String beginTime = searchObj.getBeginTime();
String endTime = searchObj.getEndTime();
if(!StringUtils.isEmpty(beginTime)){
Calendar calendar = Calendar.getInstance();
calendar.setTime(DateFormatUtil.convertToDate(beginTime,DateFormatUtil.FORMAT_DATE_DISPLAY));
int today = calendar.get(Calendar.DAY_OF_MONTH);
if(today!=1){
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
String newTime = DateFormatUtil.convertDateToString(calendar.getTime(), DateFormatUtil.FORMAT_DATE_DISPLAY);
searchObj.setBeginTime(newTime);
}
}
if(!StringUtils.isEmpty(endTime)){
Calendar calendar = Calendar.getInstance();
calendar.setTime(DateFormatUtil.convertToDate(endTime,DateFormatUtil.FORMAT_DATE_DISPLAY));
int today = calendar.get(Calendar.DAY_OF_MONTH);
boolean reset = false;
//下面有些情况却要确认。。。。
if(today!=1){
calendar.add(Calendar.MONTH, -1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
reset = true;
}else{
int month = calendar.get(Calendar.MONTH);
Calendar nowCalendar = Calendar.getInstance();
int currentMonth = nowCalendar.get(Calendar.MONTH);
//非本月第一天时,
if(month==currentMonth){
calendar.add(Calendar.MONTH, -1);
reset = true;
}
}
if(reset){
String newTime = DateFormatUtil.convertDateToString(calendar.getTime(), DateFormatUtil.FORMAT_DATE_DISPLAY);
searchObj.setEndTime(newTime);
}
}
}
public static void main(String[] args) {
//System.out.println(getColumnIndex(Common.DATATYPE.WEEK, 7));
System.out.println(RetentionAnalysisService.ReportTitle.MONTH_COLS);
}
}
}