text: /**
   * 设备/用户忠诚度（粘性）统计模型
   */
  const BaseMod = require('./base')
  const Platform = require('./platform')
  const Channel = require('./channel')
  const Version = require('./version')
  const SessionLog = require('./sessionLog')
  const UserSessionLog = require('./userSessionLog')
  const {
  	DateTime
  } = require('../lib')
  module.exports = class Loyalty extends BaseMod {
  	constructor() {
  		super()
  		this.tableName = 'loyalty-result'
  		this.platforms = []
  		this.channels = []
  		this.versions = []
  	}
  
  	/**
  	 * 设备/用户忠诚度（粘性）统计
  	 * @param {String} type 统计类型 hour：实时统计 day：按天统计，week：按周统计 month：按月统计
  	 * @param {Date|Time} date 指定日期或时间戳
  	 * @param {Boolean} reset 是否重置，为ture时会重置该批次数据
  	 */
  	async stat(type, date, reset) {
  		const allowedType = ['day']
  		if (!allowedType.includes(type)) {
  			return {
  				code: 1002,
  				msg: 'This type is not allowed'
  			}
  		}
  
  		this.fillType = type
  		const dateTime = new DateTime()
  		const dateDimension = dateTime.getTimeDimensionByType(type, -1, date)
  		this.startTime = dateDimension.startTime
  		this.endTime = dateDimension.endTime
  
  		if (this.debug) {
  			console.log('this time', dateTime.getTime())
  			console.log('dimension time', this.startTime + '--' + this.endTime)
  		}
  
  		// 查看当前时间段日志是否已存在,防止重复生成
  		if (!reset) {
  			const checkRes = await this.getCollection(this.tableName).where({
  				start_time: this.startTime,
  				end_time: this.endTime
  			}).get()
  			if (checkRes.data.length > 0) {
  				console.log('loyalty log have existed')
  				return {
  					code: 1003,
  					msg: 'This log have existed'
  				}
  			}
  		} else {
  			const delRes = await this.delete(this.tableName, {
  				start_time: this.startTime,
  				end_time: this.endTime
  			})
  			console.log('delete old data result:', JSON.stringify(delRes))
  		}
  
  		// 数据获取
  		this.sessionLog = new SessionLog()
  		const statRes = await this.aggregate(this.sessionLog.tableName, {
  			project: {
  				appid: 1,
  				version: 1,
  				platform: 1,
  				channel: 1,
  				page_count: 1,
  				duration: 1,
  				create_time: 1
  			},
  			match: {
  				create_time: {
  					$gte: this.startTime,
  					$lte: this.endTime
  				}
  			},
  			group: {
  				_id: {
  					appid: '$appid',
  					version: '$version',
  					platform: '$platform',
  					channel: '$channel'
  				},
  				page_count_sum: {
  					$sum: '$page_count'
  				},
  				duration_sum: {
  					$sum: '$duration'
  				}
  			},
  			sort: {
  				page_count_sum: 1,
  				duration_sum: 1
  			},
  			getAll: true
  		})
  
  		let res = {
  			code: 0,
  			msg: 'success'
  		}
  		if (this.debug) {
  			console.log('statRes', JSON.stringify(statRes))
  		}
  		if (statRes.data.length > 0) {
  			this.fillData = []
  			for (const i in statRes.data) {
  				await this.fill(statRes.data[i])
  			}
  
  			if (this.fillData.length > 0) {
  				res = await this.batchInsert(this.tableName, this.fillData)
  			}
  		}
  		return res
  	}
  
  	/**
  	 * 设备/用户忠诚度（粘性）数据填充
  	 * @param {Object} data 数据集合
  	 */
  	async fill(data) {
  		// 平台信息
  		let platformInfo = null
  		if (this.platforms && this.platforms[data._id.platform]) {
  			platformInfo = this.platforms[data._id.platform]
  		} else {
  			const platform = new Platform()
  			platformInfo = await platform.getPlatformAndCreate(data._id.platform, null)
  			if (!platformInfo || platformInfo.length === 0) {
  				platformInfo._id = ''
  			}
  			this.platforms[data._id.platform] = platformInfo
  			if (this.debug) {
  				console.log('platformInfo', JSON.stringify(platformInfo))
  			}
  		}
  
  		// 渠道信息
  		let channelInfo = null
  		const channelKey = data._id.appid + '_' + platformInfo._id + '_' + data._id.channel
  		if (this.channels && this.channels[channelKey]) {
  			channelInfo = this.channels[channelKey]
  		} else {
  			const channel = new Channel()
  			channelInfo = await channel.getChannelAndCreate(data._id.appid, platformInfo._id, data._id.channel)
  			if (!channelInfo || channelInfo.length === 0) {
  				channelInfo._id = ''
  			}
  			this.channels[channelKey] = channelInfo
  			if (this.debug) {
  				console.log('channelInfo', JSON.stringify(channelInfo))
  			}
  		}
  
  		// 版本信息
  		let versionInfo = null
  		const versionKey = data._id.appid + '_' + platformInfo._id + '_' + data._id.version
  		if (this.versions && this.versions[versionKey]) {
  			versionInfo = this.versions[versionKey]
  		} else {
  			const version = new Version()
  			versionInfo = await version.getVersionAndCreate(data._id.appid, platformInfo._id, data._id.version)
  			if (!versionInfo || versionInfo.length === 0) {
  				versionInfo._id = ''
  			}
  			this.versions[versionKey] = versionInfo
  			if (this.debug) {
  				console.log('versionInfo', JSON.stringify(versionInfo))
  			}
  		}
  
  		// 访问深度-用户数统计和访问次数
  		const pageMark = [1, 2, 3, 4, [5, 10], [10]]
  
  		const matchCondition = Object.assign(data._id, {
  			create_time: {
  				$gte: this.startTime,
  				$lte: this.endTime
  			}
  		})
  
  		const visitDepthData = {
  			visit_devices: {},
  			visit_users: {},
  			visit_times: {}
  		}
  		
  		const userSessionLog = new UserSessionLog()
  		//根据各访问页面数区间统计
  		for (const pi in pageMark) {
  			let pageMarkCondition = {
  				page_count: pageMark[pi]
  			}
  
  			if (Array.isArray(pageMark[pi])) {
  				if (pageMark[pi].length === 2) {
  					pageMarkCondition = {
  						page_count: {
  							$gte: pageMark[pi][0],
  							$lte: pageMark[pi][1]
  						}
  					}
  				} else {
  					pageMarkCondition = {
  						page_count: {
  							$gt: pageMark[pi][0]
  						}
  					}
  				}
  			}
  
  			// 访问次数(会话次数)统计
  			const searchCondition = {
  				...matchCondition,
  				...pageMarkCondition
  			}
  			const vistRes = await this.aggregate(this.sessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					page_count: 1,
  					create_time: 1
  				},
  				match: searchCondition,
  				group: {
  					_id: {},
  					total_visits: {
  						$sum: 1
  					}
  				}
  			})
  
  			if (this.debug) {
  				console.log('vistResCondtion', JSON.stringify(searchCondition))
  				console.log('vistRes', JSON.stringify(vistRes))
  			}
  			let vistCount = 0
  			if (vistRes.data.length > 0) {
  				vistCount = vistRes.data[0].total_visits
  			}
  			
  			// 设备数统计
  			const deviceRes = await this.aggregate(this.sessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					page_count: 1,
  					create_time: 1,
  					device_id: 1
  				},
  				match: searchCondition,
  				group: [{
  					_id: {
  						device_id: '$device_id'
  					}
  				}, {
  					_id: {},
  					total_devices: {
  						$sum: 1
  					}
  				}]
  			})
  			
  			if (this.debug) {
  				console.log('searchCondition', JSON.stringify(searchCondition))
  				console.log('deviceRes', JSON.stringify(deviceRes))
  			}
  			
  			let deviceCount = 0
  			if (deviceRes.data.length > 0) {
  				deviceCount = deviceRes.data[0].total_devices
  			}
  
  			// 用户数统计
  			const userRes = await this.aggregate(userSessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					page_count: 1,
  					create_time: 1,
  					uid: 1
  				},
  				match: searchCondition,
  				group: [{
  					_id: {
  						uid: '$uid'
  					}
  				}, {
  					_id: {},
  					total_users: {
  						$sum: 1
  					}
  				}]
  			})
  
  			if (this.debug) {
  				console.log('userResCondtion', JSON.stringify(searchCondition))
  				console.log('userRes', JSON.stringify(userRes))
  			}
  
  			let userCount = 0
  			if (userRes.data.length > 0) {
  				userCount = userRes.data[0].total_users
  			}
  
  			const pageKey = 'p_' + (Array.isArray(pageMark[pi]) ? pageMark[pi][0] : pageMark[pi])
  			visitDepthData.visit_devices[pageKey] = deviceCount
  			visitDepthData.visit_users[pageKey] = userCount
  			visitDepthData.visit_times[pageKey] = vistCount
  		}
  
  		// 访问时长-用户数统计和访问次数
  		const durationMark = [
  			[0, 2],
  			[3, 5],
  			[6, 10],
  			[11, 20],
  			[21, 30],
  			[31, 50],
  			[51, 100],
  			[100]
  		]
  		const durationData = {
  			visit_devices: {},
  			visit_users: {},
  			visit_times: {}
  		}
  		//根据各访问时长区间统计
  		for (const di in durationMark) {
  			let durationMarkCondition = {
  				duration: durationMark[di]
  			}
  
  			if (Array.isArray(durationMark[di])) {
  				if (durationMark[di].length === 2) {
  					durationMarkCondition = {
  						duration: {
  							$gte: durationMark[di][0],
  							$lte: durationMark[di][1]
  						}
  					}
  				} else {
  					durationMarkCondition = {
  						duration: {
  							$gt: durationMark[di][0]
  						}
  					}
  				}
  			}
  
  			// 访问次数(会话次数)统计
  			const searchCondition = {
  				...matchCondition,
  				...durationMarkCondition
  			}
  			if (this.debug) {
  				console.log('searchCondition', JSON.stringify(searchCondition))
  			}
  			const vistRes = await this.aggregate(this.sessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					duration: 1,
  					create_time: 1
  				},
  				match: searchCondition,
  				group: {
  					_id: {},
  					total_visits: {
  						$sum: 1
  					}
  				}
  			})
  
  			if (this.debug) {
  				console.log('vistRes', JSON.stringify(vistRes))
  			}
  			let vistCount = 0
  			if (vistRes.data.length > 0) {
  				vistCount = vistRes.data[0].total_visits
  			}
  			
  			// 设备数统计
  			const deviceRes = await this.aggregate(this.sessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					device_id: 1,
  					duration: 1,
  					create_time: 1
  				},
  				match: searchCondition,
  				group: [{
  					_id: {
  						device_id: '$device_id'
  					}
  				}, {
  					_id: {},
  					total_devices: {
  						$sum: 1
  					}
  				}]
  			})
  			
  			if (this.debug) {
  				console.log('userRes', JSON.stringify(deviceRes))
  			}
  			
  			let deviceCount = 0
  			if (deviceRes.data.length > 0) {
  				deviceCount = deviceRes.data[0].total_devices
  			}
  			
  			// 用户数统计
  			const userRes = await this.aggregate(userSessionLog.tableName, {
  				project: {
  					appid: 1,
  					version: 1,
  					platform: 1,
  					channel: 1,
  					uid: 1,
  					duration: 1,
  					create_time: 1
  				},
  				match: searchCondition,
  				group: [{
  					_id: {
  						uid: '$uid'
  					}
  				}, {
  					_id: {},
  					total_users: {
  						$sum: 1
  					}
  				}]
  			})
  
  			if (this.debug) {
  				console.log('userRes', JSON.stringify(userRes))
  			}
  
  			let userCount = 0
  			if (userRes.data.length > 0) {
  				userCount = userRes.data[0].total_users
  			}
  
  			const pageKey = 's_' + (Array.isArray(durationMark[di]) ? durationMark[di][0] : durationMark[di])
  			durationData.visit_devices[pageKey] = deviceCount
  			durationData.visit_users[pageKey] = userCount
  			durationData.visit_times[pageKey] = vistCount
  		}
  
  		// 数据填充
  		const datetime = new DateTime()
  		const insertParams = {
  			appid: data._id.appid,
  			platform_id: platformInfo._id,
  			channel_id: channelInfo._id,
  			version_id: versionInfo._id,
  			visit_depth_data: visitDepthData,
  			duration_data: durationData,
  			stat_date: datetime.getDate('Ymd', this.startTime),
  			start_time: this.startTime,
  			end_time: this.endTime
  		}
  
  		this.fillData.push(insertParams)
  		return insertParams
  	}
  }
  