Blacked python file

This commit is contained in:
Gregory Trullemans 2021-12-19 09:30:51 +01:00
parent 2e23a46277
commit df753f9e76
51 changed files with 2017 additions and 996 deletions

View File

@ -18,7 +18,7 @@ steps:
{{#success build.status}}
Ultron build {{build.number}} succeeded. Good job.
{{else}}
Ultron build {{build.number}} failed. Fix me please.
Ultron build {{build.number}} failed. Fix me please. More info : https://drone.grimbox.be/Sulley/Ultron/{{build.number}}
{{/success}}
when:
status:

View File

@ -11,7 +11,7 @@
<h4 class=""><i class="icon-primary fal fa-laugh-wink"></i> Hi {{ user.username }} !</h4>
</div>
<div class="card-body">
Welcome to Ultron v0.30 <span class="text-muted">(last update : 16-12-2021)</span><br />
Welcome to Ultron v0.31 <span class="text-muted">(last update : 19-12-2021)</span><br />
This application is there to help us manage the gymnasts (evolution, evaluation, ...). It is not perfect so feel free to make improvement proposals, bug reports, … by sending me an <a href="mailto:gregory@flyingacrobaticstrampoline.be">email</a>.
</div>
</div>

View File

@ -2,85 +2,98 @@ from django.contrib import admin
from django.db.models import fields
from config.views import search
from .models import Chrono, LearnedSkill, Point, Accident, MindState, GymnastHasRoutine, NumberOfRoutineDone, HeightWeight
from .models import (
Chrono,
LearnedSkill,
Point,
Accident,
MindState,
GymnastHasRoutine,
NumberOfRoutineDone,
HeightWeight,
)
from django_extensions.admin import ForeignKeyAutocompleteAdmin
class ChronoAdmin(ForeignKeyAutocompleteAdmin):
model = Chrono
list_display = ('date', 'gymnast', 'tof', 'type')
list_filter = ('type', )
list_display = ("date", "gymnast", "tof", "type")
list_filter = ("type",)
# search_fields = ('gymnast', 'routine')
autocomplete_fields = ['gymnast']
autocomplete_fields = ["gymnast"]
related_search_fields = {
'gymnast': ('last_name', 'first_name')
}
related_search_fields = {"gymnast": ("last_name", "first_name")}
class LearnedSkillAdmin(admin.ModelAdmin):
model = LearnedSkill
list_display = ('gymnast', 'skill', 'cando', 'date')
list_filter = ('gymnast', 'skill', 'cando')
search_fields = ('gymnast', 'skill')
autocomplete_fields = ['gymnast', 'skill']
list_display = ("gymnast", "skill", "cando", "date")
list_filter = ("gymnast", "skill", "cando")
search_fields = ("gymnast", "skill")
autocomplete_fields = ["gymnast", "skill"]
class PointAdmin(admin.ModelAdmin):
model = Point
list_display = (
'gymnast',
'point_execution',
'point_difficulty',
'point_time_of_flight',
'total',
"gymnast",
"point_execution",
"point_difficulty",
"point_time_of_flight",
"total",
)
ordering = ('gymnast',)
list_filter = ('gymnast', 'event', 'routine_type')
ordering = ("gymnast",)
list_filter = ("gymnast", "event", "routine_type")
class AccidentAdmin(admin.ModelAdmin):
model = Accident
fields = ('date', 'gymnast', 'skill', 'informations') # educative
list_display = ('date', 'gymnast', 'skill') # educative
list_filter = ('date',)
search_fields = ('date', 'gymnast') # educative
autocomplete_fields = ['gymnast'] # educative
fields = ("date", "gymnast", "skill", "informations") # educative
list_display = ("date", "gymnast", "skill") # educative
list_filter = ("date",)
search_fields = ("date", "gymnast") # educative
autocomplete_fields = ["gymnast"] # educative
class MindStateAdmin(admin.ModelAdmin):
model = MindState
fields = ('gymnast', 'date', 'score', 'informations')
list_display = ('date', 'gymnast', 'score')
list_filter = ('date', 'gymnast')
fields = ("gymnast", "date", "score", "informations")
list_display = ("date", "gymnast", "score")
list_filter = ("date", "gymnast")
class GymnastHasRoutineAdmin(ForeignKeyAutocompleteAdmin):
model = GymnastHasRoutine
list_display = ('gymnast', 'routine', 'routine_type', 'datebegin', 'dateend')
list_filter = ('gymnast', 'routine_type')
search_fields = ('gymnast', 'routine')
autocomplete_fields = ('gymnast', 'routine')
list_display = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
list_filter = ("gymnast", "routine_type")
search_fields = ("gymnast", "routine")
autocomplete_fields = ("gymnast", "routine")
class NumberOfRoutineDoneAdmin(ForeignKeyAutocompleteAdmin):
model = NumberOfRoutineDone
list_display = ('gymnast', 'routine_type', 'date', 'number_of_successes', 'number_of_try')
list_filter = ('gymnast', 'routine_type')
list_display = (
"gymnast",
"routine_type",
"date",
"number_of_successes",
"number_of_try",
)
list_filter = ("gymnast", "routine_type")
class HeightWeightAdmin(ForeignKeyAutocompleteAdmin):
model = HeightWeight
list_display = ('gymnast', 'height', 'weight', 'date')
list_filter = ('gymnast',)
list_display = ("gymnast", "height", "weight", "date")
list_filter = ("gymnast",)
admin.site.register(Accident, AccidentAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class FollowupConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.followup'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.followup"

View File

@ -5,64 +5,72 @@ from datetime import date
from django.db import models
from django.forms import fields, widgets
from .models import Chrono, LearnedSkill, Point, Accident, MindState, GymnastHasRoutine, HeightWeight
from .models import (
Chrono,
LearnedSkill,
Point,
Accident,
MindState,
GymnastHasRoutine,
HeightWeight,
)
class ChronoForm(forms.ModelForm):
class Meta:
model = Chrono
fields = ('gymnast', 'date', 'type', 'score_type', 'score', 'tof')
fields = ("gymnast", "date", "type", "score_type", "score", "tof")
widgets = {
'gymnast': forms.HiddenInput(),
'date': forms.TextInput(
"gymnast": forms.HiddenInput(),
"date": forms.TextInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
'type': forms.Select(attrs={'class': 'form-control'}),
'score_type': forms.Select(attrs={'class': 'form-control'}),
'score': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'xx,xxx'}
"type": forms.Select(attrs={"class": "form-control"}),
"score_type": forms.Select(attrs={"class": "form-control"}),
"score": forms.TextInput(
attrs={"class": "form-control", "placeholder": "xx,xxx"}
),
'tof': forms.HiddenInput(),
"tof": forms.HiddenInput(),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
class LearnedSkillForm(forms.ModelForm):
class Meta:
model = LearnedSkill
fields = ('gymnast', 'skill', 'cando', 'date')
fields = ("gymnast", "skill", "cando", "date")
widgets = {
'gymnast': forms.HiddenInput(),
'skill': forms.HiddenInput(),
'date': forms.TextInput(
"gymnast": forms.HiddenInput(),
"skill": forms.HiddenInput(),
"date": forms.TextInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
'cando': forms.Select(attrs={'class': 'form-control'}),
"cando": forms.Select(attrs={"class": "form-control"}),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
@ -70,9 +78,9 @@ class LearnedSkillForm(forms.ModelForm):
skill_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching skill…',
'data-ref': '#id_skill',
"class": "form-control",
"placeholder": "Searching skill…",
"data-ref": "#id_skill",
}
)
)
@ -81,49 +89,61 @@ class LearnedSkillForm(forms.ModelForm):
class ScoreForm(forms.ModelForm):
class Meta:
ROUTINETYPE_CHOICE = (
(0, 'Routine 1'),
(1, 'Routine 2'),
(2, 'Final\'s routine'),
(0, "Routine 1"),
(1, "Routine 2"),
(2, "Final's routine"),
)
model = Point
fields = (
'gymnast',
'event',
'routine_type',
'point_difficulty',
'point_time_of_flight',
'point_execution',
'point_horizontal_displacement',
'penality',
'total',
"gymnast",
"event",
"routine_type",
"point_difficulty",
"point_time_of_flight",
"point_execution",
"point_horizontal_displacement",
"penality",
"total",
)
widgets = {
'gymnast': forms.HiddenInput(),
'event': forms.HiddenInput(),
'routine_type': forms.Select(attrs={'class': 'form-control'}),
'point_execution': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx,xx',}
),
'point_difficulty': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx,xx',}
),
'point_time_of_flight': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx,xx',}
),
'point_horizontal_displacement': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'x,xx',}
),
'penality': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx,xx', 'value': '0'}
),
'total': forms.TextInput(
"gymnast": forms.HiddenInput(),
"event": forms.HiddenInput(),
"routine_type": forms.Select(attrs={"class": "form-control"}),
"point_execution": forms.NumberInput(
attrs={
'class': 'form-control',
'placeholder': '000,000',
'readonly': 'readonly',
'maxlength': '6',
"class": "form-control",
"placeholder": "xx,xx",
}
),
"point_difficulty": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "xx,xx",
}
),
"point_time_of_flight": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "xx,xx",
}
),
"point_horizontal_displacement": forms.NumberInput(
attrs={
"class": "form-control",
"placeholder": "x,xx",
}
),
"penality": forms.NumberInput(
attrs={"class": "form-control", "placeholder": "xx,xx", "value": "0"}
),
"total": forms.TextInput(
attrs={
"class": "form-control",
"placeholder": "000,000",
"readonly": "readonly",
"maxlength": "6",
}
),
}
@ -131,18 +151,18 @@ class ScoreForm(forms.ModelForm):
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching…",
"data-ref": "#id_gymnast",
}
)
)
event_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching…',
'data-ref': '#id_event',
"class": "form-control",
"placeholder": "Searching…",
"data-ref": "#id_event",
}
)
)
@ -151,24 +171,24 @@ class ScoreForm(forms.ModelForm):
class AccidentForm(forms.ModelForm):
class Meta:
model = Accident
fields = ('gymnast', 'date', 'nb_week_off', 'informations')
fields = ("gymnast", "date", "nb_week_off", "informations")
widgets = {
'date': forms.DateInput(
"date": forms.DateInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
'gymnast': forms.HiddenInput(),
'skill': forms.HiddenInput(),
'nb_week_off': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx'}
"gymnast": forms.HiddenInput(),
"skill": forms.HiddenInput(),
"nb_week_off": forms.NumberInput(
attrs={"class": "form-control", "placeholder": "xx"}
),
'informations': forms.Textarea(
"informations": forms.Textarea(
attrs={
'class': 'form-control',
'placeholder': 'Informations about accident: context (why, where, …), consequencies, …',
"class": "form-control",
"placeholder": "Informations about accident: context (why, where, …), consequencies, …",
}
),
}
@ -176,9 +196,9 @@ class AccidentForm(forms.ModelForm):
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
@ -186,35 +206,35 @@ class AccidentForm(forms.ModelForm):
required=False,
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching skill…',
'data-ref': '#id_skill',
"class": "form-control",
"placeholder": "Searching skill…",
"data-ref": "#id_skill",
}
)
),
)
class MindStateForm(forms.ModelForm):
class Meta:
model = MindState
fields = ('gymnast', 'date', 'score', 'informations')
fields = ("gymnast", "date", "score", "informations")
widgets = {
'gymnast': forms.HiddenInput(),
'date': forms.TextInput(
"gymnast": forms.HiddenInput(),
"date": forms.TextInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
'event': forms.HiddenInput(),
'score': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xx'}
"event": forms.HiddenInput(),
"score": forms.NumberInput(
attrs={"class": "form-control", "placeholder": "xx"}
),
'informations': forms.Textarea(
"informations": forms.Textarea(
attrs={
'class': 'form-control',
'placeholder': 'Informations about the psychological state of mind : context (why, where, …), possible consequencies, …',
"class": "form-control",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …",
}
),
}
@ -222,9 +242,9 @@ class MindStateForm(forms.ModelForm):
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
@ -233,46 +253,54 @@ class MindStateForm(forms.ModelForm):
required=False,
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching event…',
'data-ref': '#id_event',
"class": "form-control",
"placeholder": "Searching event…",
"data-ref": "#id_event",
}
)
),
)
class GymnastHasRoutineForm(forms.ModelForm):
class Meta:
model = GymnastHasRoutine
fields = ('gymnast', 'routine', 'routine_type', 'datebegin', 'dateend')
fields = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
widgets = {
'gymnast': forms.HiddenInput(),
'routine': forms.HiddenInput(),
'routine_type': forms.Select(attrs={'class': 'form-control'}),
'datebegin': forms.DateInput(attrs={'class': 'form-control datepicker',}),
'dateend': forms.DateInput(attrs={'class': 'form-control datepicker',}),
"gymnast": forms.HiddenInput(),
"routine": forms.HiddenInput(),
"routine_type": forms.Select(attrs={"class": "form-control"}),
"datebegin": forms.DateInput(
attrs={
"class": "form-control datepicker",
}
),
"dateend": forms.DateInput(
attrs={
"class": "form-control datepicker",
}
),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
routine_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching routine…',
'data-ref': '#id_routine',
"class": "form-control",
"placeholder": "Searching routine…",
"data-ref": "#id_routine",
}
)
)
class HeightWeightForm(forms.ModelForm):
"""
Formulaire d'enregistrement d'un couple taille/poids
@ -280,30 +308,30 @@ class HeightWeightForm(forms.ModelForm):
class Meta:
model = HeightWeight
fields = ('gymnast', 'date', 'height', 'weight')
fields = ("gymnast", "date", "height", "weight")
widgets = {
'gymnast': forms.HiddenInput(),
'date': forms.TextInput(
"gymnast": forms.HiddenInput(),
"date": forms.TextInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
'height': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xxx,x'}
"height": forms.NumberInput(
attrs={"class": "form-control", "placeholder": "xxx,x"}
),
'weight': forms.NumberInput(
attrs={'class': 'form-control', 'placeholder': 'xxx,x'}
"weight": forms.NumberInput(
attrs={"class": "form-control", "placeholder": "xxx,x"}
),
}
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)

View File

@ -10,111 +10,360 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('planning', '0001_initial'),
('people', '0001_initial'),
('objective', '0001_initial'),
("planning", "0001_initial"),
("people", "0001_initial"),
("objective", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='Point',
name="Point",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('routine_type', models.PositiveSmallIntegerField(choices=[(0, 'Routine 1'), (1, 'Routine 2'), (2, 'Final')])),
('point_execution', models.DecimalField(decimal_places=3, max_digits=5)),
('point_difficulty', models.DecimalField(decimal_places=1, max_digits=3)),
('point_time_of_flight', models.DecimalField(decimal_places=3, max_digits=5)),
('point_horizontal_displacement', models.DecimalField(decimal_places=3, max_digits=4)),
('penality', models.DecimalField(decimal_places=1, max_digits=3)),
('total', models.DecimalField(decimal_places=3, max_digits=6)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('event', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='planning.event')),
('gymnast', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='points', to='people.gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"routine_type",
models.PositiveSmallIntegerField(
choices=[(0, "Routine 1"), (1, "Routine 2"), (2, "Final")]
),
),
(
"point_execution",
models.DecimalField(decimal_places=3, max_digits=5),
),
(
"point_difficulty",
models.DecimalField(decimal_places=1, max_digits=3),
),
(
"point_time_of_flight",
models.DecimalField(decimal_places=3, max_digits=5),
),
(
"point_horizontal_displacement",
models.DecimalField(decimal_places=3, max_digits=4),
),
("penality", models.DecimalField(decimal_places=1, max_digits=3)),
("total", models.DecimalField(decimal_places=3, max_digits=6)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"event",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="planning.event",
),
),
(
"gymnast",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
related_name="points",
to="people.gymnast",
),
),
],
),
migrations.CreateModel(
name='MindState',
name="MindState",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('informations', models.TextField(blank=True, help_text='Only MarkDown is authorized', null=True, verbose_name='Comments')),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('score', models.PositiveSmallIntegerField(verbose_name='Score')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('event', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mindstate', to='planning.event')),
('gymnast', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='mindstate', to='people.gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"informations",
models.TextField(
blank=True,
help_text="Only MarkDown is authorized",
null=True,
verbose_name="Comments",
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
("score", models.PositiveSmallIntegerField(verbose_name="Score")),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"event",
models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="mindstate",
to="planning.event",
),
),
(
"gymnast",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
related_name="mindstate",
to="people.gymnast",
),
),
],
options={
'abstract': False,
"abstract": False,
},
),
migrations.CreateModel(
name='GymnastHasRoutine',
name="GymnastHasRoutine",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('routine_type', models.PositiveSmallIntegerField(choices=[(1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S')], default='1', verbose_name='Type')),
('datebegin', models.DateField(default=datetime.date.today, verbose_name='Date begin')),
('dateend', models.DateField(blank=True, default=datetime.date.today, null=True, verbose_name='Date end')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='routines', to='people.gymnast', verbose_name='Gymnast')),
('routine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='done_by', to='objective.routine', verbose_name='Routine')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"routine_type",
models.PositiveSmallIntegerField(
choices=[
(1, "L1"),
(2, "L2"),
(3, "L3"),
(4, "L4"),
(5, "L1S"),
(6, "L2S"),
(7, "L3S"),
(8, "L4S"),
],
default="1",
verbose_name="Type",
),
),
(
"datebegin",
models.DateField(
default=datetime.date.today, verbose_name="Date begin"
),
),
(
"dateend",
models.DateField(
blank=True,
default=datetime.date.today,
null=True,
verbose_name="Date end",
),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="routines",
to="people.gymnast",
verbose_name="Gymnast",
),
),
(
"routine",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="done_by",
to="objective.routine",
verbose_name="Routine",
),
),
],
options={
'verbose_name': 'Gymnast Has Routine',
'verbose_name_plural': 'Gymnast Has Routines',
"verbose_name": "Gymnast Has Routine",
"verbose_name_plural": "Gymnast Has Routines",
},
),
migrations.CreateModel(
name='Chrono',
name="Chrono",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.PositiveSmallIntegerField(choices=[(0, '10 |'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (99, 'Other')], verbose_name='Routine type')),
('score_type', models.PositiveSmallIntegerField(choices=[(0, 'Chrono'), (1, 'ToF')], verbose_name='Score type')),
('score', models.DecimalField(decimal_places=3, max_digits=5)),
('tof', models.DecimalField(blank=True, decimal_places=3, max_digits=5, null=True)),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chronos', to='people.gymnast', verbose_name='gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"type",
models.PositiveSmallIntegerField(
choices=[
(0, "10 |"),
(1, "L1"),
(2, "L2"),
(3, "L3"),
(4, "L4"),
(99, "Other"),
],
verbose_name="Routine type",
),
),
(
"score_type",
models.PositiveSmallIntegerField(
choices=[(0, "Chrono"), (1, "ToF")], verbose_name="Score type"
),
),
("score", models.DecimalField(decimal_places=3, max_digits=5)),
(
"tof",
models.DecimalField(
blank=True, decimal_places=3, max_digits=5, null=True
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="chronos",
to="people.gymnast",
verbose_name="gymnast",
),
),
],
options={
'verbose_name': 'Chrono',
'verbose_name_plural': 'Chronos',
'ordering': ['date', 'gymnast'],
"verbose_name": "Chrono",
"verbose_name_plural": "Chronos",
"ordering": ["date", "gymnast"],
},
),
migrations.CreateModel(
name='Accident',
name="Accident",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('informations', models.TextField(blank=True, help_text='Only MarkDown is authorized', null=True, verbose_name='Comments')),
('date', models.DateField(verbose_name='Date')),
('nb_week_off', models.SmallIntegerField(blank=True, null=True, verbose_name='# week off')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accident', to='people.gymnast', verbose_name='Gymnast')),
('skill', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accident', to='objective.skill', verbose_name='Skill')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"informations",
models.TextField(
blank=True,
help_text="Only MarkDown is authorized",
null=True,
verbose_name="Comments",
),
),
("date", models.DateField(verbose_name="Date")),
(
"nb_week_off",
models.SmallIntegerField(
blank=True, null=True, verbose_name="# week off"
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="accident",
to="people.gymnast",
verbose_name="Gymnast",
),
),
(
"skill",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="accident",
to="objective.skill",
verbose_name="Skill",
),
),
],
options={
'verbose_name': 'Accident',
'verbose_name_plural': 'Accidents',
"verbose_name": "Accident",
"verbose_name_plural": "Accidents",
},
),
migrations.CreateModel(
name='LearnedSkill',
name="LearnedSkill",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('cando', models.PositiveSmallIntegerField(choices=[(0, 'No'), (1, 'With help'), (2, 'Without help'), (3, 'Chained')], verbose_name='Can do type')),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='can_do_skill', to='people.gymnast', verbose_name='gymnast')),
('skill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='done_by_gymnasts', to='objective.skill', verbose_name='Skill')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"cando",
models.PositiveSmallIntegerField(
choices=[
(0, "No"),
(1, "With help"),
(2, "Without help"),
(3, "Chained"),
],
verbose_name="Can do type",
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="can_do_skill",
to="people.gymnast",
verbose_name="gymnast",
),
),
(
"skill",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="done_by_gymnasts",
to="objective.skill",
verbose_name="Skill",
),
),
],
options={
'verbose_name': 'Learned Skill',
'verbose_name_plural': 'Learned Skills',
'unique_together': {('gymnast', 'skill', 'date')},
"verbose_name": "Learned Skill",
"verbose_name_plural": "Learned Skills",
"unique_together": {("gymnast", "skill", "date")},
},
),
]

View File

@ -7,14 +7,19 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0001_initial'),
('followup', '0001_initial'),
("people", "0001_initial"),
("followup", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name='learnedskill',
name='gymnast',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='known_skills', to='people.gymnast', verbose_name='gymnast'),
model_name="learnedskill",
name="gymnast",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="known_skills",
to="people.gymnast",
verbose_name="gymnast",
),
),
]

View File

@ -7,14 +7,19 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('objective', '0001_initial'),
('followup', '0002_alter_learnedskill_gymnast'),
("objective", "0001_initial"),
("followup", "0002_alter_learnedskill_gymnast"),
]
operations = [
migrations.AlterField(
model_name='learnedskill',
name='skill',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='known_by_gymnasts', to='objective.skill', verbose_name='Skill'),
model_name="learnedskill",
name="skill",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="known_by_gymnasts",
to="objective.skill",
verbose_name="Skill",
),
),
]

View File

@ -7,14 +7,19 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('objective', '0001_initial'),
('followup', '0003_alter_learnedskill_skill'),
("objective", "0001_initial"),
("followup", "0003_alter_learnedskill_skill"),
]
operations = [
migrations.AlterField(
model_name='learnedskill',
name='skill',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='known_by', to='objective.skill', verbose_name='Skill'),
model_name="learnedskill",
name="skill",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="known_by",
to="objective.skill",
verbose_name="Skill",
),
),
]

View File

@ -7,25 +7,49 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('objective', '0003_delete_gymnasthasroutine'),
('people', '0001_initial'),
('followup', '0004_alter_learnedskill_skill'),
("objective", "0003_delete_gymnasthasroutine"),
("people", "0001_initial"),
("followup", "0004_alter_learnedskill_skill"),
]
operations = [
migrations.AlterField(
model_name='gymnasthasroutine',
name='gymnast',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='has_routine', to='people.gymnast', verbose_name='Gymnast'),
model_name="gymnasthasroutine",
name="gymnast",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="has_routine",
to="people.gymnast",
verbose_name="Gymnast",
),
),
migrations.AlterField(
model_name='gymnasthasroutine',
name='routine',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='done_by_gymnast', to='objective.routine', verbose_name='Routine'),
model_name="gymnasthasroutine",
name="routine",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="done_by_gymnast",
to="objective.routine",
verbose_name="Routine",
),
),
migrations.AlterField(
model_name='gymnasthasroutine',
name='routine_type',
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S')], default='1', verbose_name='Type'),
model_name="gymnasthasroutine",
name="routine_type",
field=models.PositiveSmallIntegerField(
choices=[
(0, "Other"),
(1, "L1"),
(2, "L2"),
(3, "L3"),
(4, "L4"),
(5, "L1S"),
(6, "L2S"),
(7, "L3S"),
(8, "L4S"),
],
default="1",
verbose_name="Type",
),
),
]

View File

@ -8,40 +8,123 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0001_initial'),
('objective', '0003_delete_gymnasthasroutine'),
('followup', '0005_auto_20211205_1412'),
("people", "0001_initial"),
("objective", "0003_delete_gymnasthasroutine"),
("followup", "0005_auto_20211205_1412"),
]
operations = [
migrations.CreateModel(
name='NumberOfRoutineDone',
name="NumberOfRoutineDone",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('routine_type', models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S')], default='1', verbose_name='Type')),
('number_of_try', models.PositiveSmallIntegerField(verbose_name='Number of try')),
('number_of_successes', models.PositiveSmallIntegerField(verbose_name='number of successes')),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='number_of_routine_done', to='people.gymnast', verbose_name='Gymnast')),
('routine', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='number_of_try', to='objective.routine', verbose_name='Routine')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"routine_type",
models.PositiveSmallIntegerField(
choices=[
(0, "Other"),
(1, "L1"),
(2, "L2"),
(3, "L3"),
(4, "L4"),
(5, "L1S"),
(6, "L2S"),
(7, "L3S"),
(8, "L4S"),
],
default="1",
verbose_name="Type",
),
),
(
"number_of_try",
models.PositiveSmallIntegerField(verbose_name="Number of try"),
),
(
"number_of_successes",
models.PositiveSmallIntegerField(
verbose_name="number of successes"
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="number_of_routine_done",
to="people.gymnast",
verbose_name="Gymnast",
),
),
(
"routine",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="number_of_try",
to="objective.routine",
verbose_name="Routine",
),
),
],
options={
'verbose_name': 'Number of routine done',
'verbose_name_plural': 'Number of routines done',
"verbose_name": "Number of routine done",
"verbose_name_plural": "Number of routines done",
},
),
migrations.CreateModel(
name='HeightWeight',
name="HeightWeight",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('height', models.DecimalField(decimal_places=1, max_digits=4, verbose_name='Height')),
('weight', models.DecimalField(decimal_places=1, max_digits=4, verbose_name='Weight')),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='height_weight', to='people.gymnast', verbose_name='Gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"height",
models.DecimalField(
decimal_places=1, max_digits=4, verbose_name="Height"
),
),
(
"weight",
models.DecimalField(
decimal_places=1, max_digits=4, verbose_name="Weight"
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="height_weight",
to="people.gymnast",
verbose_name="Gymnast",
),
),
],
options={
'verbose_name': 'Height & weight',
'verbose_name_plural': 'Heights & weights',
"verbose_name": "Height & weight",
"verbose_name_plural": "Heights & weights",
},
),
]

View File

@ -7,20 +7,35 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('objective', '0003_delete_gymnasthasroutine'),
('planning', '0001_initial'),
('followup', '0006_heightweight_numberofroutinedone'),
("objective", "0003_delete_gymnasthasroutine"),
("planning", "0001_initial"),
("followup", "0006_heightweight_numberofroutinedone"),
]
operations = [
migrations.AlterField(
model_name='accident',
name='skill',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='accident', to='objective.skill', verbose_name='Skill'),
model_name="accident",
name="skill",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="accident",
to="objective.skill",
verbose_name="Skill",
),
),
migrations.AlterField(
model_name='mindstate',
name='event',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mindstate', to='planning.event'),
model_name="mindstate",
name="event",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="mindstate",
to="planning.event",
),
),
]

View File

@ -6,14 +6,14 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('people', '0001_initial'),
('objective', '0003_delete_gymnasthasroutine'),
('followup', '0007_auto_20211213_1445'),
("people", "0001_initial"),
("objective", "0003_delete_gymnasthasroutine"),
("followup", "0007_auto_20211213_1445"),
]
operations = [
migrations.AlterUniqueTogether(
name='learnedskill',
unique_together={('gymnast', 'skill', 'date', 'cando')},
name="learnedskill",
unique_together={("gymnast", "skill", "date", "cando")},
),
]

View File

@ -19,6 +19,7 @@ ROUTINE_CHOICE = (
(8, "L4S"),
)
class Chrono(models.Model):
"""
Représente les chronos (de chandelles ou de série) enregistrés pour un(e) gymnaste.
@ -71,14 +72,13 @@ class Accident(Markdownizable):
"""
La classe `Accident` permet d'indiquer qu'un gymnaste a eu un accident, en liaison avec un
skill ou non.
"""
"""
class Meta:
verbose_name = "Accident"
verbose_name_plural = "Accidents"
# unique_together = ("gymnast", "skill", "date")
gymnast = models.ForeignKey(
Gymnast,
verbose_name="Gymnast",
@ -92,10 +92,12 @@ class Accident(Markdownizable):
on_delete=models.SET_NULL,
default=None,
blank=True,
null=True
null=True,
)
date = models.DateField(verbose_name="Date")
nb_week_off = models.SmallIntegerField(blank=True, null=True, verbose_name="# week off")
nb_week_off = models.SmallIntegerField(
blank=True, null=True, verbose_name="# week off"
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@ -114,21 +116,20 @@ class LearnedSkill(models.Model):
TYPE_CHOICES = ((0, "No"), (1, "With help"), (2, "Without help"), (3, "Chained"))
class Meta:
verbose_name = 'Learned Skill'
verbose_name_plural = 'Learned Skills'
unique_together = ('gymnast', 'skill', 'date', 'cando')
verbose_name = "Learned Skill"
verbose_name_plural = "Learned Skills"
unique_together = ("gymnast", "skill", "date", "cando")
gymnast = models.ForeignKey(
Gymnast,
verbose_name='gymnast',
related_name='known_skills',
verbose_name="gymnast",
related_name="known_skills",
on_delete=models.CASCADE,
)
skill = models.ForeignKey(
Skill,
verbose_name='Skill',
related_name='known_by',
verbose_name="Skill",
related_name="known_by",
on_delete=models.CASCADE,
)
cando = models.PositiveSmallIntegerField(
@ -146,11 +147,13 @@ class Point(models.Model):
ROUTINETYPE_CHOICE = ((0, "Routine 1"), (1, "Routine 2"), (2, "Final"))
gymnast = models.ForeignKey(Gymnast, on_delete=models.CASCADE, default=None, related_name="points")
gymnast = models.ForeignKey(
Gymnast, on_delete=models.CASCADE, default=None, related_name="points"
)
event = models.ForeignKey(Event, on_delete=models.CASCADE, default=None)
routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE)
point_execution = models.DecimalField(max_digits=5, decimal_places=3)
point_difficulty = (models.DecimalField(max_digits=3, decimal_places=1))
point_difficulty = models.DecimalField(max_digits=3, decimal_places=1)
point_time_of_flight = models.DecimalField(max_digits=5, decimal_places=3)
point_horizontal_displacement = models.DecimalField(max_digits=4, decimal_places=3)
penality = models.DecimalField(max_digits=3, decimal_places=1)
@ -170,21 +173,30 @@ class MindState(Markdownizable):
Représente l'état d'esprit psychologique d'un gymnaste
"""
gymnast = models.ForeignKey(Gymnast, on_delete=models.CASCADE, default=None, related_name="mindstate")
gymnast = models.ForeignKey(
Gymnast, on_delete=models.CASCADE, default=None, related_name="mindstate"
)
date = models.DateField(default=date.today, verbose_name="Date")
event = models.ForeignKey(Event, on_delete=models.SET_NULL, default=None, blank=True, null=True, related_name="mindstate")
event = models.ForeignKey(
Event,
on_delete=models.SET_NULL,
default=None,
blank=True,
null=True,
related_name="mindstate",
)
score = models.PositiveSmallIntegerField(verbose_name="Score")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return '%s - %s : %s' % (self.gymnast, self.date, self.score)
return "%s - %s : %s" % (self.gymnast, self.date, self.score)
class GymnastHasRoutine(models.Model):
"""
Classe représentant le lien entre les gymnastes et leurs séries.
"""
Classe représentant le lien entre les gymnastes et leurs séries.
"""
class Meta:
verbose_name = "Gymnast Has Routine"
@ -241,11 +253,19 @@ class NumberOfRoutineDone(models.Model):
choices=ROUTINE_CHOICE, verbose_name="Type", default="1"
)
number_of_try = models.PositiveSmallIntegerField(verbose_name="Number of try")
number_of_successes = models.PositiveSmallIntegerField(verbose_name="number of successes")
number_of_successes = models.PositiveSmallIntegerField(
verbose_name="number of successes"
)
date = models.DateField(default=date.today, verbose_name="Date")
def __str__(self):
return "%s - %s (%s) : %s | %s" % (self.gymnast, self.routine_type, self.routine, self.number_of_try, self.number_of_successes)
return "%s - %s (%s) : %s | %s" % (
self.gymnast,
self.routine_type,
self.routine,
self.number_of_try,
self.number_of_successes,
)
class HeightWeight(models.Model):

View File

@ -6,16 +6,24 @@ from . import views
# Chronos
chrono_urlpatterns = [
path(r"", views.chrono_listing, name='chrono_list'),
path(r"create/", views.chrono_create_or_update, name='chrono_create'),
path(r"create/<int:gymnastid>/", views.chrono_create_or_update, name='chrono_create_for_gymnast'),
path(r"", views.chrono_listing, name="chrono_list"),
path(r"create/", views.chrono_create_or_update, name="chrono_create"),
path(
r"create/<int:gymnastid>/",
views.chrono_create_or_update,
name="chrono_create_for_gymnast",
),
path(r"edit/<int:chronoid>/", views.chrono_create_or_update, name="chrono_update"),
]
# Learned Skill
learnedskill_urlpatterns = [
path(r"create/", views.learnedskill_create_or_update, name="learnedskill_create"),
path(r"create/<int:gymnastid>/", views.learnedskill_create_or_update, name='learnedskill_create'),
path(
r"create/<int:gymnastid>/",
views.learnedskill_create_or_update,
name="learnedskill_create",
),
path(r"new/", views.gymnast_learn_skill),
]
@ -36,7 +44,11 @@ accident_urlpatterns = [
path(r"search/", views.accident_listing),
path(r"", views.accident_listing, name="accident_list"),
path(r"add/", views.accident_create_or_update, name="accident_create"),
path(r"add/<int:gymnastid>", views.accident_create_or_update, name="accident_create_for_gymnast"),
path(
r"add/<int:gymnastid>",
views.accident_create_or_update,
name="accident_create_for_gymnast",
),
path(
r"edit/<int:accidentid>/",
views.accident_create_or_update,
@ -48,9 +60,17 @@ accident_urlpatterns = [
# Minstate
mindstate_urlpatterns = [
path(r"", views.mindstate_listing, name="mindstate_list"),
path(r"gymnast/<int:gymnastid>/", views.mindstate_listing, name="gymnast_mindstate_list"),
path(
r"gymnast/<int:gymnastid>/",
views.mindstate_listing,
name="gymnast_mindstate_list",
),
path(r"add/", views.mindstate_create_or_update, name="mindstate_create"),
path(r"add/<int:gymnastid>", views.mindstate_create_or_update, name="mindstate_create_for_gymnast"),
path(
r"add/<int:gymnastid>",
views.mindstate_create_or_update,
name="mindstate_create_for_gymnast",
),
path(
r"edit/<int:mindstateid>/",
views.mindstate_create_or_update,
@ -62,10 +82,14 @@ mindstate_urlpatterns = [
# Height & Weight
heightweight_urlpatterns = [
path(r"add/", views.heightweight_create_or_update, name="heightweight_create"),
path(r"add/<int:gymnastid>", views.heightweight_create_or_update, name="heightweight_create_for_gymnast"),
path(
r"add/<int:gymnastid>",
views.heightweight_create_or_update,
name="heightweight_create_for_gymnast",
),
path(
r"edit/<int:heightweightid>/",
views.heightweight_create_or_update,
name="heightweight_update",
),
]
]

View File

@ -8,25 +8,33 @@ from ultron.people.models import Gymnast
from ultron.planning.models import Event
from ultron.objective.models import Skill
from .models import Chrono, MindState, Point, Accident, LearnedSkill, HeightWeight
from .forms import ChronoForm, LearnedSkillForm, ScoreForm, AccidentForm, MindStateForm, HeightWeightForm
from .forms import (
ChronoForm,
LearnedSkillForm,
ScoreForm,
AccidentForm,
MindStateForm,
HeightWeightForm,
)
from datetime import datetime
import simplejson
@login_required
@require_http_methods(["GET"])
def chrono_listing(request):
""" Récupère la liste des chronos """
"""Récupère la liste des chronos"""
chrono_list = Chrono.objects.all()
context = {'chrono_list': chrono_list}
context = {"chrono_list": chrono_list}
return render(request, "followup/chronos/list.html", context)
@login_required
@require_http_methods(["GET", "POST"])
def chrono_create_or_update(request, chronoid=None, gymnastid=None):
""" Création ou modification d'un chrono """
"""Création ou modification d'un chrono"""
if chronoid:
chrono = get_object_or_404(Chrono, pk=chronoid)
@ -47,12 +55,14 @@ def chrono_create_or_update(request, chronoid=None, gymnastid=None):
if new_chrono.score_type == 1:
new_chrono.tof = new_chrono.score
else:
tof = round(( new_chrono.score * 13 ) / 15, 3) * 1000
tof = round((new_chrono.score * 13) / 15, 3) * 1000
tof = tof - (tof % 5)
new_chrono.tof = tof / 1000
new_chrono.tof = tof / 1000
new_chrono.save()
return HttpResponseRedirect("/gymnast/details/" + str(new_chrono.gymnast.id) + "/")
return HttpResponseRedirect(
"/gymnast/details/" + str(new_chrono.gymnast.id) + "/"
)
else:
if data is None and gymnastid is not None:
@ -80,7 +90,9 @@ def gymnast_learn_skill(request):
if gymnastid and skillid:
gymnast = Gymnast.objects.get(pk=gymnastid)
skill = Skill.objects.get(pk=skillid)
ls = LearnedSkill(gymnast=gymnast, skill=skill, cando=cando, date=datetime.now())
ls = LearnedSkill(
gymnast=gymnast, skill=skill, cando=cando, date=datetime.now()
)
ls.save()
return HttpResponse(status=200)
else:
@ -109,7 +121,9 @@ def learnedskill_create_or_update(request, gymnastid=None):
if learnedskill_form.is_valid():
learnedskill_form.save()
return HttpResponseRedirect("/gymnast/details/" + str(learnedskill_form.cleaned_data['gymnast'].id))
return HttpResponseRedirect(
"/gymnast/details/" + str(learnedskill_form.cleaned_data["gymnast"].id)
)
else:
print(learnedskill_form.errors)
@ -148,7 +162,9 @@ def score_create_or_update(request, scoreid=None, gymnastid=None):
form.save()
return HttpResponseRedirect(
# "/gymnast/" + str(form.cleaned_data["gymnast"].id) + "/tab/scores/"
"/gymnast/details/" + str(form.cleaned_data["gymnast"].id) + "/"
"/gymnast/details/"
+ str(form.cleaned_data["gymnast"].id)
+ "/"
)
# return HttpResponseRedirect("/score/")
else:
@ -274,21 +290,18 @@ def mindstate_create_or_update(request, mindstateid=None, gymnastid=None, eventi
if mindstateid:
mindstate = get_object_or_404(MindState, pk=mindstateid)
data = {
"gymnast_related": mindstate.gymnast,
"event_related": mindstate.event
}
data = {"gymnast_related": mindstate.gymnast, "event_related": mindstate.event}
else:
mindstate = None
data = {}
if gymnastid is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnastid)
data['gymnast'] = gymnastid
data['gymnast_related'] = str(gymnast)
data["gymnast"] = gymnastid
data["gymnast_related"] = str(gymnast)
if eventid is not None:
event = get_object_or_404(Event, pk=eventid)
data['event'] = eventid
data['event_related'] = str(event)
data["event"] = eventid
data["event_related"] = str(event)
if request.method == "POST":
form = MindStateForm(request.POST, instance=mindstate)
@ -327,27 +340,27 @@ def heightweight_create_or_update(request, heightweightid=None, gymnastid=None):
if heightweightid:
heightweight = get_object_or_404(HeightWeight, pk=heightweightid)
data = {
"gymnast_related": heightweight.gymnast
}
data = {"gymnast_related": heightweight.gymnast}
else:
mindstate = None
data = {}
if gymnastid:
gymnast = get_object_or_404(Gymnast, pk=gymnastid)
data['gymnast'] = gymnastid
data['gymnast_related'] = str(gymnast)
data["gymnast"] = gymnastid
data["gymnast_related"] = str(gymnast)
if request.method == "POST":
height_weight_form = HeightWeightForm(request.POST, instance=heightweight)
if height_weight_form.is_valid():
height_weight_form.save()
return HttpResponseRedirect("/gymnast/details/" + str(height_weight_form.cleaned_data['gymnast'].id))
return HttpResponseRedirect(
"/gymnast/details/" + str(height_weight_form.cleaned_data["gymnast"].id)
)
else:
print(height_weight_form.errors)
form = HeightWeightForm(instance=heightweight, initial=data)
context = {"form": form, "gymnastid": gymnastid, "heightweightid": heightweightid}
return render(request, "followup/heightweight/create.html", context)
return render(request, "followup/heightweight/create.html", context)

View File

@ -5,29 +5,29 @@ from .models import Place, Club, Country
class CountryAdmin(admin.ModelAdmin):
model = Country
list_display = ('name', 'iso3', 'iso2')
ordering = ('name',)
search_fields = ('name', 'nationality')
list_display = ("name", "iso3", "iso2")
ordering = ("name",)
search_fields = ("name", "nationality")
class ClubAdmin(admin.ModelAdmin):
model = Club
list_display = ('name', 'acronym', 'place', 'active')
ordering = ('name',)
list_filter = ('active',)
search_fields = ('name',)
autocomplete_fields = ('place',)
list_display = ("name", "acronym", "place", "active")
ordering = ("name",)
list_filter = ("active",)
search_fields = ("name",)
autocomplete_fields = ("place",)
class PlaceAdmin(admin.ModelAdmin):
model = Place
list_display = ('name', 'address', 'postal', 'city', 'active')
ordering = ('name',)
list_filter = ('active',)
search_fields = ('name', 'address', 'postal', 'city')
autocomplete_fields = ('country',)
list_display = ("name", "address", "postal", "city", "active")
ordering = ("name",)
list_filter = ("active",)
search_fields = ("name", "address", "postal", "city")
autocomplete_fields = ("country",)
admin.site.register(Place, PlaceAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class LocationConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.location'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.location"

View File

@ -8,53 +8,95 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
]
dependencies = []
operations = [
migrations.CreateModel(
name='Country',
name="Country",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='English name')),
('nationality', models.CharField(max_length=255, verbose_name='Nationality')),
('iso2', models.CharField(max_length=2)),
('iso3', models.CharField(max_length=3)),
('isonum', models.PositiveSmallIntegerField()),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255, verbose_name="English name")),
(
"nationality",
models.CharField(max_length=255, verbose_name="Nationality"),
),
("iso2", models.CharField(max_length=2)),
("iso3", models.CharField(max_length=3)),
("isonum", models.PositiveSmallIntegerField()),
],
options={
'verbose_name': 'Country',
'verbose_name_plural': 'Countries',
"verbose_name": "Country",
"verbose_name_plural": "Countries",
},
),
migrations.CreateModel(
name='Place',
name="Place",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Name')),
('address', models.CharField(max_length=255, verbose_name='Address')),
('postal', models.PositiveIntegerField(verbose_name='Postal code')),
('city', models.CharField(max_length=255, verbose_name='City')),
('active', models.BooleanField(default=1, verbose_name='Active')),
('country', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='location.country', verbose_name='Country')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255, verbose_name="Name")),
("address", models.CharField(max_length=255, verbose_name="Address")),
("postal", models.PositiveIntegerField(verbose_name="Postal code")),
("city", models.CharField(max_length=255, verbose_name="City")),
("active", models.BooleanField(default=1, verbose_name="Active")),
(
"country",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="location.country",
verbose_name="Country",
),
),
],
options={
'verbose_name': 'Place',
'verbose_name_plural': 'Places',
"verbose_name": "Place",
"verbose_name_plural": "Places",
},
),
migrations.CreateModel(
name='Club',
name="Club",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Name')),
('acronym', models.CharField(max_length=4, verbose_name='Acronym')),
('active', models.BooleanField(default=1, verbose_name='Active')),
('place', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='location.place', verbose_name='Place')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255, verbose_name="Name")),
("acronym", models.CharField(max_length=4, verbose_name="Acronym")),
("active", models.BooleanField(default=1, verbose_name="Active")),
(
"place",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="location.place",
verbose_name="Place",
),
),
],
options={
'verbose_name': 'Club',
'verbose_name_plural': 'Clubs',
"verbose_name": "Club",
"verbose_name_plural": "Clubs",
},
),
]

View File

@ -18,5 +18,5 @@ country_urlpatterns = [
club_urlpatterns = [
path(r"", views.club_listing, name="club_list"),
path(r"lookup/", views.club_lookup),
path(r"lookup/", views.club_lookup),
]

View File

@ -1,5 +1,3 @@
from datetime import datetime, timedelta, date
from functools import reduce
import operator
@ -64,8 +62,7 @@ def country_lookup(request):
if pattern is not None and len(pattern) >= 3:
results = Country.objects.filter(
Q(name__icontains=pattern)
| Q(nationality__icontains=pattern)
Q(name__icontains=pattern) | Q(nationality__icontains=pattern)
)
country_list = [{"id": x.id, "Label": str(x)} for x in results]
@ -126,8 +123,7 @@ def place_details(request, placeid):
@login_required
@require_http_methods(["GET"])
def club_listing(request):
"""Liste tous les clubs connus
"""
"""Liste tous les clubs connus"""
club_list = Club.objects.all()
context = {"club_list": club_list}
return render(request, "locations/clubs/list.html", context)
@ -162,6 +158,7 @@ def chooseStatistics(request):
"""
pass
# year = int(request.GET.get("year", date.today().year))
# clubid = request.GET.get("clubid", None)
@ -188,6 +185,8 @@ def club_statistics(request, clubid):
.. todo:: tenir compte de la saison.
"""
pass
# courses = Course.objects.filter(club__in=clubid).order_by(
# "iso_day_number", "hour_begin"
# )

View File

@ -1,24 +1,16 @@
from django.contrib import admin
from .models import (
Educative,
TouchPosition,
Skill,
Routine,
RoutineSkill,
Plan
)
from .models import Educative, TouchPosition, Skill, Routine, RoutineSkill, Plan
from django_extensions.admin import ForeignKeyAutocompleteAdmin
class TouchPositionAdmin(admin.ModelAdmin):
model = TouchPosition
list_display = ('long_label', 'short_label', 'allowed_in_competition', 'is_default')
ordering = ('long_label', 'short_label')
search_fields = ('long_label', 'short_label')
list_filter = ('allowed_in_competition',)
list_display = ("long_label", "short_label", "allowed_in_competition", "is_default")
ordering = ("long_label", "short_label")
search_fields = ("long_label", "short_label")
list_filter = ("allowed_in_competition",)
def duplicate_skill(self, SkillAdmin, request, queryset):
@ -31,61 +23,61 @@ class SkillAdmin(ForeignKeyAutocompleteAdmin):
model = Skill
fields = (
'long_label',
'short_label',
'informations',
'departure',
'landing',
'rotation_type',
'position',
'rotation',
'twist',
'difficulty',
'level',
'rank',
'notation',
'simplified_notation',
'is_competitive',
'age_boy',
'age_girl',
'prerequisites',
'educatives',
"long_label",
"short_label",
"informations",
"departure",
"landing",
"rotation_type",
"position",
"rotation",
"twist",
"difficulty",
"level",
"rank",
"notation",
"simplified_notation",
"is_competitive",
"age_boy",
"age_girl",
"prerequisites",
"educatives",
)
list_display = (
'long_label',
'difficulty',
'is_competitive',
'level',
'rank',
'notation',
'age_boy',
'age_girl',
"long_label",
"difficulty",
"is_competitive",
"level",
"rank",
"notation",
"age_boy",
"age_girl",
)
ordering = ('long_label', 'short_label')
search_fields = ('rank', 'long_label', 'short_label')
ordering = ("long_label", "short_label")
search_fields = ("rank", "long_label", "short_label")
list_filter = (
'is_competitive',
'departure',
'landing',
'rotation_type',
'rank',
'rotation',
'level',
'difficulty',
'age_boy',
'age_girl',
"is_competitive",
"departure",
"landing",
"rotation_type",
"rank",
"rotation",
"level",
"difficulty",
"age_boy",
"age_girl",
)
filter_horizontal = ('educatives', 'prerequisites')
filter_horizontal = ("educatives", "prerequisites")
duplicate_skill.short_description = 'Duplicate selected record'
duplicate_skill.short_description = "Duplicate selected record"
class Media:
js = (
'js/core/jquery-3.6.0.min.js',
'js/admin/skill.js',
"js/core/jquery-3.6.0.min.js",
"js/admin/skill.js",
)
@ -93,39 +85,39 @@ class RoutineAdmin(admin.ModelAdmin):
model = Routine
fields = (
'long_label',
'short_label',
'difficulty',
'level',
'rank',
'educatives',
'prerequisites',
'age_boy',
'age_girl',
'active',
'is_competitive',
"long_label",
"short_label",
"difficulty",
"level",
"rank",
"educatives",
"prerequisites",
"age_boy",
"age_girl",
"active",
"is_competitive",
)
list_display = (
'long_label',
'short_label',
'is_competitive',
'active',
'level',
'rank',
'difficulty',
"long_label",
"short_label",
"is_competitive",
"active",
"level",
"rank",
"difficulty",
)
list_filter = ('level', 'difficulty', 'is_competitive', 'active')
list_filter = ("level", "difficulty", "is_competitive", "active")
search_fields = (
'long_label',
'short_label',
"long_label",
"short_label",
)
filter_horizontal = ('educatives',)
filter_horizontal = ("educatives",)
class Media:
js = (
'js/core/jquery-3.6.0.min.js',
'js/admin/routine.js',
"js/core/jquery-3.6.0.min.js",
"js/admin/routine.js",
)
# TODO: ne proposer QUE les SKILL comme educatif
@ -138,24 +130,24 @@ class RoutineAdmin(admin.ModelAdmin):
class RoutineSkillAdmin(admin.ModelAdmin):
model = RoutineSkill
list_display = ('routine', 'skill', 'rank')
list_display = ("routine", "skill", "rank")
search_fields = (
'routine__long_label',
'routine__short_label',
"routine__long_label",
"routine__short_label",
)
ordering = ('routine', )
ordering = ("routine",)
class PlanAdmin(admin.ModelAdmin):
model = Plan
list_display = ('gymnast', 'date', 'educative')
list_filter = ('gymnast', )
list_display = ("gymnast", "date", "educative")
list_filter = ("gymnast",)
search_fields = (
'gymnast__firstname',
'gymnast__lastname',
'educative__long_label',
'educative__short_label',
"gymnast__firstname",
"gymnast__lastname",
"educative__long_label",
"educative__short_label",
)
@ -163,4 +155,4 @@ admin.site.register(TouchPosition, TouchPositionAdmin)
admin.site.register(Skill, SkillAdmin)
admin.site.register(Routine, RoutineAdmin)
admin.site.register(RoutineSkill, RoutineSkillAdmin)
admin.site.register(Plan, PlanAdmin)
admin.site.register(Plan, PlanAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class ObjectiveConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.objective'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.objective"

View File

@ -6,23 +6,30 @@ from .models import Routine, RoutineSkill, Plan
class RoutineForm(forms.ModelForm):
class Meta:
model = Routine
fields = ('long_label', 'short_label', 'difficulty', 'level', 'active', 'informations')
fields = (
"long_label",
"short_label",
"difficulty",
"level",
"active",
"informations",
)
widgets = {
'long_label': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Routine\'s long name'}
"long_label": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Routine's long name"}
),
'short_label': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Routine\'s short name'}
"short_label": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Routine's short name"}
),
'informations': forms.Textarea(
"informations": forms.Textarea(
attrs={
'class': 'form-control',
'placeholder': 'Informations about the psychological state of mind : context (why, where, …), possible consequencies, …',
"class": "form-control",
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …",
}
),
'difficulty': forms.HiddenInput(),
'level': forms.HiddenInput(),
'active': forms.HiddenInput(),
"difficulty": forms.HiddenInput(),
"level": forms.HiddenInput(),
"active": forms.HiddenInput(),
}
@ -33,15 +40,15 @@ class PlanForm(forms.ModelForm):
class Meta:
model = Plan
fields = ('date', 'gymnast', 'educative')
fields = ("date", "gymnast", "educative")
widgets = {
'gymnast': forms.HiddenInput(),
'educative': forms.HiddenInput(),
'date': forms.TextInput(
"gymnast": forms.HiddenInput(),
"educative": forms.HiddenInput(),
"date": forms.TextInput(
attrs={
'class': 'form-control datepicker',
'placeholder': date.today().strftime('%Y-%m-%d'),
'value': date.today().strftime('%Y-%m-%d'),
"class": "form-control datepicker",
"placeholder": date.today().strftime("%Y-%m-%d"),
"value": date.today().strftime("%Y-%m-%d"),
}
),
}
@ -49,9 +56,9 @@ class PlanForm(forms.ModelForm):
gymnast_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching gymnast…',
'data-ref': '#id_gymnast',
"class": "form-control",
"placeholder": "Searching gymnast…",
"data-ref": "#id_gymnast",
}
)
)
@ -59,9 +66,9 @@ class PlanForm(forms.ModelForm):
educative_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching skill…',
'data-ref': '#id_skill',
"class": "form-control",
"placeholder": "Searching skill…",
"data-ref": "#id_skill",
}
)
)
)

View File

@ -9,94 +9,266 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
]
dependencies = []
operations = [
migrations.CreateModel(
name='Educative',
name="Educative",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('informations', models.TextField(blank=True, help_text='Only MarkDown is authorized', null=True, verbose_name='Comments')),
('long_label', models.CharField(max_length=255, verbose_name='Long Name')),
('short_label', models.CharField(max_length=255, verbose_name='Short Name')),
('difficulty', models.DecimalField(decimal_places=1, default=0.0, max_digits=3, verbose_name='Difficulty')),
('level', models.PositiveSmallIntegerField(default=0, verbose_name='Level')),
('rank', models.PositiveSmallIntegerField(default=0, verbose_name='Rank')),
('age_boy', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name="Boy's age")),
('age_girl', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name="Girl's age")),
('educatives', models.ManyToManyField(blank=True, related_name='educatives_of', to='objective.Educative')),
('prerequisites', models.ManyToManyField(blank=True, related_name='prerequisite_of', to='objective.Educative')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"informations",
models.TextField(
blank=True,
help_text="Only MarkDown is authorized",
null=True,
verbose_name="Comments",
),
),
(
"long_label",
models.CharField(max_length=255, verbose_name="Long Name"),
),
(
"short_label",
models.CharField(max_length=255, verbose_name="Short Name"),
),
(
"difficulty",
models.DecimalField(
decimal_places=1,
default=0.0,
max_digits=3,
verbose_name="Difficulty",
),
),
(
"level",
models.PositiveSmallIntegerField(default=0, verbose_name="Level"),
),
(
"rank",
models.PositiveSmallIntegerField(default=0, verbose_name="Rank"),
),
(
"age_boy",
models.PositiveSmallIntegerField(
blank=True, null=True, verbose_name="Boy's age"
),
),
(
"age_girl",
models.PositiveSmallIntegerField(
blank=True, null=True, verbose_name="Girl's age"
),
),
(
"educatives",
models.ManyToManyField(
blank=True,
related_name="educatives_of",
to="objective.Educative",
),
),
(
"prerequisites",
models.ManyToManyField(
blank=True,
related_name="prerequisite_of",
to="objective.Educative",
),
),
],
options={
'verbose_name': 'Educatif',
'verbose_name_plural': 'Educatifs',
'ordering': ['long_label', 'short_label'],
"verbose_name": "Educatif",
"verbose_name_plural": "Educatifs",
"ordering": ["long_label", "short_label"],
},
),
migrations.CreateModel(
name='TouchPosition',
name="TouchPosition",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('long_label', models.CharField(max_length=30, verbose_name='Long label')),
('short_label', models.CharField(max_length=15, verbose_name='Short label')),
('allowed_in_competition', models.BooleanField(verbose_name='Allowed in competition')),
('is_default', models.BooleanField(verbose_name='Défault ?')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"long_label",
models.CharField(max_length=30, verbose_name="Long label"),
),
(
"short_label",
models.CharField(max_length=15, verbose_name="Short label"),
),
(
"allowed_in_competition",
models.BooleanField(verbose_name="Allowed in competition"),
),
("is_default", models.BooleanField(verbose_name="Défault ?")),
],
options={
'verbose_name': 'Landing',
'verbose_name_plural': 'Landings',
'ordering': ['long_label', 'short_label', 'is_default', 'allowed_in_competition'],
"verbose_name": "Landing",
"verbose_name_plural": "Landings",
"ordering": [
"long_label",
"short_label",
"is_default",
"allowed_in_competition",
],
},
),
migrations.CreateModel(
name='Routine',
name="Routine",
fields=[
('educative_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='objective.educative')),
('active', models.BooleanField()),
('is_competitive', models.BooleanField(default=False)),
(
"educative_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="objective.educative",
),
),
("active", models.BooleanField()),
("is_competitive", models.BooleanField(default=False)),
],
options={
'verbose_name': 'Routine',
'verbose_name_plural': 'Routines',
"verbose_name": "Routine",
"verbose_name_plural": "Routines",
},
bases=('objective.educative',),
bases=("objective.educative",),
),
migrations.CreateModel(
name='Skill',
name="Skill",
fields=[
('educative_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='objective.educative')),
('position', models.CharField(choices=[('0', 'None'), ('o', 'Tuck'), ('c', 'Puck'), ('<', 'Pike'), ('/', 'Straight'), ('//', 'Straddle')], max_length=2)),
('rotation_type', models.PositiveSmallIntegerField(choices=[(0, 'None'), (1, 'Frontward'), (2, 'Backward')], verbose_name='Type de rotation')),
('rotation', models.PositiveSmallIntegerField(verbose_name='1/4 de rotation')),
('twist', models.PositiveSmallIntegerField(verbose_name='1/2 Vrille')),
('notation', models.CharField(max_length=25)),
('simplified_notation', models.CharField(max_length=25, verbose_name='Notation simplifiée')),
('is_competitive', models.BooleanField(default=False)),
('departure', models.ForeignKey(default=ultron.objective.models.get_default_position, on_delete=django.db.models.deletion.CASCADE, related_name='depart_of', to='objective.touchposition', verbose_name='Take-off position')),
('landing', models.ForeignKey(default=ultron.objective.models.get_default_position, on_delete=django.db.models.deletion.CASCADE, related_name='landing_of', to='objective.touchposition', verbose_name='Landing position')),
(
"educative_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="objective.educative",
),
),
(
"position",
models.CharField(
choices=[
("0", "None"),
("o", "Tuck"),
("c", "Puck"),
("<", "Pike"),
("/", "Straight"),
("//", "Straddle"),
],
max_length=2,
),
),
(
"rotation_type",
models.PositiveSmallIntegerField(
choices=[(0, "None"), (1, "Frontward"), (2, "Backward")],
verbose_name="Type de rotation",
),
),
(
"rotation",
models.PositiveSmallIntegerField(verbose_name="1/4 de rotation"),
),
("twist", models.PositiveSmallIntegerField(verbose_name="1/2 Vrille")),
("notation", models.CharField(max_length=25)),
(
"simplified_notation",
models.CharField(max_length=25, verbose_name="Notation simplifiée"),
),
("is_competitive", models.BooleanField(default=False)),
(
"departure",
models.ForeignKey(
default=ultron.objective.models.get_default_position,
on_delete=django.db.models.deletion.CASCADE,
related_name="depart_of",
to="objective.touchposition",
verbose_name="Take-off position",
),
),
(
"landing",
models.ForeignKey(
default=ultron.objective.models.get_default_position,
on_delete=django.db.models.deletion.CASCADE,
related_name="landing_of",
to="objective.touchposition",
verbose_name="Landing position",
),
),
],
options={
'verbose_name': 'Skill',
'verbose_name_plural': 'Skills',
"verbose_name": "Skill",
"verbose_name_plural": "Skills",
},
bases=('objective.educative',),
bases=("objective.educative",),
),
migrations.CreateModel(
name='RoutineSkill',
name="RoutineSkill",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rank', models.PositiveSmallIntegerField()),
('routine', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='skill_links', to='objective.routine')),
('skill', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='routine_links', to='objective.skill')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("rank", models.PositiveSmallIntegerField()),
(
"routine",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
related_name="skill_links",
to="objective.routine",
),
),
(
"skill",
models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
related_name="routine_links",
to="objective.skill",
),
),
],
options={
'ordering': ('rank',),
"ordering": ("rank",),
},
),
migrations.AddField(
model_name='routine',
name='jumps',
field=models.ManyToManyField(through='objective.RoutineSkill', to='objective.Skill', verbose_name='routine'),
model_name="routine",
name="jumps",
field=models.ManyToManyField(
through="objective.RoutineSkill",
to="objective.Skill",
verbose_name="routine",
),
),
]

View File

@ -8,24 +8,78 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0001_initial'),
('objective', '0001_initial'),
("people", "0001_initial"),
("objective", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='GymnastHasRoutine',
name="GymnastHasRoutine",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('routine_type', models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S')], default='1', verbose_name='Type')),
('datebegin', models.DateField(default=datetime.date.today, verbose_name='Date begin')),
('dateend', models.DateField(blank=True, default=datetime.date.today, null=True, verbose_name='Date end')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='has_routine', to='people.gymnast', verbose_name='Gymnast')),
('routine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='used_by_gymnast', to='objective.routine', verbose_name='Routine')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"routine_type",
models.PositiveSmallIntegerField(
choices=[
(0, "Other"),
(1, "L1"),
(2, "L2"),
(3, "L3"),
(4, "L4"),
(5, "L1S"),
(6, "L2S"),
(7, "L3S"),
(8, "L4S"),
],
default="1",
verbose_name="Type",
),
),
(
"datebegin",
models.DateField(
default=datetime.date.today, verbose_name="Date begin"
),
),
(
"dateend",
models.DateField(
blank=True,
default=datetime.date.today,
null=True,
verbose_name="Date end",
),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="has_routine",
to="people.gymnast",
verbose_name="Gymnast",
),
),
(
"routine",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="used_by_gymnast",
to="objective.routine",
verbose_name="Routine",
),
),
],
options={
'verbose_name': 'Gymnast Has Routine',
'verbose_name_plural': 'Gymnast Has Routines',
"verbose_name": "Gymnast Has Routine",
"verbose_name_plural": "Gymnast Has Routines",
},
),
]

View File

@ -6,11 +6,11 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('objective', '0002_gymnasthasroutine'),
("objective", "0002_gymnasthasroutine"),
]
operations = [
migrations.DeleteModel(
name='GymnastHasRoutine',
name="GymnastHasRoutine",
),
]

View File

@ -8,24 +8,51 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0001_initial'),
('objective', '0003_delete_gymnasthasroutine'),
("people", "0001_initial"),
("objective", "0003_delete_gymnasthasroutine"),
]
operations = [
migrations.CreateModel(
name='Plan',
name="Plan",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
('educative', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='plan', to='objective.educative', verbose_name='Skill')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='todo', to='people.gymnast', verbose_name='Gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"date",
models.DateField(default=datetime.date.today, verbose_name="Date"),
),
(
"educative",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="plan",
to="objective.educative",
verbose_name="Skill",
),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="todo",
to="people.gymnast",
verbose_name="Gymnast",
),
),
],
options={
'verbose_name': 'Plan',
'verbose_name_plural': 'Plans',
'ordering': ['date', 'educative', 'gymnast'],
'unique_together': {('gymnast', 'educative')},
"verbose_name": "Plan",
"verbose_name_plural": "Plans",
"ordering": ["date", "educative", "gymnast"],
"unique_together": {("gymnast", "educative")},
},
),
]

View File

@ -45,7 +45,7 @@ class Educative(Markdownizable):
class TouchPosition(models.Model):
"""
Classe représentant les différentes position d'arrivée/départ (landing position) en trampoline.
Classe représentant les différentes position d'arrivée/départ (landing position) en trampoline.
"""
class Meta:
@ -274,8 +274,8 @@ class RoutineSkill(models.Model):
class Plan(models.Model):
"""
Classe représentant les objectifs qu'un gymnaste devra savoir faire pour une date donnée.
"""
Classe représentant les objectifs qu'un gymnaste devra savoir faire pour une date donnée.
"""
class Meta:
verbose_name = "Plan"
@ -284,10 +284,10 @@ class Plan(models.Model):
unique_together = ("gymnast", "educative")
gymnast = models.ForeignKey(
'people.Gymnast',
"people.Gymnast",
verbose_name="Gymnast",
related_name="todo",
on_delete=models.CASCADE
on_delete=models.CASCADE,
)
educative = models.ForeignKey(
Educative,
@ -302,4 +302,4 @@ class Plan(models.Model):
self.gymnast,
self.educative.short_label,
self.date,
)
)

View File

@ -24,7 +24,6 @@ routine_urlpatterns = [
r"edit/<int:routineid>/", views.routine_create_or_update, name="routine_update"
),
path(r"<int:routineid>", views.routine_details, name="routine_details"),
path(r"compose/<int:routineid>/", views.compose_routine, name="compose_routine"),
path(
r"<int:routineid>/add_skill/<int:skillid>/order/<int:order>/",
@ -43,20 +42,16 @@ routine_urlpatterns = [
# Plan
plan_urlpatterns = [
path(
r"add/",
views.plan_create_or_update,
name="plan_create"
),
path(r"add/", views.plan_create_or_update, name="plan_create"),
path(
r"add/<int:gymnast_id>/",
views.plan_create_or_update,
name="add_plan_for_gymnast"
name="add_plan_for_gymnast",
),
path(
r"add/<int:gymnast_id>/<int:skill_id>/",
views.plan_create_or_update,
name="add_skill_for_gymnast"
name="add_skill_for_gymnast",
),
path(
r"edit/<int:plan_id>/",

View File

@ -6,7 +6,7 @@ from django.db.models import Q
from django.urls import reverse
from ultron.people.models import Gymnast
from .models import Skill, Routine, RoutineSkill
from .models import Skill, Routine, RoutineSkill, Plan
from .forms import RoutineForm, PlanForm
import simplejson
@ -21,14 +21,16 @@ def skill_lookup(request):
"""
results = []
pattern = request.GET.get('pattern', None)
pattern = request.GET.get("pattern", None)
# Ignore queries shorter than length 2
if pattern is not None and len(pattern) > 2:
model_results = Skill.objects.filter(
Q(short_label__icontains=pattern) | Q(long_label__icontains=pattern)
)
results = [{'ID': x.id, 'Name': str(x), 'Notation': x.notation} for x in model_results]
results = [
{"ID": x.id, "Name": str(x), "Notation": x.notation} for x in model_results
]
json = simplejson.dumps(results)
return HttpResponse(json, content_type="application/json")
@ -58,8 +60,8 @@ def skill_listing(request, field=None, expression=None, value=None, level=None):
else:
skill_list = Skill.objects.all()
context = {'skill_list': skill_list}
return render(request, 'objectives/skills/list.html', context)
context = {"skill_list": skill_list}
return render(request, "objectives/skills/list.html", context)
@login_required
@ -167,7 +169,10 @@ def routine_details(request, routineid):
if skill_link.skill.age_boy is not None and skill_link.skill.age_boy > age_boy:
age_boy = skill_link.skill.age_boy
if skill_link.skill.age_girl is not None and skill_link.skill.age_girl > age_girl:
if (
skill_link.skill.age_girl is not None
and skill_link.skill.age_girl > age_girl
):
age_girl = skill_link.skill.age_girl
if routine.skill_links.all().count() != 10:
@ -198,7 +203,7 @@ def routine_details(request, routineid):
@login_required
@require_http_methods(["GET", "POST"])
def routine_create_or_update(request, routineid=None):
""" Création d'une série.
"""Création d'une série.
Args:
routine_id (int): identifiant d'un object de classe <routine>.
@ -266,7 +271,7 @@ def link_skill_to_routine(request, routineid, skillid, order):
@login_required
@require_http_methods(["GET", "POST"])
def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None):
""" Création d'un plan.
"""Création d'un plan.
Args:
plan_id (int): identifiant d'un plan (classe <Plan>).
@ -277,10 +282,10 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None)
if plan_id:
plan = get_object_or_404(Plan, pk=plan_id)
data = {
'gymnast': plan.gymnast.id,
'gymnast_related': str(chrono.gymnast),
'skill': plan.skill.id,
'skill_related': str(plan.skill),
"gymnast": plan.gymnast.id,
"gymnast_related": str(plan.gymnast),
"skill": plan.skill.id,
"skill_related": str(plan.skill),
}
else:
plan = None
@ -288,15 +293,15 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None)
if gymnast_id:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data['gymnast'] = gymnast_id
data['gymnast_related'] = str(gymnast)
data["gymnast"] = gymnast_id
data["gymnast_related"] = str(gymnast)
if skill_id:
skill = get_object_or_404(Skill, pk=skill_id)
data['educative'] = skill_id
data['educative_related'] = str(skill)
data["educative"] = skill_id
data["educative_related"] = str(skill)
if request.method == 'POST':
if request.method == "POST":
form = PlanForm(request.POST, instance=plan)
if form.is_valid():
@ -307,4 +312,4 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None)
form = PlanForm(instance=plan, initial=data)
context = {"form": form, "plan_id": plan_id}
return render(request, "objectives/plan/create.html", context)
return render(request, "objectives/plan/create.html", context)

View File

@ -6,19 +6,20 @@ class GymnastAdmin(admin.ModelAdmin):
model = Gymnast
fields = (
'last_name',
'first_name',
'birthdate',
'gender',
'trainings_by_week',
'hours_by_week',
'is_active',
"last_name",
"first_name",
"birthdate",
"gender",
"trainings_by_week",
"hours_by_week",
"is_active",
# 'club'
)
list_display = ('last_name', 'first_name', 'age', 'is_active') # , 'club'
list_filter = ('gender', 'is_active') # , 'club'
search_fields = ('last_name', 'first_name')
list_display = ("last_name", "first_name", "age", "is_active") # , 'club'
list_filter = ("gender", "is_active") # , 'club'
search_fields = ("last_name", "first_name")
# autocomplete_fields = ('club',)
admin.site.register(Gymnast, GymnastAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class PeopleConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.people'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.people"

View File

@ -1,51 +1,48 @@
'''Formulaires de gestion des données entrantes pour les gymnastes et accidents.'''
"""Formulaires de gestion des données entrantes pour les gymnastes et accidents."""
from django import forms
from .models import (
Gymnast
)
from .models import Gymnast
class GymnastForm(forms.ModelForm):
class Meta:
model = Gymnast
fields = (
'last_name',
'first_name',
'birthdate',
'gender',
'is_active',
'club',
'trainings_by_week',
'hours_by_week'
"last_name",
"first_name",
"birthdate",
"gender",
"is_active",
"club",
"trainings_by_week",
"hours_by_week",
)
widgets = {
'last_name': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Lastname'}
"last_name": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Lastname"}
),
'first_name': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Firstname'}
"first_name": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Firstname"}
),
'birthdate': forms.DateInput(attrs={'class': 'form-control datepicker'}),
'gender': forms.Select(attrs={'class': 'form-control'}),
'club': forms.HiddenInput(),
'trainings_by_week': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': '5'}
"birthdate": forms.DateInput(attrs={"class": "form-control datepicker"}),
"gender": forms.Select(attrs={"class": "form-control"}),
"club": forms.HiddenInput(),
"trainings_by_week": forms.TextInput(
attrs={"class": "form-control", "placeholder": "5"}
),
'hours_by_week': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': '11,5'}
"hours_by_week": forms.TextInput(
attrs={"class": "form-control", "placeholder": "11,5"}
),
}
club_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching club…',
'data-ref': '#id_club',
"class": "form-control",
"placeholder": "Searching club…",
"data-ref": "#id_club",
}
)
)

View File

@ -9,27 +9,62 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('location', '0001_initial'),
("location", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='Gymnast',
name="Gymnast",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('informations', models.TextField(blank=True, help_text='Only MarkDown is authorized', null=True, verbose_name='Comments')),
('last_name', models.CharField(max_length=40)),
('first_name', models.CharField(max_length=25)),
('birthdate', models.DateField(verbose_name='Date de naissance')),
('gender', models.PositiveSmallIntegerField(choices=[(0, 'Male'), (1, 'Female')], verbose_name='Sexe')),
('is_active', models.BooleanField(default=1, verbose_name='Active')),
('trainings_by_week', models.PositiveSmallIntegerField(verbose_name='# Training by week')),
('hours_by_week', models.PositiveSmallIntegerField(verbose_name='# Hours by week')),
('club', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='gymnast', to='location.club')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"informations",
models.TextField(
blank=True,
help_text="Only MarkDown is authorized",
null=True,
verbose_name="Comments",
),
),
("last_name", models.CharField(max_length=40)),
("first_name", models.CharField(max_length=25)),
("birthdate", models.DateField(verbose_name="Date de naissance")),
(
"gender",
models.PositiveSmallIntegerField(
choices=[(0, "Male"), (1, "Female")], verbose_name="Sexe"
),
),
("is_active", models.BooleanField(default=1, verbose_name="Active")),
(
"trainings_by_week",
models.PositiveSmallIntegerField(verbose_name="# Training by week"),
),
(
"hours_by_week",
models.PositiveSmallIntegerField(verbose_name="# Hours by week"),
),
(
"club",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="gymnast",
to="location.club",
),
),
],
options={
'verbose_name': 'Gymnast',
'verbose_name_plural': 'Gymnasts',
"verbose_name": "Gymnast",
"verbose_name_plural": "Gymnasts",
},
),
]

View File

@ -11,8 +11,8 @@ from ultron.tools.models import Markdownizable
class Gymnast(Markdownizable):
"""Représente un gymnaste.
Un gymnaste peut être actif ou inactif.
"""
Un gymnaste peut être actif ou inactif.
"""
class Meta:
verbose_name = "Gymnast"
@ -30,7 +30,9 @@ class Gymnast(Markdownizable):
club = models.ForeignKey(
Club, null=True, on_delete=models.SET_NULL, related_name="gymnast"
)
trainings_by_week = models.PositiveSmallIntegerField(verbose_name="# Training by week")
trainings_by_week = models.PositiveSmallIntegerField(
verbose_name="# Training by week"
)
hours_by_week = models.PositiveSmallIntegerField(verbose_name="# Hours by week")
def __str__(self):
@ -40,16 +42,16 @@ class Gymnast(Markdownizable):
def next_birthday(self):
"""Définit la prochaine date (de fête) d'anniversaire pour cette personne.
Returns:
Soit le jour/mois pour cette année
Soit le jour/mois pour l'année prochaine.
Returns:
Soit le jour/mois pour cette année
Soit le jour/mois pour l'année prochaine.
Examples: en supposant qu'on soit le 23/05/2019
>>> from datetime import date
>>> gregg = Gymnast(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5))
>>> gregg.next_birthday()
Date(2020, 2, 5)
"""
Examples: en supposant qu'on soit le 23/05/2019
>>> from datetime import date
>>> gregg = Gymnast(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5))
>>> gregg.next_birthday()
Date(2020, 2, 5)
"""
now = pendulum.now()
@ -68,7 +70,7 @@ class Gymnast(Markdownizable):
@property
def age(self):
""" Renvoie l'âge d'un gymnaste. """
"""Renvoie l'âge d'un gymnaste."""
today = date.today()
return (
today.year
@ -78,28 +80,34 @@ class Gymnast(Markdownizable):
@property
def next_age(self):
""" Renvoie l'âge prochain du gymnaste. """
"""Renvoie l'âge prochain du gymnaste."""
return (self.age) + 1
def min_rank_skill(self):
tmp = Skill.objects.filter(known_by__gymnast=self.id).order_by("rank").values('rank')[:1]
tmp = (
Skill.objects.filter(known_by__gymnast=self.id)
.order_by("rank")
.values("rank")[:1]
)
if tmp:
min_rank = tmp[0]['rank']
min_rank = tmp[0]["rank"]
else:
min_rank = 0
return min_rank
def max_rank_skill(self):
tmp = Skill.objects.filter(known_by__gymnast=self.id).order_by(
"-rank"
).values('rank')[:1]
tmp = (
Skill.objects.filter(known_by__gymnast=self.id)
.order_by("-rank")
.values("rank")[:1]
)
if tmp:
max_rank = tmp[0]['rank']
max_rank = tmp[0]["rank"]
else:
max_rank = 0
return max_rank
def known_skill_by_rank(self):
@ -118,9 +126,13 @@ class Gymnast(Markdownizable):
"""
Retourne le niveau maximum des skill que le gymnaste sait faire.
"""
tmp = Skill.objects.filter(known_by__gymnast=self.id).order_by("-level").values('level')[:1]
tmp = (
Skill.objects.filter(known_by__gymnast=self.id)
.order_by("-level")
.values("level")[:1]
)
if tmp:
max_level = tmp[0]['level']
max_level = tmp[0]["level"]
else:
max_level = 0
@ -143,25 +155,33 @@ class Gymnast(Markdownizable):
Renvoie la liste des skill inférieurs ou égaux au niveau max que le gymnaste ne sait *pas* faire.
Liste des Skill que le gymnaste ne sait PAS faire, classé par niveau (ayant un niveau inférieur ou égal au niveau max du gym)
"""
return Skill.objects.filter(level__lte=max_level_skill).exclude(known_by__gymnast=self.id)
return Skill.objects.filter(level__lte=max_level_skill).exclude(
known_by__gymnast=self.id
)
def unknown_skill_gt_level(self, max_level_skill):
"""
Renvoie la liste des skill inférieurs ou égaux au niveau max que le gymnaste ne sait *pas* faire.
Liste des Skill que le gymnaste ne sait PAS faire, classé par niveau (ayant un niveau inférieur ou égal au niveau max du gym)
"""
return Skill.objects.filter(level__gt=max_level_skill).exclude(known_by__gymnast=self.id)
return Skill.objects.filter(level__gt=max_level_skill).exclude(
known_by__gymnast=self.id
)
def unknown_skill_lte_rank(self, max_rank_skill):
# Liste des Skill que le gymnaste ne sait PAS faire, classé par niveau
# (ayant un niveau inférieur ou égal au niveau max du gym)
return Skill.objects.filter(level__lte=max_rank_skill).exclude(known_by__gymnast=self.id)
return Skill.objects.filter(level__lte=max_rank_skill).exclude(
known_by__gymnast=self.id
)
def unknown_skill_gt_rank(self, max_rank_skill):
"""
Liste des Skill que le gymnaste ne sais PAS faire (ayant un niveau plus grand que le niveau max du gym)
"""
return Skill.objects.filter(level__gt=max_rank_skill).exclude(known_by__gymnast=self.id)
return Skill.objects.filter(level__gt=max_rank_skill).exclude(
known_by__gymnast=self.id
)
@staticmethod
def compute_completude(total_skill, gymnast_nb_known_skills, max_skill):
@ -192,7 +212,10 @@ class Gymnast(Markdownizable):
skill["nb_skill"],
nb_known_skill_by_level[j]["nb_known_skill"],
int(
(nb_known_skill_by_level[j]["nb_known_skill"] / skill["nb_skill"])
(
nb_known_skill_by_level[j]["nb_known_skill"]
/ skill["nb_skill"]
)
* 100
),
)
@ -226,7 +249,10 @@ class Gymnast(Markdownizable):
skill["nb_skill"],
nb_known_skill_by_rank[j]["nb_known_skill"],
int(
(nb_known_skill_by_rank[j]["nb_known_skill"] / skill["nb_skill"])
(
nb_known_skill_by_rank[j]["nb_known_skill"]
/ skill["nb_skill"]
)
* 100
),
)
@ -263,12 +289,14 @@ class Gymnast(Markdownizable):
context = {}
max_level_skill = self.max_level_skill()
nb_known_skill_by_level = self.nb_known_skill_by_level()
gymnast_nb_known_skills = self.known_skills.distinct('skill').count()
gymnast_nb_known_skills = self.known_skills.distinct("skill").count()
if max_level_skill > 0:
nb_skill_by_level = Skill.nb_skill_by_level(max_level_skill)
context["total_skill"] = Skill.nb_skill_lte_level(max_level_skill)
context["percentages"] = self.compute_level_statistics(nb_skill_by_level, nb_known_skill_by_level)
context["percentages"] = self.compute_level_statistics(
nb_skill_by_level, nb_known_skill_by_level
)
context["skill_by_level"] = self.unknown_skill_lte_level(max_level_skill)
context["unknown_skill"] = self.unknown_skill_gt_level(max_level_skill)
else:
@ -276,7 +304,9 @@ class Gymnast(Markdownizable):
context["total_skill"] = tmp.count()
context["unknown_skill"] = tmp
context["completude"], context["evaluated_level"] = self.compute_completude(context["total_skill"], gymnast_nb_known_skills, max_level_skill)
context["completude"], context["evaluated_level"] = self.compute_completude(
context["total_skill"], gymnast_nb_known_skills, max_level_skill
)
context["max_level_skill"] = max_level_skill
return context
@ -291,12 +321,14 @@ class Gymnast(Markdownizable):
max_rank_skill = self.max_rank_skill()
context["max_rank_skill"] = max_rank_skill
nb_known_skill_by_rank = self.known_skill_by_rank()
gymnast_nb_known_skills = self.known_skills.distinct('skill').count()
gymnast_nb_known_skills = self.known_skills.distinct("skill").count()
if max_rank_skill > 0:
nb_skill_by_rank = Skill.nb_skill_by_rank(max_rank_skill)
context["total_skill"] = Skill.nb_skill_lte_rank(max_rank_skill)
context["percentages"] = self.compute_rank_statistics(nb_skill_by_rank, nb_known_skill_by_rank)
context["percentages"] = self.compute_rank_statistics(
nb_skill_by_rank, nb_known_skill_by_rank
)
context["skill_by_rank"] = self.unknown_skill_lte_rank(max_rank_skill)
context["unknown_skill"] = self.unknown_skill_gt_rank(max_rank_skill)
else:
@ -304,6 +336,8 @@ class Gymnast(Markdownizable):
context["unknown_skill"] = tmp
context["total_skill"] = tmp.count()
context["completude"], context["evaluated_level"] = self.compute_completude(context["total_skill"], gymnast_nb_known_skills, max_rank_skill)
context["completude"], context["evaluated_level"] = self.compute_completude(
context["total_skill"], gymnast_nb_known_skills, max_rank_skill
)
return context
return context

View File

@ -1,3 +1,36 @@
from django.test import TestCase
from datetime import date
from .models import Gymnast
from datetime import datetime
import pytest
# Create your tests here.
def test_gymnast_tostring():
g = Gymnast(last_name="Pauchou", first_name="Fred")
assert str(g) == "Pauchou, Fred"
def test_gymnaste_get_age():
g = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
assert g.age == 35
def test_gymnaste_get_next_age():
g = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
assert g.next_age == 36
def test_gymnaste_next_birthday():
g = Gymnast(
last_name="Pauchou",
first_name="Fred",
birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
)
assert g.next_birthday == datetime.strptime("03/07/2021", "%d/%m/%Y")

View File

@ -50,4 +50,4 @@ gymnast_urlpatterns = [
path(
r"edit/<int:gymnast_id>/", views.gymnast_create_or_update, name="gymnast_update"
),
]
]

View File

@ -11,7 +11,15 @@ from .forms import GymnastForm
from ultron.followup.models import Event
from ultron.objective.models import Educative, Plan
from ultron.followup.forms import GymnastHasRoutineForm
from ultron.followup.models import Chrono, LearnedSkill, MindState, Skill, Point, Accident, HeightWeight
from ultron.followup.models import (
Chrono,
LearnedSkill,
MindState,
Skill,
Point,
Accident,
HeightWeight,
)
import simplejson
import pendulum
@ -46,7 +54,7 @@ def gymnast_listing(request):
Liste tous les gymnasts connus
"""
gymnast_list = Gymnast.objects.all()
context = {'gymnast_list': gymnast_list}
context = {"gymnast_list": gymnast_list}
return render(request, "peoples/gymnasts/list.html", context)
@ -56,65 +64,105 @@ def gymnast_details(request, gymnast_id):
"""
Récupère toutes les informations d'un gymnaste.
"""
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
context = {} # devrait disparaitre
context = gymnast.get_informations_from_level() # devrait disparaitre
context.update(gymnast.get_informations_from_rank()) # devrait disparaitre
gymnast_nb_known_skills = gymnast.known_skills.distinct('skill').count() # devrait disparaitre
context["gymnast_nb_known_skills"] = gymnast_nb_known_skills # devrait disparaitre
context = {} # devrait disparaitre
context = gymnast.get_informations_from_level() # devrait disparaitre
context.update(gymnast.get_informations_from_rank()) # devrait disparaitre
gymnast_nb_known_skills = gymnast.known_skills.distinct(
"skill"
).count() # devrait disparaitre
context["gymnast_nb_known_skills"] = gymnast_nb_known_skills # devrait disparaitre
planified_learn = Plan.objects.filter(gymnast=gymnast_id).order_by('-date') # devrait disparaitre ?
planified_learn = Plan.objects.filter(gymnast=gymnast_id).order_by(
"-date"
) # devrait disparaitre ?
context["planified_learn"] = planified_learn
learnedskills_list = LearnedSkill.objects.filter(gymnast=gymnast_id).order_by('-date')[:10]
learnedskills_list = LearnedSkill.objects.filter(gymnast=gymnast_id).order_by(
"-date"
)[:10]
nb_skill = Skill.objects.all().count()
nb_known_skill = LearnedSkill.objects.filter(gymnast=gymnast_id).distinct('skill').count()
percentage_known_skill = ( nb_known_skill / nb_skill ) * 100
chronos_list = Chrono.objects.filter(gymnast=gymnast_id).order_by('-date')[:10]
straightjump_score = Chrono.objects.filter(gymnast=gymnast_id).filter(type=0).order_by('-date')
best_straightjump = Chrono.objects.filter(gymnast=gymnast_id).filter(type=0).order_by('-score')[:1]
best_routine = Chrono.objects.filter(gymnast=gymnast_id).filter(type=1).order_by('-score')[:1]
routine_score = Chrono.objects.filter(gymnast=gymnast_id).filter(type=1).order_by('-date')
nb_known_skill = (
LearnedSkill.objects.filter(gymnast=gymnast_id).distinct("skill").count()
)
percentage_known_skill = (nb_known_skill / nb_skill) * 100
chronos_list = Chrono.objects.filter(gymnast=gymnast_id).order_by("-date")[:10]
straightjump_score = (
Chrono.objects.filter(gymnast=gymnast_id).filter(type=0).order_by("-date")
)
best_straightjump = (
Chrono.objects.filter(gymnast=gymnast_id).filter(type=0).order_by("-score")[:1]
)
best_routine = (
Chrono.objects.filter(gymnast=gymnast_id).filter(type=1).order_by("-score")[:1]
)
routine_score = (
Chrono.objects.filter(gymnast=gymnast_id).filter(type=1).order_by("-date")
)
points_routine_1_list = Point.objects.filter(gymnast=gymnast_id).filter(routine_type=0).order_by('-event__datebegin')
points_routine_2_list = Point.objects.filter(gymnast=gymnast_id).filter(routine_type=1).order_by('-event__datebegin')
points_routine_final_list = Point.objects.filter(gymnast=gymnast_id).filter(routine_type=2).order_by('-event__datebegin')
points_routine_1_list = (
Point.objects.filter(gymnast=gymnast_id)
.filter(routine_type=0)
.order_by("-event__datebegin")
)
points_routine_2_list = (
Point.objects.filter(gymnast=gymnast_id)
.filter(routine_type=1)
.order_by("-event__datebegin")
)
points_routine_final_list = (
Point.objects.filter(gymnast=gymnast_id)
.filter(routine_type=2)
.order_by("-event__datebegin")
)
# Devrait être dans un template tags
nb_skill_chained = Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=3).distinct().count()
nb_skill_chained = (
Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=3)
.distinct()
.count()
)
nb_skill_not_chained = Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=2).exclude(
known_by__gymnast=gymnast.id, known_by__cando=3
).distinct().count()
nb_skill_not_chained = (
Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=2)
.exclude(known_by__gymnast=gymnast.id, known_by__cando=3)
.distinct()
.count()
)
nb_skill_whith_help = Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=1).exclude(
known_by__gymnast=gymnast.id, known_by__cando__gte=2
).distinct().count()
nb_skill_whith_help = (
Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=1)
.exclude(known_by__gymnast=gymnast.id, known_by__cando__gte=2)
.distinct()
.count()
)
height_weight = HeightWeight.objects.filter(gymnast=gymnast_id).order_by('-date')[:1]
height_weight = HeightWeight.objects.filter(gymnast=gymnast_id).order_by("-date")[
:1
]
nb_unknown_skill = nb_skill - gymnast_nb_known_skills
context['gymnast'] = gymnast
context['learnedskills_list'] = learnedskills_list
context['chronos_list'] = chronos_list
context['straightjump_score'] = straightjump_score
context['routine_score'] = routine_score
context['best_routine'] = best_routine
context['best_straightjump'] = best_straightjump
context['nb_skill'] = nb_skill
context['nb_known_skill'] = nb_known_skill
context['points_routine_1_list'] = points_routine_1_list
context['points_routine_2_list'] = points_routine_2_list
context['points_routine_final_list'] = points_routine_final_list
context['percentage_known_skill'] = percentage_known_skill
context['nb_skill_chained'] = nb_skill_chained
context['nb_skill_not_chained'] = nb_skill_not_chained
context['nb_skill_whith_help'] = nb_skill_whith_help
context['nb_unknown_skill'] = nb_unknown_skill
context['height_weight'] = height_weight
context["gymnast"] = gymnast
context["learnedskills_list"] = learnedskills_list
context["chronos_list"] = chronos_list
context["straightjump_score"] = straightjump_score
context["routine_score"] = routine_score
context["best_routine"] = best_routine
context["best_straightjump"] = best_straightjump
context["nb_skill"] = nb_skill
context["nb_known_skill"] = nb_known_skill
context["points_routine_1_list"] = points_routine_1_list
context["points_routine_2_list"] = points_routine_2_list
context["points_routine_final_list"] = points_routine_final_list
context["percentage_known_skill"] = percentage_known_skill
context["nb_skill_chained"] = nb_skill_chained
context["nb_skill_not_chained"] = nb_skill_not_chained
context["nb_skill_whith_help"] = nb_skill_whith_help
context["nb_unknown_skill"] = nb_unknown_skill
context["height_weight"] = height_weight
# context = {
# 'gymnast': gymnast,
@ -143,7 +191,9 @@ def gymnast_display_event(request, gymnast_id):
"""
today = pendulum.now().date()
next_event_list = Event.objects.filter(gymnasts=gymnast_id, datebegin__gte=today)
previous_event_list = Event.objects.filter(gymnasts=gymnast_id, datebegin__lte=today)
previous_event_list = Event.objects.filter(
gymnasts=gymnast_id, datebegin__lte=today
)
context = {
"next_event_list": next_event_list,
@ -160,10 +210,7 @@ def gymnast_display_accident(request, gymnast_id):
"""
accident_list = Accident.objects.filter(gymnast=gymnast_id)
context = {
"accident_list": accident_list,
"gymnast_id": gymnast_id
}
context = {"accident_list": accident_list, "gymnast_id": gymnast_id}
return render(request, "peoples/gymnasts/list_accident.html", context)
@ -174,16 +221,17 @@ def gymnast_display_phisiological(request, gymnast_id):
"""
Renvoie les listes des tailles/poids, état d'esprit et accidents.
"""
accident_list = Accident.objects.filter(gymnast=gymnast_id).order_by('-date')
mindstate_list = MindState.objects.filter(gymnast=gymnast_id).order_by('-date')
height_weight_list = HeightWeight.objects.filter(gymnast=gymnast_id).order_by('-date')
accident_list = Accident.objects.filter(gymnast=gymnast_id).order_by("-date")
mindstate_list = MindState.objects.filter(gymnast=gymnast_id).order_by("-date")
height_weight_list = HeightWeight.objects.filter(gymnast=gymnast_id).order_by(
"-date"
)
context = {
'accident_list': accident_list,
'mindstate_list': mindstate_list,
'height_weight_list': height_weight_list,
'gymnast_id': gymnast_id,
"accident_list": accident_list,
"mindstate_list": mindstate_list,
"height_weight_list": height_weight_list,
"gymnast_id": gymnast_id,
}
return render(request, "peoples/gymnasts/physiological_followup.html", context)
@ -253,8 +301,7 @@ def gymnast_display_routines(request, gymnast_id):
@login_required
@require_http_methods(["GET", "POST"])
def link_routine_to_gymnast(request, gymnast_id=None):
"""
"""
""" """
if gymnast_id:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
@ -289,7 +336,7 @@ def gymnast_create_or_update(request, gymnast_id=None):
if gymnast_id:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
data = {'club_related': gymnast.club}
data = {"club_related": gymnast.club}
else:
gymnast = None
data = {}
@ -323,34 +370,42 @@ def gymnast_display_skill(request, gymnast_id):
context = {}
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
gymnast_nb_known_skills = gymnast.known_skills.distinct('skill').count()
gymnast_nb_known_skills = gymnast.known_skills.distinct("skill").count()
context = gymnast.get_informations_from_level()
context.update(gymnast.get_informations_from_rank())
planified_skill = Skill.objects.filter(plan__gymnast=gymnast.id).order_by('-plan__date').annotate(plan_date=F("plan__date"))
planified_skill = (
Skill.objects.filter(plan__gymnast=gymnast.id)
.order_by("-plan__date")
.annotate(plan_date=F("plan__date"))
)
context["planified_skill"] = planified_skill
if gymnast.gender:
context["skill_by_age"] = Skill.objects.filter(age_girl__lte=gymnast.age).exclude(
known_by__gymnast=gymnast.id
)
context["skill_by_age"] = Skill.objects.filter(
age_girl__lte=gymnast.age
).exclude(known_by__gymnast=gymnast.id)
else:
context["skill_by_age"] = Skill.objects.filter(age_boy__lte=gymnast.age).exclude(
known_by__gymnast=gymnast.id
)
context["skill_by_age"] = Skill.objects.filter(
age_boy__lte=gymnast.age
).exclude(known_by__gymnast=gymnast.id)
skill_whith_help = Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=1).exclude(
known_by__gymnast=gymnast.id, known_by__cando__gte=2
).distinct()
skill_whith_help = (
Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=1)
.exclude(known_by__gymnast=gymnast.id, known_by__cando__gte=2)
.distinct()
)
skill_not_chained = Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=2).exclude(
known_by__gymnast=gymnast.id, known_by__cando=3
).distinct()
skill_not_chained = (
Skill.objects.filter(known_by__gymnast=gymnast_id, known_by__cando=2)
.exclude(known_by__gymnast=gymnast.id, known_by__cando=3)
.distinct()
)
context["gymnast"] = gymnast
context["skill_whith_help"] = skill_whith_help
context["skill_not_chained"] = skill_not_chained
context["gymnast_nb_known_skills"] = gymnast_nb_known_skills
return render(request, "peoples/gymnasts/list_skill.html", context)
return render(request, "peoples/gymnasts/list_skill.html", context)

View File

@ -22,36 +22,34 @@ from .models import (
class EventTypeAdmin(admin.ModelAdmin):
model = EventType
list_display = ('name', 'acronym')
ordering = ('name',)
search_fields = ('name', 'acronym')
list_display = ("name", "acronym")
ordering = ("name",)
search_fields = ("name", "acronym")
class EventAdmin(ForeignKeyAutocompleteAdmin):
model = Event
fields = ('name', 'eventtype', 'place', 'datebegin', 'dateend', 'informations')
list_display = ('name', 'eventtype', 'place', 'datebegin')
ordering = ('name',)
list_filter = ('eventtype',)
search_fields = ('name',)
autocomplete_fields = (
'eventtype',
)
fields = ("name", "eventtype", "place", "datebegin", "dateend", "informations")
list_display = ("name", "eventtype", "place", "datebegin")
ordering = ("name",)
list_filter = ("eventtype",)
search_fields = ("name",)
autocomplete_fields = ("eventtype",)
# related_search_fields = {
# 'place': ('name', 'city'),
# }
# filter_horizontal = ('gymnasts', 'club')
# filter_horizontal = ('gymnasts', 'club')
# filter_horizontal = ('gymnasts',)
class Event_ParticipationAdmin(admin.ModelAdmin):
model = Event_Participation
fields = ('event', 'gymnast', 'rank')
list_display = ('event', 'gymnast', 'rank')
fields = ("event", "gymnast", "rank")
list_display = ("event", "gymnast", "rank")
admin.site.register(EventType, EventTypeAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class PlanningConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.planning'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.planning"

View File

@ -1,4 +1,3 @@
from datetime import date
from django import forms
@ -7,6 +6,7 @@ from django.contrib.admin.widgets import FilteredSelectMultiple
from ultron.people.models import Gymnast
from .models import Event
class EventForm(forms.ModelForm):
# gymnasts = forms.ModelMultipleChoiceField(queryset=Gymnast.objects.all(), widget=FilteredSelectMultiple('Gymnast(s)', is_stacked=False))
@ -14,37 +14,37 @@ class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = (
'name',
'datebegin',
'dateend',
'place',
'eventtype',
'informations',
"name",
"datebegin",
"dateend",
"place",
"eventtype",
"informations",
) # , 'gymnasts'
widgets = {
'place': forms.HiddenInput(),
"place": forms.HiddenInput(),
# 'gymnasts': forms.ModelMultipleChoiceField(queryset=Gymnast.objects.all(), widget=FilteredSelectMultiple('Gymnast(s)', is_stacked=False)),
# 'gymnasts': forms.MultipleChoiceField(choices=MYCHOICES, widget=forms.SelectMultiple)
'eventtype': forms.Select(attrs={'class': 'form-control'}),
'name': forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Even\'s name'}
"eventtype": forms.Select(attrs={"class": "form-control"}),
"name": forms.TextInput(
attrs={"class": "form-control", "placeholder": "Even's name"}
),
'datebegin': forms.DateTimeInput(
"datebegin": forms.DateTimeInput(
attrs={
'class': 'form-control datetimepicker',
'placeholder': date.today().strftime('%Y-%m-%d 08:00'),
"class": "form-control datetimepicker",
"placeholder": date.today().strftime("%Y-%m-%d 08:00"),
}
),
'dateend': forms.DateTimeInput(
"dateend": forms.DateTimeInput(
attrs={
'class': 'form-control datetimepicker',
'placeholder': date.today().strftime('%Y-%m-%d 18:00'),
"class": "form-control datetimepicker",
"placeholder": date.today().strftime("%Y-%m-%d 18:00"),
}
),
'informations': forms.Textarea(
"informations": forms.Textarea(
attrs={
'class': 'form-control',
'placeholder': 'Informations about the event…',
"class": "form-control",
"placeholder": "Informations about the event…",
}
),
}
@ -52,9 +52,9 @@ class EventForm(forms.ModelForm):
place_related = forms.CharField(
widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Searching place…',
'data-ref': '#id_place',
"class": "form-control",
"placeholder": "Searching place…",
"data-ref": "#id_place",
}
)
)
@ -62,4 +62,4 @@ class EventForm(forms.ModelForm):
# class Media:
# css = {'all':('/static/admin/css/widgets.css',),}
# js = ('/admin/jquery.js','/admin/jsi18n/') # OLD
# js = ('/admin/jsi18n/', ) # NEW
# js = ('/admin/jsi18n/', ) # NEW

View File

@ -9,62 +9,118 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('people', '0001_initial'),
('location', '0001_initial'),
("people", "0001_initial"),
("location", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='Event',
name="Event",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('datebegin', models.DateTimeField(verbose_name='Début')),
('dateend', models.DateTimeField(blank=True, verbose_name='Fin')),
('informations', models.TextField(blank=True, help_text='Only MarkDown is authorized', null=True, verbose_name='Comments')),
('name', models.CharField(max_length=255, verbose_name='Nom')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("datebegin", models.DateTimeField(verbose_name="Début")),
("dateend", models.DateTimeField(blank=True, verbose_name="Fin")),
(
"informations",
models.TextField(
blank=True,
help_text="Only MarkDown is authorized",
null=True,
verbose_name="Comments",
),
),
("name", models.CharField(max_length=255, verbose_name="Nom")),
],
options={
'verbose_name': 'Event',
'verbose_name_plural': 'Event',
"verbose_name": "Event",
"verbose_name_plural": "Event",
},
),
migrations.CreateModel(
name='EventType',
name="EventType",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nom')),
('acronym', models.CharField(max_length=15, verbose_name='Acronyme')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255, verbose_name="Nom")),
("acronym", models.CharField(max_length=15, verbose_name="Acronyme")),
],
options={
'verbose_name': 'Event Type',
'verbose_name_plural': 'Event Types',
"verbose_name": "Event Type",
"verbose_name_plural": "Event Types",
},
),
migrations.CreateModel(
name='Event_Participation',
name="Event_Participation",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rank', models.PositiveSmallIntegerField(default=0)),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='planning.event')),
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='people.gymnast')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("rank", models.PositiveSmallIntegerField(default=0)),
(
"event",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="planning.event"
),
),
(
"gymnast",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="people.gymnast"
),
),
],
options={
'verbose_name': 'Event Participation',
"verbose_name": "Event Participation",
},
),
migrations.AddField(
model_name='event',
name='eventtype',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='planning.eventtype', verbose_name='Type'),
model_name="event",
name="eventtype",
field=models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="planning.eventtype",
verbose_name="Type",
),
),
migrations.AddField(
model_name='event',
name='gymnasts',
field=models.ManyToManyField(related_name='participate_to', through='planning.Event_Participation', to='people.Gymnast', verbose_name='Participants'),
model_name="event",
name="gymnasts",
field=models.ManyToManyField(
related_name="participate_to",
through="planning.Event_Participation",
to="people.Gymnast",
verbose_name="Participants",
),
),
migrations.AddField(
model_name='event',
name='place',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='location.place'),
model_name="event",
name="place",
field=models.ForeignKey(
default=None,
on_delete=django.db.models.deletion.CASCADE,
to="location.place",
),
),
]

View File

@ -5,7 +5,11 @@ from django.db import models
import pendulum
from ultron.tools.models import Markdownizable, Temporizable, get_number_of_weeks_between
from ultron.tools.models import (
Markdownizable,
Temporizable,
get_number_of_weeks_between,
)
from ultron.people.models import Gymnast
from ultron.location.models import Place
@ -15,14 +19,14 @@ from ultron.location.models import Place
class EventType(models.Model):
"""
Classe représentant les types d'évènements.
Classe représentant les types d'évènements.
C'est un dictionnaire fini :
- compétiton qualificative,
- compétition finale,
- démonstration,
-
"""
C'est un dictionnaire fini :
- compétiton qualificative,
- compétition finale,
- démonstration,
-
"""
class Meta:
verbose_name = "Event Type"
@ -38,20 +42,18 @@ class EventType(models.Model):
class Event(Markdownizable, Temporizable):
"""Classe représentant les évènements.
Un évènement est caractérisé par :
* un nom,
* un lieu (place),
* un type (compétition, démonstration, ),
* des gymnastes (participation prévue).
"""
Un évènement est caractérisé par :
* un nom,
* un lieu (place),
* un type (compétition, démonstration, ),
* des gymnastes (participation prévue).
"""
class Meta:
verbose_name = "Event"
verbose_name_plural = "Event"
place = models.ForeignKey(
Place, on_delete=models.CASCADE, default=None
)
place = models.ForeignKey(Place, on_delete=models.CASCADE, default=None)
eventtype = models.ForeignKey(
EventType, verbose_name="Type", on_delete=models.CASCADE, default=None
)
@ -72,9 +74,9 @@ class Event(Markdownizable, Temporizable):
def checkdates(self):
"""
Fonction assignant la date de fin d'un évènement à la date de début, si la date
de fin n'est pas définie, l'heure de fin est par défaut 18h00.
"""
Fonction assignant la date de fin d'un évènement à la date de début, si la date
de fin n'est pas définie, l'heure de fin est par défaut 18h00.
"""
if self.dateend is None and self.datebegin is not None:
self.dateend = datetime.combine(self.datebegin.date(), time(18, 0))
@ -85,8 +87,8 @@ class Event(Markdownizable, Temporizable):
class Event_Participation(models.Model):
"""
"""
""" """
class Meta:
verbose_name = "Event Participation"
@ -95,4 +97,4 @@ class Event_Participation(models.Model):
rank = models.PositiveSmallIntegerField(default=0)
def __str__(self):
return "%s to %s" % (self.gymnast, self.event)
return "%s to %s" % (self.gymnast, self.event)

View File

@ -18,6 +18,7 @@ from .forms import EventForm
# import pendulum
import simplejson
# import collections
# import locale
@ -47,7 +48,7 @@ def event_lookup(request):
@require_http_methods(["GET", "POST"])
def event_create_or_update(request, eventid=None):
"""
Création ou mise à jour d'un évènement.
Création ou mise à jour d'un évènement.
"""
if eventid:
@ -141,8 +142,7 @@ def __get_event_list(request):
@login_required
@require_http_methods(["GET"])
def calendar(request):
"""Récupère la liste de tous évènements suivant un pattern si celui-ci est définit.
"""
"""Récupère la liste de tous évènements suivant un pattern si celui-ci est définit."""
event_list = __get_event_list(request)
context = {"event_list": event_list}
return render(request, "calendar.html", context)

View File

@ -4,7 +4,7 @@ from .models import Profile
class ProfileAdmin(admin.ModelAdmin):
model = Profile
list_display = ('user', 'template_color', 'sidebar_color')
list_display = ("user", "template_color", "sidebar_color")
admin.site.register(Profile, ProfileAdmin)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class ProfileConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ultron.profiles'
default_auto_field = "django.db.models.BigAutoField"
name = "ultron.profiles"

View File

@ -9,18 +9,18 @@ class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = (
'template_color',
'sidebar_color',
'is_sidebar_minified',
"template_color",
"sidebar_color",
"is_sidebar_minified",
)
widgets = {
'template_color': forms.Select(attrs={'class': 'form-control'}),
'sidebar_color': forms.Select(attrs={'class': 'form-control'}),
'is_sidebar_minified': forms.CheckboxInput(
"template_color": forms.Select(attrs={"class": "form-control"}),
"sidebar_color": forms.Select(attrs={"class": "form-control"}),
"is_sidebar_minified": forms.CheckboxInput(
attrs={
'class': 'bootstrap-switch mt-0',
'data-on-label': '<i class="tim-icons icon-check-2 text-success"></i>',
'data-off-label': '<i class="tim-icons icon-simple-remove text-danger"></i>',
"class": "bootstrap-switch mt-0",
"data-on-label": '<i class="tim-icons icon-check-2 text-success"></i>',
"data-off-label": '<i class="tim-icons icon-simple-remove text-danger"></i>',
}
),
}

View File

@ -15,13 +15,47 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='Profile',
name="Profile",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('template_color', models.PositiveSmallIntegerField(choices=[(0, 'Dark'), (1, 'Light')], default=0, verbose_name='Template')),
('sidebar_color', models.PositiveSmallIntegerField(choices=[(0, 'Purple'), (1, 'Blue'), (2, 'Green'), (3, 'Orange'), (4, 'Red')], default=0, verbose_name='Sidebar')),
('is_sidebar_minified', models.BooleanField(default=False)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"template_color",
models.PositiveSmallIntegerField(
choices=[(0, "Dark"), (1, "Light")],
default=0,
verbose_name="Template",
),
),
(
"sidebar_color",
models.PositiveSmallIntegerField(
choices=[
(0, "Purple"),
(1, "Blue"),
(2, "Green"),
(3, "Orange"),
(4, "Red"),
],
default=0,
verbose_name="Sidebar",
),
),
("is_sidebar_minified", models.BooleanField(default=False)),
(
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
]

View File

@ -12,27 +12,26 @@ from .models import Profile
User = get_user_model()
@login_required
@require_http_methods(["GET", "POST"])
def profile_update(request):
"""Modification du profil de l'utilisateur connecté
"""
"""Modification du profil de l'utilisateur connecté"""
try:
profile = request.user.profile
except Exception: # don't do this !
profile = Profile.objects.create(user=request.user)
if request.method == 'POST':
if request.method == "POST":
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
form.save()
request.session['template'] = profile.template_color
request.session['sidebar'] = profile.sidebar_color
request.session['is_sidebar_minified'] = profile.is_sidebar_minified
request.session["template"] = profile.template_color
request.session["sidebar"] = profile.sidebar_color
request.session["is_sidebar_minified"] = profile.is_sidebar_minified
return HttpResponseRedirect("/")
@ -42,4 +41,4 @@ def profile_update(request):
context = {
"form": form,
}
return render(request, 'profiles/update.html', context)
return render(request, "profiles/update.html", context)

View File

@ -9,29 +9,29 @@ import markdown
def get_number_of_weeks_between(start, stop):
"""
Renvoie le nombre de semaines entre deux dates.
Par extension, cela permet de connaitre le nombre d'occurence d'un
évènement (entraînement, par exemple) hebdromadaire entre deux dates
et ainsi pouvoir plannifier.
Renvoie le nombre de semaines entre deux dates.
Par extension, cela permet de connaitre le nombre d'occurence d'un
évènement (entraînement, par exemple) hebdromadaire entre deux dates
et ainsi pouvoir plannifier.
:param start: date de début de la période
:type start: datetime.date
:param stop: date de fin de la période
:type stop: datetime.date
:return: Le nombre de semaines entre les deux dates.
:param start: date de début de la période
:type start: datetime.date
:param stop: date de fin de la période
:type stop: datetime.date
:return: Le nombre de semaines entre les deux dates.
Remarks:
Proposition d'utiliser isocalendar() sur une date.
L'indice 1 de la valeur de retour donne la semaine correspondant.
Remarks:
Proposition d'utiliser isocalendar() sur une date.
L'indice 1 de la valeur de retour donne la semaine correspondant.
Eg.
>>> from datetime import date
>>> d = date(2020, 9, 27)
>>> d.isocalendar()
(2020, 39, 7)
Eg.
>>> from datetime import date
>>> d = date(2020, 9, 27)
>>> d.isocalendar()
(2020, 39, 7)
-> Est-ce qu'il ne suffirait pas de faire la différence ?
"""
-> Est-ce qu'il ne suffirait pas de faire la différence ?
"""
tmp = stop - start
number_of_days = abs(tmp.days)
@ -48,28 +48,28 @@ def get_number_of_weeks_between(start, stop):
class TemporizableQuerySet(models.QuerySet):
"""
Classe permettant de spécifier le `QuerySet` de la classe `Temporizable`.
"""
Classe permettant de spécifier le `QuerySet` de la classe `Temporizable`.
"""
def next(self, limit):
"""
Renvoie la liste des prochains "temporizable" (par rapport à la date du jour).
Renvoie la liste des prochains "temporizable" (par rapport à la date du jour).
:param limit: nombre d'éléments désirés.
:type limit: int
:return: une liste de `limit` éléments temporizables.
"""
return self.filter(datebegin__gte=timezone.now()).order_by('datebegin')[0:limit]
:param limit: nombre d'éléments désirés.
:type limit: int
:return: une liste de `limit` éléments temporizables.
"""
return self.filter(datebegin__gte=timezone.now()).order_by("datebegin")[0:limit]
def last(self, limit):
"""
Renvoie la liste des derniers "temporizable" (par rapport à la date du jour).
Renvoie la liste des derniers "temporizable" (par rapport à la date du jour).
:param limit: nombre d'éléments désirés.
:type limit: int
:return: une liste de `limit` éléments temporizables
"""
return self.filter(dateend__lte=timezone.now()).order_by('-dateend')[0:limit]
:param limit: nombre d'éléments désirés.
:type limit: int
:return: une liste de `limit` éléments temporizables
"""
return self.filter(dateend__lte=timezone.now()).order_by("-dateend")[0:limit]
# def get(self, date_string):
# """
@ -87,52 +87,52 @@ class TemporizableQuerySet(models.QuerySet):
class Temporizable(models.Model):
"""
Classe abstraite définissant une période comprise entre deux dates.
"""
"""
class Meta:
abstract = True
datebegin = models.DateTimeField(verbose_name='Début')
dateend = models.DateTimeField(blank=True, verbose_name='Fin')
datebegin = models.DateTimeField(verbose_name="Début")
dateend = models.DateTimeField(blank=True, verbose_name="Fin")
objects = models.Manager.from_queryset(TemporizableQuerySet)()
def get_total_occurence(self):
"""
Renvoie le nombre de semaines entre les deux dates d'une instance de la
classe `Temporizable`.
Renvoie le nombre de semaines entre les deux dates d'une instance de la
classe `Temporizable`.
:return: nombre de semaines.
"""
:return: nombre de semaines.
"""
return get_number_of_weeks_between(self.datebegin.date(), self.dateend.date())
def get_number_of_occurence_to_event(self, the_date):
"""
Renvoie le nombre semaines entre une date choisie et le début
(datebegin) d'une instance de la classe `Temporizable`.
Renvoie le nombre semaines entre une date choisie et le début
(datebegin) d'une instance de la classe `Temporizable`.
:param the_date: date par rapport à laquelle le calcul sera fait.
:type the_date: datetime.date
:return: nombre de semaines.
"""
:param the_date: date par rapport à laquelle le calcul sera fait.
:type the_date: datetime.date
:return: nombre de semaines.
"""
return get_number_of_weeks_between(the_date, self.datebegin.date())
def get_number_of_occurence_inbetween(self, the_date, rest=True):
"""
Renvoie le nombre semaines entre une date choisie et une instance de la
classe `Temporizable`. Le calcul peut se faire soit entre la date
choisie et le date de fin d'une occurence de la classe, soit entre la
date de début d'une occurence de la classe et la date choisie.
Renvoie le nombre semaines entre une date choisie et une instance de la
classe `Temporizable`. Le calcul peut se faire soit entre la date
choisie et le date de fin d'une occurence de la classe, soit entre la
date de début d'une occurence de la classe et la date choisie.
:param the_date: date par rapport à laquelle le calcul sera fait.
:type the_date: datetime.date
:param rest: paramètre définissant s'il faut calculer le reste des
occurences à venir (depuis `the_date` jusqu'à la date de fin) ou
les occurences déjà passées (depuis la date de début jusqu'à
`the_date`)
:type rest: booléen
:return: nombre de semaines.
"""
:param the_date: date par rapport à laquelle le calcul sera fait.
:type the_date: datetime.date
:param rest: paramètre définissant s'il faut calculer le reste des
occurences à venir (depuis `the_date` jusqu'à la date de fin) ou
les occurences déjà passées (depuis la date de début jusqu'à
`the_date`)
:type rest: booléen
:return: nombre de semaines.
"""
if rest:
return get_number_of_weeks_between(the_date, self.dateend.date())
else:
@ -150,8 +150,8 @@ class Markdownizable(models.Model):
informations = models.TextField(
null=True,
blank=True,
verbose_name='Comments',
help_text='Only MarkDown is authorized',
verbose_name="Comments",
help_text="Only MarkDown is authorized",
)
def to_markdown(self):