医生健康报告

# -*- 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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容