<?php
namespace model\doctor;
/**
 * Class blood
 * @package model
 */
class blood extends \model\element
{
	public function __construct($elecfg='dt_blood')
    {
		parent::__construct($elecfg);
	}

	public function getHand($str)
    {
		if($str=='L' || $str=='l' || $str=='左' || $str=='左手'){
            return 'L';
        }else if($str=='R' || $str=='r' || $str=='右' || $str=='右手'){
            return 'R';
        }
	}
    
    /**
    * 计算脉压
    */
	public function getPulse($row)
    {
		return $row['bd_sbp']*1 - $row['bd_dbp']*1;
	}
    
    /**
    * 平均动脉压
    */
	public function getBloodMap($row)
    {
		return floor(($row['bd_sbp']*1 - $row['bd_dbp']*1) / 3 + $row['bd_dbp']*1);
	}
    
    /**
    * 取24小时记录
    */
	public function get24Hour($req)
    {
        $req['date_next'] = date('Y-m-d',strtotime("+1 day", strtotime($req['date_start'])));
        $req['tdate'] = $req['date_start'].' '.$req['time_start'].':00:00';
        $req['where_hand'] = $req['hand'] ? " AND bd_hand='".$req['hand']."'" : "";
		$sql = "SELECT STR_TO_DATE(CONCAT(bd_date,' ',bd_time,':00'), '%Y-%m-%d %H:%i:%s') AS tdate,dt_blood.*
                FROM dt_blood
                WHERE bd_uid = '{:uid}' AND bd_date>= '{:date_start}' AND bd_date<= '{:date_next}' {:where_hand}
                HAVING  tdate>= '{:tdate}' AND tdate <=DATE_ADD('{:tdate}', INTERVAL 24 HOUR)
                ORDER BY STR_TO_DATE(CONCAT(bd_date,' ',bd_time,':00'), '%Y-%m-%d %H:%i:%s')";
        $sql = qgprintf($sql,$req);
        $st = $this->db->query($sql);
        return $st->fetchAll(\PDO::FETCH_ASSOC);
	}
    
    /**
    * 统计24个小时的记录有多少个有效小时
    */
	public function count24Hour($rows)
    {
        $hours = [];
        foreach($rows as $row){
            $hours[date('H',strtotime($row['tdate']))] = 1;
        }
        return count($hours);
	}
    
    /**
    * 是否有24个小时的记录
    */
	public function isHas24Hour($rows)
    {
        return $this->count24Hour($rows) == 24;
	}

    public function list($rules = [],$where='',$page=0,$pagesize=0,$sidx='',$sord='asc',$orderby='')
    {
		$table = $this->table.'(e)';
        $fields = '*';
        $this->join = [];
		$this->joinWhere = [];
		$this->group = [];
		$objList = []; //用于回调方法中，创建的对象缓存
        $where = $this->filter2medoo($where,function(&$field,&$op,&$data){
            if(is_string($data)) $data = trim($data);
            $cfg = $this->elecfg['fields'][$field];
            if(!empty($cfg['formartSearchBegin'])){
                $cfg['formartSearchBegin']($field,$op,$data);
            }
            switch ($field) {
                case 'bd_uid':
                        $data = (new \model\user())->getAdminAuidByLike($data);
                        $op = 'eq';
                        if(empty($data)) $data = 'none';
                    break;
                default:
                    break;
            }
            
            //取其他表值
            if(!empty($cfg['linkOne'])){
                $link = $cfg['linkOne'];
                if(isset($link['search']) && !empty($link['search']['function'])){
                    $link['search']['function']($field,$op,$data,$this->join,$this->joinWhere,$this->group,$objList,$this->db);
                }else{
                    if(isset($link['myfield']) && $link['myfield']){
                        $field = $link['myfield'];
                    }
                    if(isset($cfg['list']['valuetype']) && $cfg['list']['valuetype']=='key'){
                        if(empty($data)){
                            $op = null;
                        }else{
                            $op = 'eq';
                        }
                    }else{
                        $captionField = (isset($link['captionField']) && $link['captionField']) ? $link['captionField'] : $link['caption'];
                        $w = [
                            $captionField.'['.$this->getMedooOp($op).']'=> $data
                        ];
                        $data = $this->db->select($link['table'],$link['field'],$w);
                        if(empty($data)) $data = [0];
                        $op = 'eq';
                        $data = array_unique($data);
                    }
                }
                
            }else if(!empty($cfg['linkMore'])){
				$as = 't'.$field;
				$on = ["e.".$this->key => $cfg['linkMore']['mykey_link_field']];
				if(!empty($cfg['linkMore']['AND'])){
					$on['AND'] = $cfg['linkMore']['AND'];
				}
				if(!empty($cfg['linkMore']['element'])){
				    if(!empty($data)){
    				    if(isset($cfg['list']['valuetype']) && $cfg['list']['valuetype']=='key'){
            				$linkIds = $data;
    				    }else{
            				$linkIds = makeOne(\model\element::class,$cfg['linkMore']['element'])->like($data);
    				    }
        				$op = 'eq';
        				$field = $cfg['linkMore']['field'];
        				$data = $linkIds;
				    }else{
				        $op = null;
				    }
				}
				if(!is_null($op)){
				    $this->join['[>]'.$cfg['linkMore']['table'].'('.$as.')'] = $on;
				}
            }
            //其他修正
            if(!empty($cfg['list']['searchField'])){
                $field = $cfg['list']['searchField'];
            }
            if(!empty($cfg['formartSearch'])){
                $cfg['formartSearch']($field,$op,$data);
            }
        });
        if(!is_array($where)) $where =[];
        
		if(!empty($rules)){
		    if(!empty($rules['keys'])){
		        $where[$this->key] = $rules['keys'];
		        unset($rules['keys']);
		    }
			foreach($rules as $field=>$value){
			    if(isset($this->elecfg['rules'][$field])){
			        //自定义规则查询
			        $this->elecfg['rules'][$field]($rules,$field,$value,$this->join,$this->joinWhere,$this->group);
			    }else{
    				$cfg = $this->elecfg['fields'][$field];
    				if(!empty($cfg['linkMore'])){
    					$as = 't'.$field;
    					$on = ["e.".$this->key => $cfg['linkMore']['mykey_link_field']];
    					if(!empty($cfg['linkMore']['AND'])){
    						$on['AND'] = $cfg['linkMore']['AND'];
    					}
    					$this->join['[>]'.$cfg['linkMore']['table'].'('.$as.')'] = $on;
    					$this->joinWhere[$as.'.'.$cfg['linkMore']['field']] = $value;
    					unset($rules[$field]);
    				}
			    }
			}
			$where = array_merge($rules,$where);
		}
		
		//check1
		if(!empty($this->elecfg['url']['check1']['checkField'])){
		    if(\p::has($this->elecfg['pwcode'],'check1')){
		        ;
		    }else{
		        $where['OR #user'] = [
		            $this->elecfg['url']['check1']['checkField']=> 1,
		            $this->elecfg['url']['check1']['userField']=> getOpuser(),
		        ];
		    }
		}
	
		if(!empty($this->joinWhere)){
			$where = array_merge($where, $this->joinWhere);
		}

		if(!empty($this->group)){
			$where = array_merge($where, $this->group);
		}

		//自定义排序
        if($sidx!='' && isset($this->elecfg['fields'][$sidx]['linkOne']) && isset($this->elecfg['fields'][$sidx]['linkOne']['order'])){
    		$sidx = $this->elecfg['fields'][$sidx]['linkOne']['order']['function']($this->join,$this->joinWhere,$this->group,$objList,$this->db);
        }
        
		$where = $this->listWhere($where,$page,$pagesize,$sidx,$sord,$orderby);
		if($this->elecfg['where']){
			$where = array_merge($this->elecfg['where'],$where);
		}

		if($page>0 && $pagesize>0){
            if(empty($this->join)){
                $pages = $this->paging($table,$where,$page,$pagesize);
            }else{
                $pages = $this->paging($table,$this->join,'1',$where,$page,$pagesize);
            }
			$where["LIMIT"] = [$pages['limit'],$pagesize];
		}
        if(empty($this->join)){
            $rows = $this->db->select($table,$fields,$where);
        }else{
            $rows = $this->db->select($table,$this->join,$fields,$where);
        }
		//dd($this->db->last());
        if(!empty($rows)) foreach($rows as $k=>&$row){
            $row = $this->getRowInfo($row);
        }
		$data = [
			'page'=> $page,
			'total'=> $pages['total'],
			'records' => $pages['records'],
			'rows' => $rows
		];
		return $data;        
    }
    
    //计算数组key是否连续，如果不连续则将连续的分割成不同数组， 白黑白
    function explodeArray($arr) {
        $keys = array_keys($arr);
        $count = count($keys);
        $diffKeyPos = 0;
        for($i=1;$i<$count;$i++){
            if($keys[$i]-1 != $keys[$i-1]){
                $diffKeyPos = $keys[$i];
            }
        }
        $newArr = [];
        if($diffKeyPos!=0){
            foreach($arr as $k=>$v){
                if($k<$diffKeyPos){
                    $newArr[0][$k] = $v;
                }else{
                    $newArr[1][$k] = $v;
                }
            }
        }else{
            $newArr[0] = $arr;
        }
        return $newArr;
    }    
    
    //计算标准差
    function calculateStandardDeviation($data) {
        // 计算均值
        $mean = array_sum($data) / count($data);
    
        // 计算差的平方
        $differencesSquared = array_map(function($x) use ($mean) {
            return pow($x - $mean, 2);
        }, $data);
    
        // 计算方差
        $variance = array_sum($differencesSquared) / count($data);
    
        // 计算标准差
        $standardDeviation = sqrt($variance);
    
        return $standardDeviation;
    }    

    // 计算SBP平均真实变异性
    function calculateMeanRealVariability($list) {
        $data = $this->explodeArray($list); //分割不连续的值为多个集,(白黑白)
        $mrvArr = [];
        foreach($data as $k=>$arr){
            if(count($arr)>3){ //每个集需有3个以上的记录
                $diff = [];
                $keys = array_keys($arr);
                $count = count($keys);
                for($i=1;$i<$count;$i++){ //从第2个单元开始
                    $diff[] = abs($arr[$keys[$i]] - $arr[$keys[$i-1]]); //求与前一个差值的绝对值
                }
                $mrvArr[$k] = array_sum($diff) / (count($diff)-1); //差值求和 除以 差值的减一后的总数
            }
        }
        return @round(array_sum($mrvArr) / count($mrvArr),2); //多个集求平均，并四舍五入保留2位小数
    } 


    // 计算变异系数
    function calculateCoefficientOfVariation($data) {
        // 计算均值
        $mean = array_sum($data) / count($data);
        
        // 计算标准差
        $differencesSquared = array_map(function($x) use ($mean) {
            return pow($x - $mean, 2);
        }, $data);
        $variance = array_sum($differencesSquared) / count($data);
        $standardDeviation = sqrt($variance);
    
        // 计算变异系数
        $coefficientOfVariation = ($standardDeviation / $mean) * 100;
        return $coefficientOfVariation;
    }  
    
    //计算收缩压与舒张压的近似回归斜率
    function slope($sbpArr,$dbpArr) {
        // 计算均值
        $mean_sbp = array_sum($sbpArr) / count($sbpArr);
        $mean_dbp = array_sum($dbpArr) / count($dbpArr);
        
        // 计算斜率
        $numerator = 0;
        $denominator = 0;
        
        for ($i = 0; $i < count($sbpArr); $i++) {
            $numerator += ($sbpArr[$i] - $mean_sbp) * ($dbpArr[$i] - $mean_dbp);
            $denominator += pow($sbpArr[$i] - $mean_sbp, 2);
        }
        $slope = $numerator / $denominator; 
        return $slope;
    }
    
    //摘要统计
    function sumInfo($rows) {
        if(empty($rows)) {return [];};
		$sumArr = [];
		$sumArr['count'] = count($rows);
		foreach($rows as $k=>$row){
		    $time = date('H:i',strtotime('2000-01-01 '.$row['bd_time'].':00'));
		    $sbp = $row['bd_sbp']*1;
		    $dbp = $row['bd_dbp']*1;
		    $heart = $row['bd_heart_rate']*1;
		    $pulse = $sbp - $dbp;
		    $map = floor(($sbp - $dbp) / 3 + $dbp);
		    $err = $row['err'];
		    //全天
		    if(!isset($sumArr['sbp'])){
		        $sumArr['sbp']['min']['value'] = $sbp;
		        $sumArr['sbp']['max']['value'] = $sbp;
		        $sumArr['sbp']['min']['time'] = $time;
		        $sumArr['sbp']['max']['time'] = $time;
		    }
		    if(!isset($sumArr['dbp'])){
		        $sumArr['dbp']['min']['value'] = $dbp;
		        $sumArr['dbp']['max']['value'] = $dbp;
		        $sumArr['dbp']['min']['time'] = $time;
		        $sumArr['dbp']['max']['time'] = $time;
		    }
		    if(!isset($sumArr['heart'])){
		        $sumArr['heart']['min']['value'] = $heart;
		        $sumArr['heart']['max']['value'] = $heart;
		        $sumArr['heart']['min']['time'] = $time;
		        $sumArr['heart']['max']['time'] = $time;
		    }
		    if(!isset($sumArr['pulse'])){
		        $sumArr['pulse']['min']['value'] = $pulse;
		        $sumArr['pulse']['max']['value'] = $pulse;
		        $sumArr['pulse']['min']['time'] = $time;
		        $sumArr['pulse']['max']['time'] = $time;
		    }
		    if(!isset($sumArr['map'])){
		        $sumArr['map']['min']['value'] = $map;
		        $sumArr['map']['max']['value'] = $map;
		        $sumArr['map']['min']['time'] = $time;
		        $sumArr['map']['max']['time'] = $time;
		    }
		    if($sbp < $sumArr['sbp']['min']['value']){
    		    $sumArr['sbp']['min']['value'] = $sbp;
		        $sumArr['sbp']['min']['time'] = $time;
		    }
		    if($sbp > $sumArr['sbp']['max']['value']){
    		    $sumArr['sbp']['max']['value'] = $sbp;
		        $sumArr['sbp']['max']['time'] = $time;
		    }
		    if($dbp < $sumArr['dbp']['min']['value']){
    		    $sumArr['dbp']['min']['value'] = $dbp;
		        $sumArr['dbp']['min']['time'] = $time;
		    }
		    if($dbp > $sumArr['dbp']['max']['value']){
    		    $sumArr['dbp']['max']['value'] = $dbp;
		        $sumArr['dbp']['max']['time'] = $time;
		    }
		    if($heart < $sumArr['heart']['min']['value']){
    		    $sumArr['heart']['min']['value'] = $heart;
		        $sumArr['heart']['min']['time'] = $time;
		    }
		    if($heart > $sumArr['heart']['max']['value']){
    		    $sumArr['heart']['max']['value'] = $heart;
		        $sumArr['heart']['max']['time'] = $time;
		    }
		    if($pulse < $sumArr['pulse']['min']['value']){
    		    $sumArr['pulse']['min']['value'] = $pulse;
		        $sumArr['pulse']['min']['time'] = $time;
		    }
		    if($pulse > $sumArr['pulse']['max']['value']){
    		    $sumArr['pulse']['max']['value'] = $pulse;
		        $sumArr['pulse']['max']['time'] = $time;
		    }
		    if($map < $sumArr['map']['min']['value']){
    		    $sumArr['map']['min']['value'] = $map;
		        $sumArr['map']['min']['time'] = $time;
		    }
		    if($map > $sumArr['map']['max']['value']){
    		    $sumArr['map']['max']['value'] = $map;
		        $sumArr['map']['max']['time'] = $time;
		    }
		    //集
		    $sumArr['sun'][$k] = $row['sun'];
		    $sumArr['sbp']['list'][$k] = $sbp;
		    $sumArr['dbp']['list'][$k] = $dbp;
		    $sumArr['heart']['list'][$k] = $heart;
		    $sumArr['pulse']['list'][$k] = $pulse;
		    $sumArr['map']['list'][$k] = $map;
		    
		    if($err['sbp']){
		        $sumArr['sbp']['err']['count']++;
		    }
		    if($err['dbp']){
		        $sumArr['dbp']['err']['count']++;
		    }
		    if($err['heart']){
		        $sumArr['heart']['err']['count']++;
		    }
		    if($err['map']){
		        $sumArr['map']['err']['count']++;
		    }
		}
		//平均值
		$sumArr['sbp']['average'] = round(array_sum($sumArr['sbp']['list']) / count($sumArr['sbp']['list']));
		$sumArr['dbp']['average'] = round(array_sum($sumArr['dbp']['list']) / count($sumArr['dbp']['list']));
		$sumArr['heart']['average'] = round(array_sum($sumArr['heart']['list']) / count($sumArr['heart']['list']));
		$sumArr['pulse']['average'] = round(array_sum($sumArr['pulse']['list']) / count($sumArr['pulse']['list']));
		$sumArr['map']['average'] = round(array_sum($sumArr['map']['list']) / count($sumArr['map']['list']));
		
		if($sumArr['count']>3){
    		//标准差
    		$sumArr['sbp']['standardDeviation'] = round($this->calculateStandardDeviation($sumArr['sbp']['list']));
    		$sumArr['dbp']['standardDeviation'] = round($this->calculateStandardDeviation($sumArr['dbp']['list']));
    		$sumArr['heart']['standardDeviation'] = round($this->calculateStandardDeviation($sumArr['heart']['list']));
    		$sumArr['pulse']['standardDeviation'] = round($this->calculateStandardDeviation($sumArr['pulse']['list']));
    		$sumArr['map']['standardDeviation'] = round($this->calculateStandardDeviation($sumArr['map']['list']));
		
    		//变异系数
    		$sumArr['sbp']['cv'] = round($this->calculateCoefficientOfVariation($sumArr['sbp']['list']),1);
    		$sumArr['dbp']['cv'] = round($this->calculateCoefficientOfVariation($sumArr['dbp']['list']),1);
    		$sumArr['heart']['cv'] = round($this->calculateCoefficientOfVariation($sumArr['heart']['list']),1);
    		$sumArr['pulse']['cv'] = round($this->calculateCoefficientOfVariation($sumArr['pulse']['list']),1);
    		$sumArr['map']['cv'] = round($this->calculateCoefficientOfVariation($sumArr['map']['list']),1);
    		
    		//异常
            if(!isset($sumArr['sbp']['err']['count'])) $sumArr['sbp']['err']['count'] = 0;
            if(!isset($sumArr['dbp']['err']['count'])) $sumArr['dbp']['err']['count'] = 0;
            if(!isset($sumArr['heart']['err']['count'])) $sumArr['heart']['err']['count'] = 0;
            if(!isset($sumArr['map']['err']['count'])) $sumArr['map']['err']['count'] = 0;
    		
    		$sumArr['sbp']['err']['bili'] = round($sumArr['sbp']['err']['count'] / $sumArr['count'] * 100,1);
    		$sumArr['sbp']['err']['meanRealVari'] = round($this->calculateMeanRealVariability($sumArr['sbp']['list']),2);
    		$sumArr['dbp']['err']['bili'] = round($sumArr['dbp']['err']['count'] / $sumArr['count'] * 100,1);
    		$sumArr['dbp']['err']['meanRealVari'] = round($this->calculateMeanRealVariability($sumArr['dbp']['list']),2);
    		$sumArr['heart']['err']['bili'] = round($sumArr['heart']['err']['count'] / $sumArr['count'] * 100,1);
    		$sumArr['map']['err']['bili'] = round($sumArr['map']['err']['count'] / $sumArr['count'] * 100,1);
		}
		return $sumArr;
    }    
}