Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP HB2-88 allow excluding activities from training model #95

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion assets/stylesheets/homebytwo.scss
Expand Up @@ -52,6 +52,7 @@
@import '../../node_modules/kanbasu/src/scss/helpers/display';
@import '../../node_modules/kanbasu/src/scss/helpers/align';
@import '../../node_modules/kanbasu/src/scss/helpers/align-responsive';
@import '../../node_modules/kanbasu/src/scss/helpers/flex';


/**
Expand Down Expand Up @@ -90,4 +91,4 @@
@import 'components/map';
@import 'components/masterhead';
@import 'components/nav';
@import 'components/routes';
@import 'components/routes';
18 changes: 18 additions & 0 deletions homebytwo/routes/migrations/0055_activity_use_for_training.py
@@ -0,0 +1,18 @@
# Generated by Django 2.2.17 on 2020-11-20 20:04

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('routes', '0054_fix_django_doctor_field_issues_'),
]

operations = [
migrations.AddField(
model_name='activity',
name='use_for_training',
field=models.BooleanField(default=True),
),
]
2 changes: 2 additions & 0 deletions homebytwo/routes/models/activity.py
Expand Up @@ -200,6 +200,8 @@ class Activity(TimeStampedModel):
related_name="activities",
)

use_for_training = models.BooleanField(default=True)

class Meta:
ordering = ["-start_date"]
verbose_name_plural = "activities"
Expand Down
3 changes: 2 additions & 1 deletion homebytwo/routes/tasks.py
Expand Up @@ -103,7 +103,8 @@ def train_prediction_models_task(athlete_id):

athlete = Athlete.objects.get(id=athlete_id)
activities = athlete.activities.filter(
activity_type__name__in=ActivityType.SUPPORTED_ACTIVITY_TYPES
activity_type__name__in=ActivityType.SUPPORTED_ACTIVITY_TYPES,
use_for_training=True,
)
activities = activities.order_by("activity_type")
activities = activities.distinct("activity_type")
Expand Down
36 changes: 35 additions & 1 deletion homebytwo/routes/views.py
Expand Up @@ -5,9 +5,10 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import BooleanField, Case, F, Value, When
from django.http import FileResponse, Http404, HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse_lazy
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_safe
Expand Down Expand Up @@ -259,6 +260,39 @@ class ActivityList(ListView):
def get_queryset(self):
return Activity.objects.for_user(self.request.user)

def post(self, request):
self.object_list = self.get_queryset()
context_data = self.get_context_data()
page_activity_ids = context_data[
self.get_context_object_name(self.object_list)
].values_list("pk", flat=True)

use_for_training_ids = request.POST.getlist("use_for_training")
Activity.objects.for_user(self.request.user).filter(
pk__in=page_activity_ids
).annotate(
new_use_for_training=Case(
When(id__in=use_for_training_ids, then=True),
default=Value(False),
output_field=BooleanField(),
)
).update(
use_for_training=F("new_use_for_training")
)

train_prediction_models_task.delay(request.user.athlete.id)

activities_url = reverse("routes:activities")
page_number = context_data["page_obj"].number

redirect_url = (
activities_url
if page_number == 1
else activities_url + f"?page={page_number}"
)

return redirect(redirect_url)


@login_required
@strava_required # only the superuser can be logged-in without a Strava account
Expand Down
66 changes: 40 additions & 26 deletions homebytwo/templates/routes/activity_list.html
@@ -1,37 +1,51 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% load humanize duration %}

{% block title %}Home by Two - Strava Activities{% endblock %}

{% block content %}
<h1>Strava Activities</h1>
<ul class="list-stacked list-stacked--tight mrgb">
{% for activity in strava_activities %}
<li class="mrgb-">
<div>
<a class="strava" href="{{ activity.get_strava_url }}">
{{ activity.activity_type }}: {{ activity.name }}
</a>
</div>
<div>
{{ activity.start_date|naturalday }}
{% if activity.distance %}
- {{ activity.get_distance.km|floatformat:"01"|intcomma }}km
{% endif %}
{% if activity.total_elevation_gain %}
- {{ activity.get_total_elevation_gain.m|floatformat:"0"|intcomma }}m+
{% endif %}

{% if activity.moving_time %}
- {{ activity.moving_time|duration }}
{% endif %}
<div>
</li>
{% empty %}
<li>No activities yet.</li>
{% endfor %}
</ul>

<form method="post">
{% csrf_token %}
<ul class="list-stacked list-stacked--tight mrgb">
{% for activity in strava_activities %}
<li class="mrgb-">
<div class="flex">
<div class="flex-shrink mrgr-">
<input name="use_for_training" type="checkbox" value="{{ activity.pk }}"{% if activity.use_for_training %} checked{% endif %}>
</div>
<div class="flex-grow">
<div>
<a class="strava" href="{{ activity.get_strava_url }}">
{{ activity.activity_type }}: {{ activity.name }}
</a>
</div>
<div>
{{ activity.start_date|naturalday }}
{% if activity.distance %}
- {{ activity.get_distance.km|floatformat:"01"|intcomma }}km
{% endif %}
{% if activity.total_elevation_gain %}
- {{ activity.get_total_elevation_gain.m|floatformat:"0"|intcomma }}m+
{% endif %}

{% if activity.moving_time %}
- {{ activity.moving_time|duration }}
{% endif %}
</div>
</div>
</div>
</li>
{% empty %}
<li>No activities yet.</li>
{% endfor %}
</ul>

<button class="btn btn--primary">{% trans "Include (checked) / exclude (unchecked) activities from training model" %}</button>
</form>

<div class="pagination">
<span class="step-links">
Expand Down