Working 2.0

This commit is contained in:
Pedro Romero 2025-05-13 01:13:40 +02:00
parent a10fce5731
commit 69b0fa02a4
37 changed files with 155 additions and 48 deletions

View File

@ -1,10 +1,44 @@
# forms.py
from django import forms
from django.utils.safestring import mark_safe
from .models import Participant
import re
from django.core.exceptions import ValidationError
_DECIMAL_RE = re.compile(r"[^\d,\.]")
class ParticipantForm(forms.ModelForm):
class Meta:
model = Participant
fields = ["group_name","R_diff","L_diff","Ph_diff","Pcu_diff","s_vol_over_eta"]
widgets = {f: forms.NumberInput(attrs={"step": "0.1", "class": "input"})
for f in fields if f!="group_name"}
widgets["group_name"]= forms.TextInput(attrs={"class":"input"})
model = Participant
fields = [
"group_name",
"R_diff",
"L_diff",
"Ph_diff",
"Pcu_diff",
"s_vol_over_eta",
]
widgets = {
f: forms.NumberInput(attrs={"step": "0.1", "class": "input"})
for f in fields if f != "group_name"
}
widgets["group_name"] = forms.TextInput(attrs={"class": "input"})
labels = {
"group_name": "Nombre del grupo",
"R_diff": mark_safe("R<sub>diff</sub>"),
"L_diff": mark_safe("L<sub>diff</sub>"),
"Ph_diff": mark_safe("P<sub>h, diff</sub>"),
"Pcu_diff": mark_safe("P<sub>cu, diff</sub>"),
"s_vol_over_eta": mark_safe("S/Vol·η"),
}
def clean_s_vol_over_eta(self):
raw = self.data.get("s_vol_over_eta", "")
raw = _DECIMAL_RE.sub("", raw) # quita letras o espacios
raw = raw.replace(",", ".") # coma → punto
try:
value = float(raw)
except ValueError:
raise ValidationError("Introduce un número válido (ej. 12.3)")
if value <= 0:
raise ValidationError("Debe ser mayor que 0")
return value

View File

@ -1,6 +1,8 @@
# apps/participants/models.py
from django.db import models
from apps.core.models import TimeStampedModel
import re
from django.core.exceptions import ValidationError
class Participant(TimeStampedModel):
group_name = models.CharField(max_length=80, unique=True)
@ -10,8 +12,7 @@ class Participant(TimeStampedModel):
L_diff = models.FloatField()
Ph_diff = models.FloatField()
Pcu_diff= models.FloatField()
s_vol_over_eta = models.FloatField(help_text="S*Vol/η") # métrica objetiva
s_vol_over_eta = models.FloatField()
score = models.FloatField(default=0)
class Meta:
@ -19,3 +20,8 @@ class Participant(TimeStampedModel):
def __str__(self):
return self.group_name
def clean(self):
super().clean()
if self.s_vol_over_eta <= 0:
raise ValidationError({"s_vol_over_eta": "Debe ser mayor que 0"})

View File

@ -29,7 +29,7 @@ def calculate_scores():
p.score += _factor(diff) * weight
# 3) Objetivo (rank por métrica)
sorted_by_obj = sorted(participants, key=lambda x: x.s_vol_over_eta)
sorted_by_obj = sorted(participants, key=lambda x: x.s_vol_over_eta, reverse=True)
for idx, p in enumerate(sorted_by_obj, start=1):
p.score += max(settings.objective_weight - (idx - 1), 0)

Binary file not shown.

View File

@ -1,39 +1,103 @@
/* static/css/styles.css */
:root{
--brand-blue:#002e5d;
--brand-yellow:#f4b400;
--brand-orange:#ffa94d;
}
body{background:var(--brand-blue);color:#fff;font-family:Inter,system-ui,sans-serif}
/* Botones */
.btn{
@apply inline-block px-6 py-3 rounded-xl font-medium transition transform;
}
.btn-primary{
background:var(--brand-orange);color:#222;
}
.btn-primary:hover{filter:brightness(1.1) scale(1.02)}
.btn-secondary{
background:transparent;border:2px solid var(--brand-orange);color:var(--brand-orange);
}
.btn-secondary:hover{background:var(--brand-orange);color:#222}
/* Animaciones hero */
@keyframes scaleFade{
0%{opacity:0;transform:scale(.7)}
100%{opacity:1;transform:scale(1)}
}
.hero-appear{animation:scaleFade .6s ease-out both}
/* Transición logo grande→pequeño */
.logo-big {width: 60%}
.logo-small {width:48px}
/* Table */
table{border-collapse:collapse;width:100%;max-width:640px;margin-inline:auto}
th,td{padding:.6rem 1rem;border-bottom:1px solid #ffffff33}
thead{background:#ffffff11}
tbody tr:nth-child(even){background:#ffffff08}
:root {
--brand-blue: #002e5d;
--brand-orange: #ffa94d;
}
/* Cuerpo */
body {
background: var(--brand-blue);
color: #fff;
font-family: Inter, system-ui, sans-serif;
}
/* Botones */
.btn {
display: inline-block;
padding: 0.75rem 1.25rem;
border-radius: 0.5rem;
font-weight: 600;
text-decoration: none;
transition: box-shadow 0.2s ease, background-color 0.2s ease, color 0.2s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
cursor: pointer;
}
.btn:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
.btn:focus {
outline: 2px solid rgba(255,255,255,0.6);
outline-offset: 2px;
}
/* Botón principal */
.btn-primary {
background-color: var(--brand-orange);
color: #222;
border: none;
}
.btn-primary:hover {
background-color: #ee993f;
}
/* Botón secundario */
.btn-secondary {
background-color: transparent;
border: 2px solid var(--brand-orange);
color: var(--brand-orange);
}
.btn-secondary:hover {
background-color: var(--brand-orange);
color: #222;
}
/* Formularios */
form {
max-width: 360px;
margin: 0 auto; /* centra el bloque del formulario */
width: 100%;
}
form label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #fff;
}
form input,
form select,
form textarea {
width: 100%;
padding: 0.5rem 1rem;
margin-bottom: 1rem;
border: none;
border-radius: 0.375rem;
background-color: #fff;
color: #333;
font-size: 1rem;
box-sizing: border-box;
}
form input:focus,
form select:focus,
form textarea:focus {
outline: 2px solid var(--brand-orange);
outline-offset: 2px;
}
/* Animaciones hero */
@keyframes scaleFade {
0% { opacity: 0; transform: scale(.7) }
100% { opacity: 1; transform: scale(1) }
}
.hero-appear { animation: scaleFade .6s ease-out both }
/* Logos */
.logo-big { width: 60% }
.logo-small { width: 100px }
/*-- Texto matemático --*/
label sub,
label sup {
font-size: 0.75em;
vertical-align: baseline;
position: relative;
top: 0.25em;
}

View File

@ -12,6 +12,7 @@
</head>
<body class="min-h-screen flex flex-col">
{% block navbar %}
<!--NAVBAR-->
<header class="flex items-center gap-4 px-6 py-4">
<a href="/" aria-label="Inicio">
@ -22,6 +23,7 @@
<a href="{% url 'settings' %}" class="btn btn-secondary hidden sm:inline-block">Administración</a>
</nav>
</header>
{% endblock %}
<!--CONTENIDO-->
<main class="flex-1 flex flex-col items-center justify-center px-4">

View File

@ -1,6 +1,7 @@
<!-- templates/home.html -->
{% extends "base.html" %}
{% load static %}
{% block navbar %}{% endblock %}
{% block title %}Trafoking{% endblock %}
{% block content %}
<section class="flex flex-col items-center text-center gap-12 hero-appear">

View File

@ -20,4 +20,4 @@
</button>
</form>
{% endblock %}
{% endblock %}