<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from collections import OrderedDict

from django.db.models import Count, Case, When
from django.db.models.functions import TruncDate
from django.utils import timezone

import pandas as pd
import plotly.offline as plotly
import plotly.graph_objs as go

from core.models import DiaperChange, Sleep
from core.utils import duration_string

from .utils import default_graph_layout_options, split_graph_output


def diaperchange_types(child):
    changes = DiaperChange.objects.filter(child=child) \
        .annotate(date=TruncDate('time')) \
        .values('date') \
        .annotate(wet_count=Count(Case(When(wet=True, then=1)))) \
        .annotate(solid_count=Count(Case(When(solid=True, then=1)))) \
        .annotate(total=Count('id')) \
        .order_by('-date')

    solid_trace = go.Scatter(
        mode='markers',
        name='Solid changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('solid_count', flat=True)),
    )
    wet_trace = go.Scatter(
        mode='markers',
        name='Wet changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('wet_count', flat=True))
    )
    total_trace = go.Scatter(
        name='Total changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('total', flat=True))
    )

    layout_args = default_graph_layout_options()
    layout_args['barmode'] = 'stack'
    layout_args['title'] = '<b>Diaper Change Types</b><br>{}'.format(child)
    layout_args['xaxis']['title'] = 'Date'
    layout_args['yaxis']['title'] = 'Number of changes'

    fig = go.Figure({
        'data': [solid_trace, wet_trace, total_trace],
        'layout': go.Layout(**layout_args)
    })
    output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
    return split_graph_output(output)


def sleep_totals(child):
    """Create a graph showing total time sleeping for each day."""
    instances = Sleep.objects.filter(child=child).order_by('start')

    totals = {}
    for instance in instances:
        start = timezone.localtime(instance.start)
        end = timezone.localtime(instance.end)
        if start.date() not in totals.keys():
            totals[start.date()] = timezone.timedelta(seconds=0)
        if end.date() not in totals.keys():
            totals[end.date()] = timezone.timedelta(seconds=0)

        # Account for dates crossing midnight.
        if start.date() != end.date():
            totals[start.date()] += end.replace(
                day=start.day, hour=23, minute=59, second=59) - start
            totals[end.date()] += end - start.replace(
                day=end.day, hour=0, minute=0, second=0)
        else:
            totals[start.date()] += instance.duration

    trace = go.Bar(
        name='Total sleep',
        x=list(totals.keys()),
        y=[td.seconds/3600 for td in totals.values()],
        hoverinfo='text',
        text=[duration_string(td) for td in totals.values()]
    )

    layout_args = default_graph_layout_options()
    layout_args['barmode'] = 'stack'
    layout_args['title'] = '<b>Sleep Totals</b><br>{}'.format(child)
    layout_args['xaxis']['title'] = 'Date'
    layout_args['yaxis']['title'] = 'Hours of sleep'

    fig = go.Figure({
        'data': [trace],
        'layout': go.Layout(**layout_args)
    })
    output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
    return split_graph_output(output)


def sleep_pattern(child):
    """Create a graph showing blocked out periods of sleep during each day."""
    instances = Sleep.objects.filter(child=child).order_by('start')
    y_df = pd.DataFrame()
    text_df = pd.DataFrame()
    last_end_time = None
    adjustment = None<commit_msg>Add duration figures to graph view for sleep totals.<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from collections import OrderedDict

from django.db.models import Count, Case, When
from django.db.models.functions import TruncDate
from django.utils import timezone

import pandas as pd
import plotly.offline as plotly
import plotly.graph_objs as go

from core.models import DiaperChange, Sleep
from core.utils import duration_string, duration_string_short

from .utils import default_graph_layout_options, split_graph_output


def diaperchange_types(child):
    changes = DiaperChange.objects.filter(child=child) \
        .annotate(date=TruncDate('time')) \
        .values('date') \
        .annotate(wet_count=Count(Case(When(wet=True, then=1)))) \
        .annotate(solid_count=Count(Case(When(solid=True, then=1)))) \
        .annotate(total=Count('id')) \
        .order_by('-date')

    solid_trace = go.Scatter(
        mode='markers',
        name='Solid changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('solid_count', flat=True)),
    )
    wet_trace = go.Scatter(
        mode='markers',
        name='Wet changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('wet_count', flat=True))
    )
    total_trace = go.Scatter(
        name='Total changes',
        x=list(changes.values_list('date', flat=True)),
        y=list(changes.values_list('total', flat=True))
    )

    layout_args = default_graph_layout_options()
    layout_args['barmode'] = 'stack'
    layout_args['title'] = '<b>Diaper Change Types</b><br>{}'.format(child)
    layout_args['xaxis']['title'] = 'Date'
    layout_args['yaxis']['title'] = 'Number of changes'

    fig = go.Figure({
        'data': [solid_trace, wet_trace, total_trace],
        'layout': go.Layout(**layout_args)
    })
    output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
    return split_graph_output(output)


def sleep_totals(child):
    """Create a graph showing total time sleeping for each day."""
    instances = Sleep.objects.filter(child=child).order_by('start')

    totals = {}
    for instance in instances:
        start = timezone.localtime(instance.start)
        end = timezone.localtime(instance.end)
        if start.date() not in totals.keys():
            totals[start.date()] = timezone.timedelta(seconds=0)
        if end.date() not in totals.keys():
            totals[end.date()] = timezone.timedelta(seconds=0)

        # Account for dates crossing midnight.
        if start.date() != end.date():
            totals[start.date()] += end.replace(
                day=start.day, hour=23, minute=59, second=59) - start
            totals[end.date()] += end - start.replace(
                day=end.day, hour=0, minute=0, second=0)
        else:
            totals[start.date()] += instance.duration

    trace = go.Bar(
        name='Total sleep',
        x=list(totals.keys()),
        y=[td.seconds/3600 for td in totals.values()],
        hoverinfo='text',
        textposition='outside',
        text=[duration_string_short(td) for td in totals.values()]
    )

    layout_args = default_graph_layout_options()
    layout_args['barmode'] = 'stack'
    layout_args['title'] = '<b>Sleep Totals</b><br>{}'.format(child)
    layout_args['xaxis']['title'] = 'Date'
    layout_args['yaxis']['title'] = 'Hours of sleep'

    fig = go.Figure({
        'data': [trace],
        'layout': go.Layout(**layout_args)
    })
    output = plotly.plot(fig, output_type='div', include_plotlyjs=False)
    return split_graph_output(output)


def sleep_pattern(child):
    """Create a graph showing blocked out periods of sleep during each day."""
    instances = Sleep.objects.filter(child=child).order_by('start')
    y_df = pd.DataFrame()
    text_df = pd.DataFrame()
    last_end_time = None
    adjustment = None
{'fraction_non_alphanumeric': 0.14337287261474987, 'fraction_numerical': 0.0046415678184631255, 'mean_word_length': 3.220348204570185, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1500665', 'n_tokens_mistral': 2460, 'n_tokens_neox': 2434, 'n_words': 497}