toxic

备忘录

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
<?php
/**
 * Created by PhpStorm.
 * User: buhuan
 * Date: 14-4-18
 * Time: 上午10:14
 * 统计进程
 * 广告留存
 * 公式
 * flag_id = channel_id*10000 + domain_id
 */

namespace Application\Process;


use Application\Core\ProcessBase;
use Application\Interfaces\IProcess;
use Application\Core\Pusher;
use \Ev;
use \EvTimer;

class Statistics extends ProcessBase implements IProcess{
    /**
     * 子进程数目序号 => 执行的函数
     */
    private $procs = array(
           0 => 'userOnline_daemon_handler',
           1 => 'Retention_daemon_handler',
           2 => 'AdRetention_daemon_handler'
    );

    /**
     * 用户在线每5分钟执行一次 并且是在5的整数倍分钟时间点执行
     */
    const USER_ONLINE_DIFF = 5;//分钟

    /**
     * 留存率每60分钟执行一次
     */
    const RETENTION_DIFF = 60;//分钟

    /**
     * 广告留存率每60分钟执行一次
     */
    const AD_RETENTION_DIFF = 60;//分钟

    /**
     * 在凌晨0点更新前N天的留存并写入前一天的留存
     */
    const RETENTION_PUSH_HOUR  =  0;//整点

    /**
     * 在凌晨0点更新前N天的广告留存并写入前一天的广告留存
     */
    const AD_RETENTION_PUSH_HOUR = 1;//整点

    private  $pids = array();

    private  $excutable = NULL;



    function onPreInit()
    {
        parent::onPreInit(); // TODO: Change the autogenerated stub
        foreach($this->procs as $function_name){
            $this->excutable[$function_name] = TRUE;
        }
    }

    /**
     * 开始执行命令。
     */
    function execute()
    {
        // TODO: Implement execute() method.
        //创建子进程
        $num = count($this->procs);
        $pid = pcntl_fork();
        for($i =0 ; $i < $num ; $i++){
              if($pid == -1){
                  print "不能创建子进程".chr(10);
              }else if($pid){
                  //父进程
                  print '子进程号:'.$pid.chr(10);
                  $this->pids[$i] = $pid;//存入子进程序号和进程号
                  $pid = pcntl_fork();
              }else{
                  if($this->excutable[$this->procs[$i]])
                        $this->daemon_dispatch($i);
              }
        }
    }

    /**
     * @param $i 进程序号
     */
    private function daemon_dispatch($i){
        switch($i){
            case 0:         $timediff = self::USER_ONLINE_DIFF * 60;
                            //确认分钟数为5的整数倍的时候开始执行
                            $minutes = intval(date('i'));
                            $countdown = (5 - $minutes%5)*60;//倒计时开始毫秒数
                            break;

            case 1:          //Retention
                            $timediff = self::RETENTION_DIFF * 60;
                            $countdown = 1;
                            break;

            case 2:         //ADRETENTION
                            $timediff = self::AD_RETENTION_DIFF * 60;
                            $countdown = 10;
                            break;
        }
        print  '启动进程['.$this->pids[$i].']'.$this->procs[$i].chr(10);
        $timer = new EvTimer($countdown,$timediff,array($this,$this->procs[$i]));
        $this->excutable[$this->procs[$i]] = FALSE;
        Ev::run();
    }

    /**
     * 释放资源。
     */
    function dispose()
    {
        // TODO: Implement dispose() method.
    }


    function userOnline_daemon_handler(){
        print "执行用户在线...".chr(10);
        $statistics_date = strtotime(date('Y-m-d'));
        $statistics_time = time();

        //查找当前在线的玩家数量
        $sql = "SELECT count(user_id) as num FROM user_online";
        $d = $this->scope->db->fetch($sql);
        $num = $d['num'];

        $data = array(
            'statistics_date' => $statistics_date,
            'statistics_time' => $statistics_time,
            'online' => $num
        );

        Pusher::instance($this->scope)->doPushStat(107,$data);
    }


    function Retention_daemon_handler(){
        $hour = intval(date('H'));
        print "执行留存率...".chr(10);
        if($hour == SELF::RETENTION_PUSH_HOUR){//如果是$push_hour点 则开始发送数据
            $time = time();
            $current_time = $time-24*60*60;//计算的基准时间
            $start_datetime = date('Y-m-d',$current_time).' 00:00:00';
            $end_datetime = date('Y-m-d',$current_time).' 23:59:59';
            //查询当前前一天的注册人数
            $sql = "SELECT COUNT(user_id) as reg_num FROM user_info_ext WHERE user_active_time > '$start_datetime' AND user_active_time < '$end_datetime'";
            $d = $this->scope->db->fetch($sql);
            $reg_num = $d['reg_num'];

            //查询当前前一天登录的用户
            $sql = "SELECT user_id FROM user_info_ext WHERE user_last_login_time > '$start_datetime' AND user_last_login_time < '$end_datetime' ";
            $d = $this->scope->db->fetchAll($sql);
            $login_users = $d;

            $reg_nums = array();
            $reg_nums['day1'] = $this->nDayUsers(1,$current_time);
            $reg_nums['day3'] = $this->nDayUsers(3,$current_time);
            $reg_nums['day7'] = $this->nDayUsers(7,$current_time);
            $reg_nums['day15'] = $this->nDayUsers(15,$current_time);
            $reg_nums['day30'] = $this->nDayUsers(30,$current_time);

            $data = array(
                'currentTime' => $time,
                'reg_num' => $reg_num,
                'reg_nums' => $reg_nums,
                'login_users' => $login_users
            );

            Pusher::instance($this->scope)->doPushStat(106,$data);
        }
    }

    function AdRetention_daemon_handler(){
        $hour = intval(date('H'));
        print "执行广告留存率...".chr(10);
        if($hour == SELF::AD_RETENTION_PUSH_HOUR){//如果是$push_hour点 则开始发送数据
            $time = time();
            $current_time = $time-24*60*60;//计算的基准时间
            $start_datetime = date('Y-m-d',$current_time).' 00:00:00';
            $end_datetime = date('Y-m-d',$current_time).' 23:59:59';

            //必须先知道哪些渠道ID 和 域名ID
            //查询当前前一天的注册人数集合
            $sql = "SELECT COUNT(user_id) as reg_num,flag_id FROM user_info_ext
                        WHERE flag_id <> 0 AND user_active_time > '$start_datetime' AND user_active_time < '$end_datetime'  GROUP BY flag_id";
            $d = $this->scope->db->fetchAll($sql);
            $reg_num = $d;


            //查询当前前一天登录的用户的不重复的flag_id
            $sql = "SELECT DISTINCT(flag_id) as flag_id FROM user_info_ext WHERE user_last_login_time > '$start_datetime' AND user_last_login_time < '$end_datetime'  AND flag_id <> 0";
            $flags = $this->scope->db->fetchAll($sql);

            //查询当前前一天登录的用户
            $sql = "SELECT user_id,flag_id FROM user_info_ext WHERE user_last_login_time > '$start_datetime' AND user_last_login_time < '$end_datetime'  AND flag_id <> 0";
            $d = $this->scope->db->fetchAll($sql);
            $login_users = array();
            //按channel_id,domain_id重组用户数据
            if(count($d) > 0 && count($flags) > 0){
                foreach($flags as $flag){
                    foreach($d as $user){
                        if($flag['flag_id'] == $user['flag_id']){
                            $login_users[$flag['flag_id']][] = $user['user_id'];
                        }
                    }
                }
            }
            unset($d);

            $reg_nums = array();
            $reg_nums['day1'] = $this->nDayUsers_Ad(1,$current_time);
            $reg_nums['day2'] = $this->nDayUsers_Ad(2,$current_time);
            $reg_nums['day3'] = $this->nDayUsers_Ad(3,$current_time);
            $reg_nums['day4'] = $this->nDayUsers_Ad(4,$current_time);
            $reg_nums['day5'] = $this->nDayUsers_Ad(5,$current_time);
            $reg_nums['day6'] = $this->nDayUsers_Ad(6,$current_time);
            $reg_nums['day7'] = $this->nDayUsers_Ad(7,$current_time);
            $reg_nums['day8'] = $this->nDayUsers_Ad(8,$current_time);

            $data = array(
                'currentTime' => $time,
                'reg_num' => $reg_num,
                'reg_nums' => $reg_nums,
                'login_users' => $login_users
            );

            Pusher::instance($this->scope)->doPushStat(108,$data);
        }
    }


    /**
     * @param int $n 1=1日 3=3日。。。
     * @param int $current_time 基准时间
     * @return array
     */
    protected  function nDayDate($n,$current_time){
        $diff = 24*60*60;
        $start_datetime = date('Y-m-d',$current_time-$n*$diff).' 00:00:00';
        $end_datetime = date('Y-m-d',$current_time-$n*$diff).' 23:59:59';
        $date = array();
        $date[0] = $start_datetime;
        $date[1] = $end_datetime;
        return $date;
    }


    /**
     * 得到基准日期前第n日的注册用户集合
     * @param $n
     * @param $current_time
     * @return array
     */
    protected function nDayUsers($n,$current_time){
        $dates = $this->nDayDate($n,$current_time);
        //查询次日注册用户
        $sql = "SELECT user_id FROM user_info_ext WHERE user_active_time > '{$dates[0]}' AND user_active_time < '{$dates[1]}'";
        return $this->scope->db->fetchAll($sql);
    }


    /**
     * 得到基准日期前第n日的注册用户集合
     * @param $n
     * @param $current_time
     * @return array
     */
    function nDayUsers_Ad($n,$current_time){
        $dates = $this->nDayDate($n,$current_time);

        //查询当前前一天注册的用户的不重复的flag_id
        $sql = "SELECT DISTINCT(flag_id) as flag_id FROM user_info_ext WHERE user_active_time > '{$dates[0]}' AND user_active_time < '{$dates[1]}' AND flag_id <> 0";
        $flags = $this->scope->db->fetchAll($sql);

        //查询$n日注册用户
        $sql = "SELECT user_id,flag_id FROM user_info_ext WHERE user_active_time > '{$dates[0]}' AND user_active_time < '{$dates[1]}' AND flag_id <> 0";
        $d = $this->scope->db->fetchAll($sql);
        $reg_users = array();

        if(count($d) > 0 && count($flags) > 0){
            foreach($flags as $flag){
                foreach($d as $user){
                    if($flag['flag_id'] == $user['flag_id']){
                        $reg_users[$flag['flag_id']][] = $user['user_id'];
                    }
                }
            }
        }
        usleep(100000);
        return $reg_users;
    }

} 

 

posted on 2014-04-18 14:55  toxic  阅读(247)  评论(0编辑  收藏  举报