美文网首页
医生健康报告

医生健康报告

作者: 汤汤汤汤汤雪林 | 来源:发表于2017-03-15 11:07 被阅读0次
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import time
import datetime
import calendar

from comm.db import db
from bson import ObjectId


def get_time():
    year = datetime.date.today().year
    month = datetime.date.today().month
    firstDayWeekDay, monthRange = calendar.monthrange(year, month)
    start = str(datetime.date(year= year, month=month, day=1))
    end = str(datetime.date(year=year, month=month, day=monthRange))
    return time.mktime(time.strptime(str(start),'%Y-%m-%d')), \
           time.mktime(time.strptime(str(end),'%Y-%m-%d')), start[0:7]


def format_aggregate_result_date(data):
    """
    时间处理
    """
    num = len(data)
    if num == 4:
        return '%04d-%02d-%02d %02d' % (data['y'], data['m'], data['d'], data['h'])
    elif num == 3:
        return '%04d-%02d-%02d' % (data['y'], data['m'], data['d'])
    elif num == 2:
        return '%04d-%02d' % (data['y'], data['m'])
    else:
        return str(data['y'])


def mktime_to_hms(t):
    """
    将时间戳取出'HH:MM:SS'
    """
    t = time.strftime('%H:%M', time.localtime(t))
    return t


era = datetime.datetime(1970, 1, 1)


class HeartReport(object):
    def __init__(self, watch_id):
        self.watch_id = watch_id
        self.start, self.end, self.rpt_date=get_time()
        self.heart_rate_data = []

    def get_heart_rate(self):
        query = {'watch_id': self.watch_id, 'maketime': {'$gte': self.start, '$lte':self.end}}
        cursor = db.heart_rate.aggregate([
            {'$match': query},
            {'$group': {
                '_id': '$bpm',
                'count': {'$sum': 1}
            }}
        ])

        for c in cursor:
            c['bpm'] = c['_id']
            del c['_id']
            self.heart_rate_data.append(c)

    def risk_evaluation(self):
        for i in self.heart_rate_data:
            print i
            if i['bpm'] > 90:
                print i['count']


class SportReport(object):
    def __init__(self, watch_id):
        self.start, self.end, self.rpt_date = get_time()
        self.data = {}
        self.watch_id = watch_id
        self.sport_total = 0
        self.sport_advise = ''

    def create_report(self):
        self.get_total_data()
        self.get_step_data()
        self.get_sport_type_data()
        self.risk_evaluation()
        self.run_advise()
        self.save_to_mongo()

    def get_total_data(self):
        """
        获取step和 calorie总数
        """
        query = {'watch_id': self.watch_id,
                 'maketime': {'$gte': self.start, '$lte': self.end}}
        total = db.step.find(query)
        step_total = 0
        calorie_total = 0
        for c in total:
            step_total += c.get('step', 0)
            calorie_total += c.get('calorie', 0)
        self.data = {'step': step_total, 'calorie': calorie_total}

    def get_step_data(self):
        """
        获取step图表数据(日期:步数)
        """
        query = {'watch_id': self.watch_id,
                 'maketime': {'$gte': self.start, '$lte': self.end}}
        # date_mode = '%Y-%m-%d'
        date_group_mode = {'y': {'$year': '$time'}, 'm': {'$month': '$time'}, 'd': {'$dayOfMonth': '$time'}}
        cursor = db.step.aggregate([
            {'$match': query},
            {'$project': {
                'time': {'$add': [{'$multiply': [1000, {'$add': ['$maketime', 28800]}]}, era]},
                'n': '$step',
            }},
            {'$group': {
                '_id': date_group_mode,
                'n': {'$sum': '$n'},
            }}
        ])
        result_step = []
        for data in cursor:
            result_step.append({
                'date': format_aggregate_result_date(data['_id']),
                'step': data['n'],
            })
        self.data['step_data'] = result_step

    def get_sport_type_data(self):
        """
        获取各种运动类型运动 次数/时长/卡路里消耗
        """
        start = time.strftime('%Y-%m',time.localtime(self.start))
        end = time.strftime('%Y-%m',time.localtime(self.end))
        query = {'watch_id': self.watch_id, 'date': {'$gte': start, '$lte': end}}
        cursor = db.exercise_log.find(query)
        sport_num_dic = {}
        result = []
        for i in cursor:
            if sport_num_dic.has_key(i['type']):
                sport_num_dic[i['type']][0] += 1
                sport_num_dic[i['type']][1] += int(i.get('long', 0))
                sport_num_dic[i['type']][2] += int(i.get('calorie', 0))
                continue
            sport_num_dic.setdefault(i['type'], [1, int(i.get('long', 0)), int(i.get('calorie', 0))])
        sport_calorie = 0
        for k, v in sport_num_dic.items():
            r = {}
            i = v
            r['sport_num'] = i.pop(0)
            r['sport_time_long'] = i.pop(0)
            r['calorie'] = i.pop(0)
            r['sport_type'] = k
            sport_calorie += r['calorie']
            result.append(r)
            self.sport_total += 1
        self.data['sport_type_data'] = result
        self.data['sport_type_calorie'] = sport_calorie

    def risk_evaluation(self):
        if self.data['step'] - 280000 > 20000:
            sport_status = '运动过量'
        elif 260000 < self.data['step'] <= 299999:
            sport_status = '运动量适中'
        else:
            sport_status = '运动量较少'
        self.sport_advise = sport_status
        self.data['sport_analysis'] = {
            'sport_status': sport_status,
            'month_step': self.data['step'],
            'sport_num': self.sport_total,
            'month_calorie': self.data['sport_type_calorie']
        }

    def run_advise(self):
        if self.sport_advise == '运动过量':
            advise = '您本月运动过量,过度锻炼会对身体造成损伤,特别是每天的运动时间超过90分钟,会伤害肌腱、韧带、骨头、 \
                     关节和肌肉,而且受伤之后痊愈的几率很小。建议您每周坚持运动3~5次,每次运动30分钟为最佳'
        elif self.sport_advise == '运动量适中':
            advise = '您本月运动量适中,适当的锻炼可以强身健体。'
        else:
            advise = '您本月运动量较少,请加油锻炼。'
        self.data['run_advise'] = advise

    def save_to_mongo(self):
        db.doctor_rpt_sport.insert({
            'date': self.rpt_date,
            'step_info': self.data['step_data'],
            'step_total': self.data['step'],
            'step_calorie_total': self.data['calorie'],
            'sport_type_info': self.data['sport_type_data'],
            'sport_calorie_total': self.data['sport_type_calorie'],
            'sport_analysis': self.data['sport_analysis'],
            'run_advise': self.data['run_advise']
        })


class SleepReport(object):
    def __init__(self, watch_id):
        self.start, self.end, self.rpt_date = get_time()
        self.watch_id = watch_id
        self.data = {}

    def create_sleep_rpt(self):
        self.get_sleep_month_info()
        self.get_sleep_daily_info()
        self.sleep_advise()
        self.sleep_status()
        self.sleep_analysis()
        self.save_to_mongo()

    def get_sleep_month_info(self):
        """
        获取睡眠月视图,以及每晚平均睡眠时间
        """
        query = {'watch_id': self.watch_id, 'maketime': {'$gte': self.start, '$lte': self.end}}
        date_group_mode = {'y': {'$year': '$time'}, 'm': {'$month': '$time'}, 'd': {'$dayOfMonth': '$time'}}
        cursor = db.sleep.aggregate([
            {'$match': query},
            {'$project': {
                'time': {'$add': [{'$multiply': [1000, {'$add': ['$maketime', 28800]}]}, era]},
                'n': '$duration',
            }},
            {'$group': {
                '_id': date_group_mode,
                'n': {'$sum': '$n'},
            }}
        ])
        result = []
        avg_sleep_time = 0
        day = 0
        for data in cursor:
            avg_sleep_time +=data['n']
            result.append({
                'date': format_aggregate_result_date(data['_id']),
                'curation': data['n'],
            })
            day += 1
        self.data['sleep_analysis']['avg_sleep_time'] = float(avg_sleep_time) /day
        self.data['month_info'] = result

    def get_sleep_daily_info(self):
        """
        睡眠日视图
        """
        query = {'watch_id': self.watch_id, 'maketime': {'$gte': self.start, '$lte': self.end}}
        cursor = db.sleep.find(query)
        result = []
        for data in cursor:
            result.append({
                'date': data['maketime'],
                'quiet_percent': int(data['duration'] * float((data['quiet_percent']))//100),
                'heart_percent': int(data['duration'] * float((data['heart_percent']))//100),
                'start_time': data['start_time'],
                'end_time': data['end_time']
            })
        self.data['daily_info'] = result

    def sleep_analysis(self):
        """
        睡眠分析: 一般入睡时间,一般起床时间,每晚实际睡眠时间由get_sleep_month_info获取平均值
                上床到入睡时间暂时固定.20分钟
        """
        query = {'watch_id': self.watch_id, 'maketime': {'$gte': self.start, '$lte': self.end}}
        st = db.sleep.aggregate([
            {'$match': query},
            {'$project': {
                'start': '$start_time',
                'end': '$end_time'
            }},
            {'$group': {
                '_id': '$start',
                'count': {'$sum': 1},
            }}
        ])
        et = db.sleep.aggregate([
            {'$match': query},
            {'$project': {
                'start': '$start_time',
                'end': '$end_time'
            }},
            {'$group': {
                '_id': '$end',
                'count': {'$sum': 1},
            }}
        ])
        st_dic = {}
        et_dic = {}
        for i in st:
            st_dic[i['_id']] = i['count']
        for k, v in st_dic.items():
            if v == max(st_dic.values()):
                self.data['sleep_analysis']['start_sleep_time'] = mktime_to_hms(k)
        for e in et:
            et_dic[e['_id']] = e['count']
        for k, v in et_dic.items():
            if v == max(et_dic.values()):
                self.data['sleep_analysis']['end_sleep_time'] = mktime_to_hms(k)
        self.data['sleep_analysis']['to_sleep_time'] = 20

    def sleep_advise(self):
        """
        暂时不做判断建议
        """
        pass

    def sleep_status(self):
        """
        后期根据手表功能决定是否做睡眠状态数据
        """
        pass

    def save_to_mongo(self):
        db.doctor_rpt_sleep.insert({
            'date': self.rpt_date,
            'sleep_month_info': self.data['month_info'],
            'sleep_daily_info': self.data['daily_info'],
            'sleep_analysis': self.data['sleep_analysis'],
            'sleep_status': '',
            'sleep_advise': ''
        })


class HabitReport(object):
    def __init__(self, watch_id):
        self.watch_id = watch_id
        self.start, self.end, self.rpt_date = get_time()
        self.data = {}
        self.score_count = 0

    def create_habit_rpt(self):
        self.get_diet_info()
        self.get_habit_info()
        self.get_diet_month_info()
        self.get_score_main()
        self.get_life_advise()

    def get_diet_info(self):
        """
        获取膳食记录
        """
        query = {'maketime': {'$gte': self.start, '$lte': self.end},
                 'watch_id': self.watch_id}
        date_group_mode = {'m': {'$month': '$time'}, 'd': {'$dayOfMonth': '$time'}, 'name': '$name'}
        cursor = db.diet.aggregate([
            {'$match': query},
            {'$project': {
                'time': {'$add': [{'$multiply': [1000, {'$add': ['$maketime', 28800]}]}, era]},
                'name': '$food_name',
                'n': '$food_value',
                'c': '$calorie'
            }},
            {'$group': {
                '_id': date_group_mode,
                'n': {'$sum': '$n'},
                'c': {'$sum': '$c'}
            }}
        ])
        calorie = 0
        self.data.setdefault('diet_info', [])
        for i in cursor:
            day = str(i['_id']['m']) + '-' + str(i['_id']['d'])
            calorie += i['c']
            self.data['diet_info'].append({'date':day, 'name':i['_id']['name'], 'value':i['n'] })
        self.data['calorie']= calorie

    def get_diet_month_info(self):
        query = {'maketime': {'$gte': self.start, '$lte': self.end},
                 'watch_id': self.watch_id}
        date_group_mode = {'m': {'$month': '$time'}, 'name': '$name'}
        cursor = db.diet.aggregate([
            {'$match': query},
            {'$project': {
                'time': {'$add': [{'$multiply': [1000, {'$add': ['$maketime', 28800]}]}, era]},
                'name': '$food_name',
                'n': '$food_value',
                'c': '$calorie'
            }},
            {'$group': {
                '_id': date_group_mode,
                'n': {'$sum': '$n'},
                'c': {'$sum': '$c'}
            }}
        ])
        self.data.setdefault('diet_month_info', [])
        for i in cursor:
            day = str(i['_id']['m'])
            self.data['diet_month_info'].append({'month':day, 'name':i['_id']['name'], 'value':i['n'] })

    def get_habit_info(self):
        """
        获取生活习惯记录
        """
        self.data.setdefault('habit', {'cigarette':0, 'alcoholic': []})
        results = db.habit.find({'maketime': {'$gte': self.start, '$lte': self.end}, 'watch_id': self.watch_id}).sort([('maketime', -1)])
        for result in results:
            habit = {'cigarette': 0, 'alcoholic': {}}
            if 'wine' in result['alcoholic'].keys() and result['alcoholic']['wine']:
                result['alcoholic']['wine'] = float(result['alcoholic']['wine'])
            if 'wine' in result['alcoholic'].keys() and not result['alcoholic']['wine']:
                result['alcoholic']['wine'] = 0.0
            if 'red' in result['alcoholic'].keys() and result['alcoholic']['red']:
                result['alcoholic']['red'] = float(result['alcoholic']['red'])
            if 'red' in result['alcoholic'].keys() and not result['alcoholic']['red']:
                result['alcoholic']['red'] = 0.0
            if 'beer' in result['alcoholic'].keys() and result['alcoholic']['beer']:
                result['alcoholic']['beer'] = float(result['alcoholic']['beer'])
            if 'beer' in result['alcoholic'].keys() and not result['alcoholic']['beer']:
                result['alcoholic']['beer'] = 0.0

            self.data['habit']['alcoholic'].append(result['alcoholic'])
            self.data['habit']['cigarette'] += int(result['cigarette'])

    def get_score_main(self):
        """
        评分
        food_dic{
            高膳食纤维
            谷类食物
            食物搭配合理
            能量摄入
            肉类
            蔬菜类
            食物种类丰富
            吸烟
            喝酒
        }
        """
        food_dic = {
            'high_fiber': [u'米', u'豆', u'麦'],
            'cereal': [u'米', u'麦'],
            'food_collocation': [u'米', u'肉', u'菜', u'面', u'豆', u'奶'],
            'energy_intake': 2000.0,
            'meat': 0.35,
            'vegetable': 0.65,
            'food_types': 6,
            'smoke': 5,
            'drink': 200,
        }
        score = {}
        for k, v in food_dic.items():
            if type(v) is not list:
                continue
            else:
                score = self.get_score(k, v, score, 10)

        score.setdefault('energy', {})
        if self.data['calorie'] <1000:
            score['energy']['state'],score['energy']['advise'] = [u'较少', u'立即改善']
            score['energy']['score'] = round(self.data['calorie'] / food_dic['energy_intake']*20, 0)
        else:
            score['energy']['state'],score['energy']['advise'] = [u'适量', u'继续保持']
            score['energy']['score'] = round(self.data['calorie'] / food_dic['energy_intake']*20, 0)
        meat = 0
        for i in self.data['diet_info']:
            if u'肉' in i['name'] or u'蛋' in i['name']:
                meat += 1
        try:
            meat_b = float(meat) / len(self.data['diet_info'])
        except ZeroDivisionError:
            meat_b = 1.21
        score.setdefault('m_and_v', {})
        if meat_b < food_dic['meat']:
            score['m_and_v']['state'],score['m_and_v']['advise'] = [u'否', u'立即改善']
        else:
            score['m_and_v']['state'],score['m_and_v']['advise'] = [u'是', u'继续保持']
        score['m_and_v']['score'] = round((1 - abs(food_dic['meat'] - meat_b)) *10, 0)
        food_types_count = len(self.data['diet_month_info'])

        score.setdefault('food_type', {})
        if food_types_count < 5:
            score['food_type']['state'], score['food_type']['advise'] = [u'不丰富', u'努力改善']
        else:
            score['food_type']['state'], score['food_type']['advise'] = [u'丰富', u'继续保持']
        score['food_type']['score'] = 10.0 if food_types_count >= 10.0 else float(food_types_count)

        score.setdefault('smoke', {})
        if 0 <= self.data['habit']['cigarette'] <= 10:
            score['smoke']['score'] = float(10-self.data['habit']['cigarette'])
            score['smoke']['state'], score['smoke']['advise'] = [u'适量', u'继续保持']
        else:
            score['smoke']['score'],score['smoke']['state'],score['smoke']['advise'] = [1, u'过量', u'立即改善']

        score.setdefault('drink', {})
        drink = 0
        try:
            for a, v in self.data['habit']['alcoholic']:
                drink += v
            if drink == 0:
                raise KeyError
            if drink - food_dic['drink'] < -50:
                score['drink']['score'] = 20 - round(drink/food_dic['drink']*20, 0)
                score['drink']['state'], score['drink']['advise']= [ u'适量', u'继续保持']
            elif drink - food_dic['drink'] >= 0:
                score['drink']['score'] = 20 - round(food_dic['drink']/drink*20, 0)
                score['drink']['state'], score['drink']['advise']= [ u'过量', u'立即改善']
        except KeyError:
            score['drink']['score'], score['drink']['state'], score['drink']['advise']= [20, u'适量', u'继续保持']

        self.data.setdefault('score_count', 0)
        for k, v in score.items():
            self.data['score_count'] += v['score']
        self.data['score'] = score
        print self.data

    def get_score(self, score_type, types_dic, score_dic, standard_socre):
        """
        计算单项得分
        socre_type: 计分项名称(high_fiber...)
        types_dic: 计分项内容 [u'米', u'豆'...]
        scoer_dic: 返回值的总项
        standard_socre: 标准分数
        """
        score_dic.setdefault(score_type, {'score': 0})
        for i in self.data['diet_info']:
            for h in types_dic:
                if h in i['name']:
                    score_dic[score_type]['score'] += 1
        if self.data['diet_info']!=0 and score_dic[score_type]['score'] != 0:
            if round(float(score_dic[score_type]['score']) / len(self.data['diet_info'])*20, 0) > 10:
                score_dic[score_type]['score'] = 10.0
            else:
                score_dic[score_type]['score'] = round(float(score_dic[score_type]['score']) / len(self.data['diet_info'])*20, 0)
            score_dic[score_type]['state'], score_dic[score_type]['advise'] = self.get_state_advise(score_dic[score_type]['score'], standard_socre)
        else:
            pass
        return score_dic

    def get_state_advise(self, s, d):
        """
        根据分数判断状态以及建议
        """
        if d == 10:
            if s < 5 :
                return [u'否', u'努力提升']
            else:
                return [u'是', u'继续保持']
        else:
            if s < 10:
                return [u'否', u'努力提升']
            else:
                return [u'是', u'继续保持']

    def get_life_advise(self):
        """
        生活习惯建议
        """
        self.data['life_advise'] = ''

    def save_to_mongo(self):
        db.doctor_rpt_habit.insert({
            'date': self.rpt_date,
            'diet_month_info': self.data['diet_month_info'],
            'diet_info': self.data['date_info'],
            'calorie': self.data['calorie'],
            'smoke': self.data['haibt']['cigarette'],
            'drink': self.data['habit']['alcoholic'],
            'health_score_info': self.data['score'],
            'score': self.data['score_count'],
            'life_advise': self.data['life_advise']
        })


if __name__ == '__main__':
    # watch_id = ObjectId('589545425f1d6569e76622af')
    cursor = db.watch.find()
    for i in cursor:
        HR = HabitReport(i['_id'])
        HR.create_habit_rpt()

相关文章

网友评论

      本文标题:医生健康报告

      本文链接:https://www.haomeiwen.com/subject/lbklnttx.html