Browse Source

Merge branch 'master' of atrey.karlin.mff.cuni.cz:/akce/MaM/MaMweb/mamweb

Conflicts:
	seminar/views.py
remotes/origin/vysl
Aneta 9 years ago
parent
commit
0b30583b0a
  1. 8
      diff_db_backup.sh
  2. 1
      mamweb/settings_prod.py
  3. 11
      seminar/export.py
  4. 75
      seminar/migrations/0028_add_body_celkem_views.py
  5. 51
      seminar/migrations/0029_fix_body_celkem_views.py
  6. 30
      seminar/models.py
  7. 10
      seminar/templates/seminar/archiv/cislo.html
  8. 4
      seminar/templates/seminar/archiv/cislo_vysledkovka.tex
  9. 24
      seminar/templates/seminar/stav_databaze.html
  10. 2
      seminar/urls.py
  11. 58
      seminar/utils.py
  12. 51
      seminar/views.py

8
diff_db_backup.sh

@ -6,6 +6,12 @@ F2="$2"
TMPF1=`tempfile`
TMPF2=`tempfile`
if which colordiff; then
DIFF=colordiff
else
DIFF=diff
fi
if [ "z$F1" == "z" ]; then
echo "Requies argument"
exit 1
@ -21,7 +27,7 @@ else
cat "$F2" | bunzip2 > "$TMPF2"
fi
colordiff "$TMPF1" "$TMPF2"
$DIFF "$TMPF1" "$TMPF2"
rm "$TMPF1" "$TMPF2"

1
mamweb/settings_prod.py

@ -5,6 +5,7 @@ from .settings_common import *
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
INSTALLED_APPS += (
'django_extensions',
)
# SECURITY WARNING: keep the secret key used in production secret!

11
seminar/export.py

@ -5,7 +5,8 @@ from django.core.urlresolvers import reverse
from django.views import generic
from django.utils.encoding import force_text
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni
from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni
from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from .ovvpfile import OvvpFile
class ExportIndexView(generic.View):
@ -75,7 +76,7 @@ class ExportRocnikView(generic.View):
rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True)
cislo = rocnik.posledni_zverejnena_vysledkovka_cislo()
vysledky = VysledkyKCislu.objects.filter(cislo = cislo).select_related("resitel").order_by('-body_celkem').all()
vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = cislo).select_related("resitel").order_by('-body').all()
of = default_ovvpfile('MaM.rocnik', rocnik)
of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(
@ -91,11 +92,11 @@ class ExportRocnikView(generic.View):
v = vysledky[vi]
rd = v.resitel.export_row()
if posledni_body > v.body_celkem:
posledni_body = v.body_celkem
if posledni_body > v.body:
posledni_body = v.body
posledni_poradi = vi + 1
rd['rank'] = posledni_poradi
rd['points'] = v.body_celkem
rd['points'] = v.body
of.rows.append(rd)

75
seminar/migrations/0028_add_body_celkem_views.py

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django_countries.fields
import seminar.models
import django.utils.timezone
from django.conf import settings
CREATE_VIEWS="""
drop view seminar_body_k_cislu;
drop view seminar_body_za_cislo;
create view seminar_body_za_cislo as
select
seminar_reseni.cislo_body_id || '-' || seminar_reseni.resitel_id as id,
seminar_reseni.cislo_body_id as cislo_id,
seminar_reseni.resitel_id as resitel_id,
seminar_cisla.cislo as cislo,
seminar_cisla.rocnik_id as rocnik_id,
seminar_rocniky.rocnik as rocnik,
seminar_cisla.verejna_vysledkovka as verejna_vysledkovka,
sum(seminar_reseni.body) as body
from
seminar_reseni
inner join seminar_cisla on seminar_reseni.cislo_body_id = seminar_cisla.id
inner join seminar_rocniky on seminar_cisla.rocnik_id = seminar_rocniky.id
group by seminar_reseni.cislo_body_id, seminar_reseni.resitel_id, seminar_cisla.cislo,
seminar_cisla.rocnik_id, seminar_rocniky.rocnik, seminar_cisla.verejna_vysledkovka
order by body desc;
create view seminar_body_k_cislu_rocnik as
select
akt_body.id as id,
akt_body.cislo_id as cislo_id,
akt_body.resitel_id as resitel_id,
akt_body.body as body,
sum(min_body.body) as body_celkem
from
seminar_body_za_cislo as akt_body
inner join seminar_body_za_cislo as min_body on
(akt_body.resitel_id = min_body.resitel_id and
(akt_body.rocnik = min_body.rocnik and akt_body.cislo >= min_body.cislo)
)
group by akt_body.id, akt_body.cislo_id, akt_body.resitel_id, akt_body.body
order by body_celkem desc;
create view seminar_body_k_cislu_odjakziva as
select
akt_body.id as id,
akt_body.cislo_id as cislo_id,
akt_body.resitel_id as resitel_id,
akt_body.body as body,
sum(min_body.body) as body_celkem
from
seminar_body_za_cislo as akt_body
inner join seminar_body_za_cislo as min_body on
(akt_body.resitel_id = min_body.resitel_id and
((akt_body.rocnik = min_body.rocnik and akt_body.cislo >= min_body.cislo) or
(akt_body.rocnik < min_body.rocnik)
)
)
group by akt_body.id, akt_body.cislo_id, akt_body.resitel_id, akt_body.body
order by body_celkem desc;
"""
class Migration(migrations.Migration):
dependencies = [("seminar", "0027_export_flag_a_typ_akce")]
operations = [
migrations.RunSQL(sql=CREATE_VIEWS)
]

51
seminar/migrations/0029_fix_body_celkem_views.py

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django_countries.fields
import seminar.models
import django.utils.timezone
from django.conf import settings
CREATE_VIEWS="""
drop view seminar_body_k_cislu_rocnik;
create view seminar_body_k_cislu_rocnik as
select
seminar_cisla.id || '-' || min_body.resitel_id as id,
seminar_cisla.id as cislo_id,
min_body.resitel_id as resitel_id,
sum(min_body.body) as body
from
seminar_cisla
inner join seminar_body_za_cislo as min_body on
(min_body.rocnik_id = seminar_cisla.rocnik_id and seminar_cisla.cislo >= min_body.cislo)
group by seminar_cisla.id, min_body.resitel_id
order by body desc;
drop view seminar_body_k_cislu_odjakziva;
create view seminar_body_k_cislu_odjakziva as
select
seminar_cisla.id || '-' || min_body.resitel_id as id,
seminar_cisla.id as cislo_id,
min_body.resitel_id as resitel_id,
sum(min_body.body) as body
from
seminar_cisla
inner join seminar_rocniky on
(seminar_cisla.rocnik_id = seminar_rocniky.id)
inner join seminar_body_za_cislo as min_body on
(min_body.rocnik_id = seminar_cisla.rocnik_id and seminar_cisla.cislo >= min_body.cislo) or
(min_body.rocnik < seminar_rocniky.rocnik)
group by seminar_cisla.id, min_body.resitel_id
order by body desc;
"""
class Migration(migrations.Migration):
dependencies = [("seminar", "0028_add_body_celkem_views")]
operations = [
migrations.RunSQL(sql=CREATE_VIEWS)
]

30
seminar/models.py

@ -650,9 +650,9 @@ class VysledkyBase(SeminarModelBase):
def __str__(self):
return force_unicode(u"%s: %sb (%s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
# NOTE: DB HOG (ale nepouzivany)
# NOTE: DB zatez pri vypisu (ale nepouzivany)
@python_2_unicode_compatible
class VysledkyZaCislo(VysledkyBase):
class Meta:
@ -660,25 +660,27 @@ class VysledkyZaCislo(VysledkyBase):
abstract = False
managed = False
def __str__(self):
# NOTE: DB HOG (ale nepouzivany)
return force_unicode(u"%s: %sb (za %s)" % (self.resitel.plne_jmeno(), self.body, str(self.cislo)))
@python_2_unicode_compatible
class VysledkyKCislu(VysledkyBase):
class VysledkyKCisluZaRocnik(VysledkyBase):
class Meta:
db_table = 'seminar_body_k_cislu'
db_table = 'seminar_body_k_cislu_rocnik'
abstract = False
managed = False
body_celkem = models.DecimalField(max_digits=8, decimal_places=1, db_column='body_celkem',
verbose_name=u'body celkem do čísla')
# body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body',
# verbose_name=u'body do čísla (za ročník)')
def __str__(self):
# NOTE: DB HOG (ale nepouzivany)
return force_unicode(u"%s: %sb / %sb (do %s)" % (self.resitel.plne_jmeno(), self.body, self.body_celkem, str(self.cislo)))
class VysledkyKCisluOdjakziva(VysledkyBase):
class Meta:
db_table = 'seminar_body_k_cislu_odjakziva'
abstract = False
managed = False
# body = models.DecimalField(max_digits=8, decimal_places=1, db_column='body',
# verbose_name=u'body do čísla (i minulé ročníky)')
@python_2_unicode_compatible

10
seminar/templates/seminar/archiv/cislo.html

@ -34,17 +34,19 @@
{% for p in problemy %}
<th class='border-r'><a href="{{ p.verejne_url }}">{{ p.cislo_zadani.cislo }}.{{ p.kod }}</a>
{% endfor %}
<th class='border-r'>Sum
<th class='border-r'>Sum<sup>-1</sup>
<th>Celkem
<th>Odjakživa
{% for rv in vysledkovka %}
<tr>
<td class='border-r'>{{ rv.poradi }}
<th class='border-r'>{{ rv.resitel.plne_jmeno }} [{{ rv.resitel.id }}]
<th class='border-r'>{{ rv.resitel.plne_jmeno }} {{ rv.titul }}
{% for b in rv.body %}
<td class='border-r'>{{ b }}
{% endfor %}
<td class='border-r'>{{ rv.vysledek.body |default:0 }}
<td>{{ rv.vysledek.body_celkem }}
<td class='border-r'>{{ rv.body_minule }}
<td><b>{{ rv.body_celkem_rocnik }}</b>
<td>{{ rv.body_celkem_odjakziva }}
</tr>
{% endfor %}
</table>

4
seminar/templates/seminar/archiv/cislo_vysledkovka.tex

@ -22,12 +22,12 @@
{% for rv in vysledkovka %}
{{ rv.poradi }} &
{% if rv.resitel.titul %}
\titul{ {{ rv.resitel.titul }} }
\titul{ {{ rv.titul }} }
{% endif %}
{{ rv.resitel.plne_jmeno }} & {{ rv.resitel.rocnik |default:"" }} & {{ rv.body_minule }}
{% for b in rv.body %}
{{ b }} &
{% endfor %}
{{ rv.vysledek.body |default:0 }} & {{ rv.vysledek.body_celkem }} \\
{{ rv.body_celkem_rocnik |default:0 }} & {{ rv.body_celkem_minule }} \\
{% endfor %}
\end{longtable}

24
seminar/templates/seminar/stav_databaze.html

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block content %}
<div>
<h2>Stav databáze</h2>
<h3>Řešitelé</h3>
<div>Řešitelů: {{ resitele |length}} ({{ muzi |length}} mužů, {{ zeny |length}} žen)</div>
<div>Křestní jména mužů:</div>
<p><code>{% for n, c in jmena_muzu.items %}{{ n }} ({{ c }}), {% endfor %}</code>
<div>Křestní jména žen:</div>
<p><code>{% for n, c in jmena_zen.items %}{{ n }} ({{ c }}), {% endfor %}</code>
<h3>Nastavení</h3>
<h3>Problémy</h3>
{% for p in problemy %}
<div>{{ p |safe }}</div>
{% endfor %}
</div>
{% endblock content %}

2
seminar/urls.py

@ -17,6 +17,8 @@ urlpatterns = patterns('',
url(r'^zadani/aktualni/$', views.AktualniZadaniView, name='seminar_aktualni_zadani'),
url(r'^stav$', views.StavDatabazeView, name='stav_databaze'),
url(r'^aesop-export/mam-rocnik-(?P<prvni_rok>\d+)\.csv$', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'),
url(r'^aesop-export/mam-sous-(?P<datum_zacatku>[\d-]+)\.csv$', export.ExportSousView.as_view(), name='seminar_export_sous'),
url(r'^aesop-export/index.csv$', export.ExportIndexView.as_view(), name='seminar_export_index'),

58
seminar/utils.py

@ -1,5 +1,17 @@
# -*- coding: utf-8 -*-
import datetime
def histogram(seznam):
d = {}
for i in seznam:
if i not in d:
d[i] = 0
d[i] += 1
return d
roman_numerals = zip((1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1),
('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I'))
@ -18,3 +30,49 @@ def from_roman(rom):
return i + from_roman(rom[len(n):])
raise Exception('Invalid roman numeral: "%s"', rom)
def seznam_problemu():
from .models import Problem, Resitel, Rocnik, Reseni, Cislo
problemy = []
# Pomocna fce k formatovani problemovych hlasek
def prb(cls, msg, objs=None):
s = u'<b>%s:</b> %s' % (cls.__name__, msg)
if objs:
s += u' ['
for o in objs:
try:
url = o.admin_url()
except:
url = None
if url:
s += u'<a href="%s">%s</a>, ' % (url, o.pk, )
else:
s += u'%s, ' % (o.pk, )
s = s[:-2] + u']'
problemy.append(s)
# Duplicita jmen
jmena = {}
for r in Resitel.objects.all():
j = r.plne_jmeno()
if j not in jmena:
jmena[j] = []
jmena[j].append(r)
for j in jmena:
if len(jmena[j]) > 1:
prb(Resitel, u'Duplicitní jméno "%s"' % (j, ), jmena[j])
# Data maturity a narození
for r in Resitel.objects.all():
if not r.rok_maturity:
prb(Resitel, u'Neznámý rok maturity', [r])
if r.rok_maturity and (r.rok_maturity < 1990 or r.rok_maturity > datetime.date.today().year + 10):
prb(Resitel, u'Podezřelé datum maturity', [r])
if r.datum_narozeni and (r.datum_narozeni.year < 1970 or r.datum_narozeni.year > datetime.date.today().year - 12):
prb(Resitel, u'Podezřelé datum narození', [r])
# if not r.email:
# prb(Resitel, u'Neznámý email', [r])
return problemy

51
seminar/views.py

@ -5,8 +5,9 @@ from django.views import generic
from django.utils.translation import ugettext as _
from django.http import Http404
from .models import Problem, Cislo, Reseni, VysledkyKCislu, Nastaveni, Rocnik, Soustredeni, Organizator
from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel
from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from . import utils
def AktualniZadaniView(request):
nastaveni = get_object_or_404(Nastaveni)
@ -146,7 +147,7 @@ class CisloView(generic.DetailView):
def get_context_data(self, **kwargs):
context = super(CisloView, self).get_context_data(**kwargs)
vysledky = VysledkyKCislu.objects.filter(cislo = context['cislo']).order_by('-body_celkem').select_related("resitel")
vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).order_by('-body').select_related("resitel")
reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel")
problemy = sorted(list(set([r.problem for r in reseni])), key=lambda x:(0 if x.typ==Problem.TYP_ULOHA else 1,x.kod))
@ -168,17 +169,22 @@ class CisloView(generic.DetailView):
v = vysledky[vi]
tv = RadekVysledkovky()
tv.resitel = v.resitel
tv.rocnik = tv.resitel.rocnik(context['cislo'].datum_vydani)
tv.resitel.titul = tv.resitel.titul(v.body_celkem)
tv.rocnik = tv.resitel.rocnik(context['cislo'].rocnik)
tv.vysledek = v
#odkazuje na VysledkyKCislu
tv.body = ['']*len(problemy)
#pole bodu za ulohy
tv.poradi = ''
#defaultni poradi je prazdne - kvuli sdilenym mistum
tv.body_minule = 0
tv.body_celkem_rocnik = v.body
tv.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body
body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo'])
tv.body_cislo = body_cislo_q[0].body if len(body_cislo_q) > 0 else 0
tv.body_minule = tv.body_celkem_rocnik - tv.body_cislo
tv.titul = tv.resitel.titul(tv.body_celkem_odjakziva)
#pocet bodu do tohoto cisla
if posledni_body > v.body_celkem:
if posledni_body > tv.body_celkem_rocnik:
if stejne_body.get(posledni_body):
konec_rozmezi[posledni_body] = int(predchozi_poradi.poradi) + stejne_body[posledni_body]
#druha hranice sdilenych pozic - zacatek + pocet lidi se stejnymi body
@ -187,16 +193,16 @@ class CisloView(generic.DetailView):
elif predchozi_poradi :
predchozi_poradi.poradi = '{0}.'.format(predchozi_poradi.poradi)
#pokud nebyl rozsah hodnot, pridam tecku za cislo
posledni_body = v.body_celkem
posledni_body = tv.body_celkem_rocnik
tv.poradi = vi + 1
#poradi se meni jen u resitele s rozdilnym poctem bodu nez mel minuly
predchozi_poradi = tv
elif posledni_body == v.body_celkem:
if not stejne_body.get(v.body_celkem):
stejne_body[v.body_celkem] = 1
elif posledni_body == tv.body_celkem_rocnik:
if not stejne_body.get(tv.body_celkem_rocnik):
stejne_body[tv.body_celkem_rocnik] = 1
#pokud klic neexistuje, zalozim novy pro tohoto resitele
else:
stejne_body[v.body_celkem] += 1
stejne_body[tv.body_celkem_rocnik] += 1
#rozsirim pocet resitelu sdilejici stejnou pozici
vysledky_resitele[v.resitel.id] = tv
#odkaz na radek vysledkovky patrici danemu resiteli
@ -204,10 +210,6 @@ class CisloView(generic.DetailView):
for r in reseni:
vysledky_resitele[r.resitel.id].body[problem_index[r.problem.id]] = r.body
body_za_cislo = vysledky_resitele[r.resitel.id].vysledek.body
#body za toto cislo, stejne jako tv.vysledek.body
body_celkem = vysledky_resitele[r.resitel.id].vysledek.body_celkem
vysledky_resitele[r.resitel.id].body_minule = body_celkem - body_za_cislo
context['vysledkovka'] = vysledkovka
@ -242,3 +244,22 @@ class SoustredeniListView(generic.ListView):
class SoustredeniView(generic.DetailView):
model = Soustredeni
template_name = 'seminar/archiv/soustredeni.html'
### Status
def StavDatabazeView(request):
# nastaveni = Nastaveni.objects.get()
problemy = utils.seznam_problemu()
muzi = Resitel.objects.filter(pohlavi_muz=True)
zeny = Resitel.objects.filter(pohlavi_muz=False)
return render(request, 'seminar/stav_databaze.html',
{
# 'nastaveni': nastaveni,
'problemy': problemy,
'resitele': Resitel.objects.all(),
'muzi': muzi,
'zeny': zeny,
'jmena_muzu': utils.histogram([r.jmeno for r in muzi]),
'jmena_zen': utils.histogram([r.jmeno for r in zeny]),
})

Loading…
Cancel
Save