150 lines
4.6 KiB
Python
150 lines
4.6 KiB
Python
import io
|
|
from collections.__init__ import defaultdict
|
|
from datetime import timedelta
|
|
|
|
import numpy as np
|
|
from django.http import HttpResponse
|
|
from django.views.generic import DetailView
|
|
|
|
from web.models import User, ActivityLog, Activity
|
|
|
|
|
|
class UserChartsPie(DetailView):
|
|
model = User
|
|
pk_url_kwarg = 'user_id'
|
|
|
|
def render_to_response(self, context, **response_kwargs):
|
|
import matplotlib
|
|
matplotlib.use('Agg')
|
|
import matplotlib.pyplot as plt
|
|
fig = plt.figure(figsize=(6, 6), dpi=100)
|
|
ax = fig.add_subplot(111)
|
|
|
|
total_time = defaultdict(float)
|
|
|
|
logs = ActivityLog.objects.filter(user=self.object).all()
|
|
for log in logs:
|
|
total_time[str(log.activity)] += (log.end_time - log.start_time).total_seconds()
|
|
|
|
sectors = sorted(list(total_time.items()), key=lambda x: x[1])
|
|
|
|
ax.pie(x=[i[1] for i in sectors], labels=[i[0] for i in sectors], autopct='%1.0f%%')
|
|
|
|
buf = io.BytesIO()
|
|
fig.savefig(buf, format='png')
|
|
b = buf.getvalue()
|
|
return HttpResponse(b, content_type='image/png')
|
|
|
|
|
|
class UserChartsActivityAll(DetailView):
|
|
model = User
|
|
pk_url_kwarg = 'user_id'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['activity'] = Activity.objects.filter(id=self.kwargs['activity_id']).first()
|
|
return context
|
|
|
|
def bar_chart(self, plt, ax, logs, day_l, day_r, day_count, days):
|
|
day_seconds = np.zeros(day_count)
|
|
|
|
for log in logs:
|
|
for i, day in enumerate(days):
|
|
l = max(log.start_time, day)
|
|
r = min(log.end_time, day + timedelta(days=1))
|
|
|
|
if r > l:
|
|
day_seconds[i] += (r - l).total_seconds()
|
|
|
|
day_hours = day_seconds / timedelta(hours=1).total_seconds()
|
|
|
|
ax.bar(days, day_hours)
|
|
ax.hlines([np.mean(day_hours)], day_l, day_r, color='orange', lw=3)
|
|
plt.xticks(days, [f'{i:%m-%d}' for i in days], rotation=60)
|
|
plt.ylabel('кол-во часов')
|
|
|
|
def tracker_chart(self, plt, ax, logs, day_l, day_r, day_count, days):
|
|
ys = []
|
|
widths = []
|
|
lefts = []
|
|
|
|
for log in logs:
|
|
for i, day in enumerate(days):
|
|
l = max(log.start_time, day)
|
|
r = min(log.end_time, day + timedelta(days=1))
|
|
|
|
if r > l:
|
|
ys.append(day)
|
|
widths.append((r - l) / timedelta(hours=1))
|
|
lefts.append((l - day) / timedelta(hours=1))
|
|
|
|
ax.barh(y=ys, width=widths, left=lefts, zorder=2)
|
|
plt.xlim(0, 24)
|
|
plt.xticks(range(24), [f'{i:02d}:00' for i in range(24)])
|
|
plt.yticks(days, [f'{i:%m-%d}' for i in days])
|
|
plt.grid(True, zorder=1)
|
|
|
|
def render_to_response(self, context, **response_kwargs):
|
|
logs = list(ActivityLog.objects.filter(user=self.object, activity=context['activity']).order_by('start_time').all())
|
|
|
|
day_r = logs[-1].end_time.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
day_l = max(
|
|
logs[0].start_time.replace(hour=0, minute=0, second=0, microsecond=0),
|
|
day_r - timedelta(days=13)
|
|
)
|
|
|
|
day_count = (day_r - day_l) // timedelta(days=1) + 1
|
|
|
|
days = [day_l + timedelta(days=1) * i for i in range(day_count)]
|
|
|
|
import matplotlib
|
|
matplotlib.use('Agg')
|
|
import matplotlib.pyplot as plt
|
|
fig = plt.figure(figsize=(16, 12), dpi=100)
|
|
|
|
ax = fig.add_subplot(211)
|
|
self.bar_chart(plt, ax, logs, day_l, day_r, day_count, days)
|
|
|
|
ax = fig.add_subplot(212)
|
|
self.tracker_chart(plt, ax, logs, day_l, day_r, day_count, days)
|
|
|
|
buf = io.BytesIO()
|
|
fig.savefig(buf, format='png')
|
|
b = buf.getvalue()
|
|
return HttpResponse(b, content_type='image/png')
|
|
|
|
|
|
class UserActivityChartsTracker(DetailView):
|
|
model = User
|
|
pk_url_kwarg = 'user_id'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['activity'] = Activity.objects.filter(id=self.kwargs['activity_id']).first()
|
|
return context
|
|
|
|
def render_to_response(self, context, **response_kwargs):
|
|
print('start_tracker')
|
|
import matplotlib
|
|
matplotlib.use('Agg')
|
|
import matplotlib.pyplot as plt
|
|
fig = plt.figure(figsize=(16, 6), dpi=100)
|
|
ax = fig.add_subplot(111)
|
|
|
|
logs = list(ActivityLog.objects.filter(user=self.object, activity=context['activity']).order_by('start_time').all())
|
|
|
|
day_r = logs[-1].end_time.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
day_l = max(
|
|
logs[0].start_time.replace(hour=0, minute=0, second=0, microsecond=0),
|
|
day_r - timedelta(days=14)
|
|
)
|
|
|
|
day_count = (day_r - day_l) // timedelta(days=1) + 1
|
|
|
|
days = [day_l + timedelta(days=1) * i for i in range(day_count)]
|
|
|
|
buf = io.BytesIO()
|
|
fig.savefig(buf, format='png')
|
|
b = buf.getvalue()
|
|
return HttpResponse(b, content_type='image/png')
|