Merge branch 'data_migrations' of gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb into data_migrations
This commit is contained in:
		
						commit
						4ed15d16a7
					
				
					 4 changed files with 67 additions and 69 deletions
				
			
		|  | @ -18,6 +18,7 @@ from django.contrib.contenttypes.models import ContentType | |||
| from django.utils.text import get_valid_filename | ||||
| from imagekit.models import ImageSpecField, ProcessedImageField | ||||
| from imagekit.processors import ResizeToFit, Transpose | ||||
| from django.utils.functional import cached_property | ||||
| 
 | ||||
| from django_countries.fields import CountryField | ||||
| from solo.models import SingletonModel | ||||
|  | @ -855,10 +856,11 @@ class Problem(SeminarModelBase,PolymorphicModel): | |||
| 		return self.nazev | ||||
| 
 | ||||
| 	# Implicitini implementace, jednotlivé dědící třídy si přepíšou | ||||
| 	@cached_property | ||||
| 	def kod_v_rocniku(self): | ||||
| 		if self.stav == 'zadany': | ||||
| 			if self.nadproblem: | ||||
| 				return self.nadproblem.kod_v_rocniku()+".{}".format(self.kod) | ||||
| 				return self.nadproblem.kod_v_rocniku+".{}".format(self.kod) | ||||
| 			return str(self.kod) | ||||
| 		return '<Není zadaný>' | ||||
| 
 | ||||
|  | @ -927,10 +929,11 @@ class Tema(Problem): | |||
| 	abstrakt = models.TextField('Abstrakt na rozcestník', blank=True) | ||||
| 	obrazek = models.ImageField('Obrázek na rozcestník', null=True) | ||||
| 
 | ||||
| 	@cached_property | ||||
| 	def kod_v_rocniku(self): | ||||
| 		if self.stav == 'zadany': | ||||
| 			if self.nadproblem: | ||||
| 				return self.nadproblem.kod_v_rocniku()+".t{}".format(self.kod) | ||||
| 				return self.nadproblem.kod_v_rocniku+".t{}".format(self.kod) | ||||
| 			return "t{}".format(self.kod) | ||||
| 		return '<Není zadaný>' | ||||
| 
 | ||||
|  | @ -963,7 +966,7 @@ class Clanek(Problem): | |||
| 		if self.stav == 'zadany': | ||||
| # Nemělo by být potřeba | ||||
| #			if self.nadproblem: | ||||
| #				return self.nadproblem.kod_v_rocniku()+".c{}".format(self.kod) | ||||
| #				return self.nadproblem.kod_v_rocniku+".c{}".format(self.kod) | ||||
| 			return "c{}".format(self.kod) | ||||
| 		return '<Není zadaný>' | ||||
| 	 | ||||
|  | @ -1020,11 +1023,12 @@ class Uloha(Problem): | |||
| 	# UlohaZadaniNode | ||||
| 	# UlohaVzorakNode | ||||
| 
 | ||||
| 	@cached_property | ||||
| 	def kod_v_rocniku(self): | ||||
| 		if self.stav == 'zadany': | ||||
| 			name="{}.u{}".format(self.cislo_zadani.poradi,self.kod) | ||||
| 			if self.nadproblem: | ||||
| 				return self.nadproblem.kod_v_rocniku()+name | ||||
| 				return self.nadproblem.kod_v_rocniku+name | ||||
| 			return name | ||||
| 		return '<Není zadaný>' | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,10 +17,11 @@ import seminar.treelib as t | |||
| org_required = permission_required('auth.org', raise_exception=True) | ||||
| resitel_required = permission_required('auth.resitel', raise_exception=True) | ||||
| User = get_user_model() | ||||
| User.je_org = lambda self: self.has_perm('auth.org') | ||||
| User.je_resitel = lambda self: self.has_perm('auth.resitel') | ||||
| AnonymousUser.je_org = lambda self: False | ||||
| AnonymousUser.je_resitel = lambda self: False | ||||
| # Není to úplně hezké, ale budeme doufat, že to je funkční... | ||||
| User.je_org = property(lambda self: self.has_perm('auth.org')) | ||||
| User.je_resitel = property(lambda self: self.has_perm('auth.resitel')) | ||||
| AnonymousUser.je_org = False | ||||
| AnonymousUser.je_resitel = False | ||||
| 
 | ||||
| 
 | ||||
| class FirstTagParser(HTMLParser): | ||||
|  | @ -239,47 +240,25 @@ def hlavni_problem(problem): | |||
| 		problem = problem.nadproblem | ||||
| 	return problem | ||||
| 
 | ||||
| def hlavni_problemy_rocniku(rocnik, jen_verejne=True): | ||||
| 	""" Pro zadaný ročník vrátí hlavní problémy ročníku, | ||||
| 	tj. ty, které už nemají nadproblém.""" | ||||
| 	hlavni_problemy = [] | ||||
| 	for cislo in cisla_rocniku(rocnik, jen_verejne): | ||||
| 		for problem in hlavni_problemy_cisla(cislo): | ||||
| 			hlavni_problemy.append(problem) | ||||
| 	hlavni_problemy_set = set(hlavni_problemy) | ||||
| 	hlavni_problemy = list(hlavni_problemy_set) | ||||
| 	hlavni_problemy.sort(key=lambda k:k.kod_v_rocniku()) # setřídit podle pořadí | ||||
| 	 | ||||
| 	return hlavni_problemy | ||||
| def problemy_rocniku(rocnik, jen_verejne=True): | ||||
| 	return  m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body__in = cisla_rocniku(rocnik, jen_verejne))).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem') | ||||
| 
 | ||||
| def problemy_cisla(cislo): | ||||
| 	""" Vrátí seznam všech problémů s body v daném čísle. """ | ||||
| 	hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all() | ||||
| 	# hodnocení, která se vážou k danému číslu | ||||
| 	 | ||||
| 	reseni = [h.reseni for h in hodnoceni] | ||||
| 	problemy = [h.problem for h in hodnoceni] | ||||
| 	problemy_set = set(problemy)  # chceme každý problém unikátně, | ||||
| 	problemy = (list(problemy_set))  # převedení na množinu a zpět to zaručí | ||||
| 
 | ||||
| 	return problemy | ||||
| 	return m.Problem.objects.filter(hodnoceni__in = m.Hodnoceni.objects.filter(cislo_body = cislo)).distinct().select_related('nadproblem').select_related('nadproblem__nadproblem') | ||||
| 
 | ||||
| 
 | ||||
| def hlavni_problemy_cisla(cislo, problemy=None): | ||||
| 	""" Vrátí seznam všech problémů s body v daném čísle, které již nemají nadproblém. """ | ||||
| 	if problemy is None: | ||||
| 		problemy = problemy_cisla(cislo) | ||||
| 
 | ||||
| def hlavni_problemy_f(problemy=None): | ||||
| 	""" Vrátí seznam všech problémů, které již nemají nadproblém. """ | ||||
| 	# hlavní problémy čísla  | ||||
| 	# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém) | ||||
| 	hlavni_problemy = [] | ||||
| 	hlavni_problemy = set() | ||||
| 	for p in problemy: | ||||
| 		hlavni_problemy.append(hlavni_problem(p)) | ||||
| 		hlavni_problemy.add(hlavni_problem(p)) | ||||
| 		 | ||||
| 	# zunikátnění | ||||
| 	hlavni_problemy_set = set(hlavni_problemy) | ||||
| 	hlavni_problemy = list(hlavni_problemy_set) | ||||
| 	hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku()) # setřídit podle t1, t2, c3, ... | ||||
| 	hlavni_problemy = list(hlavni_problemy) | ||||
| 	hlavni_problemy.sort(key=lambda k: k.kod_v_rocniku) # setřídit podle t1, t2, c3, ... | ||||
| 	 | ||||
| 	return hlavni_problemy | ||||
| 
 | ||||
|  | @ -289,7 +268,7 @@ def podproblemy_v_cislu(cislo, problemy=None, hlavni_problemy=None): | |||
| 	if problemy is None: | ||||
| 		problemy = problemy_cisla(cislo) | ||||
| 	if hlavni_problemy is None: | ||||
| 		hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) | ||||
| 		hlavni_problemy = hlavni_problemy_f(problemy) | ||||
| 
 | ||||
| 	podproblemy = dict((hp.id, []) for hp in hlavni_problemy) | ||||
| 	hlavni_problemy = set(hlavni_problemy) | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ import csv | |||
| import logging | ||||
| import time | ||||
| 
 | ||||
| from seminar.utils import aktivniResitele, resi_v_rocniku, hlavni_problemy_rocniku, cisla_rocniku, hlavni_problemy_cisla | ||||
| from seminar.utils import aktivniResitele, resi_v_rocniku, problemy_rocniku, cisla_rocniku, hlavni_problemy_f | ||||
| 
 | ||||
| # ze starého modelu | ||||
| #def verejna_temata(rocnik): | ||||
|  | @ -644,29 +644,25 @@ class RocnikView(generic.DetailView): | |||
| 	def get_object(self, queryset=None): | ||||
| 		if queryset is None: | ||||
| 			queryset = self.get_queryset() | ||||
| 		rocnik_arg = self.kwargs.get('rocnik') | ||||
| 		queryset = queryset.filter(rocnik=rocnik_arg) | ||||
| 
 | ||||
| 		try: | ||||
| 			obj = queryset.get() | ||||
| 		except queryset.model.DoesNotExist: | ||||
| 			raise Http404(_("No %(verbose_name)s found matching the query") % | ||||
| 						{'verbose_name': queryset.model._meta.verbose_name}) | ||||
| 		return obj | ||||
| 		return get_object_or_404(queryset,rocnik=self.kwargs.get('rocnik')) | ||||
| 
 | ||||
| 	def get_context_data(self, **kwargs): | ||||
| 		start = time.time() | ||||
| 		context = super(RocnikView, self).get_context_data(**kwargs) | ||||
| 
 | ||||
| 		# vysledkovka = True zajistí vykreslení, | ||||
| 		# zkontrolovat, kdy se má a nemá vykreslovat | ||||
| 		context['vysledkovka'] = True | ||||
| 		context['cisla_s_neverejnymi'] = cisla_rocniku(context["rocnik"], jen_verejne=False) | ||||
| 		if self.request.user.je_org: | ||||
| 			context['cisla_s_neverejnymi'] = cisla_rocniku(context["rocnik"], jen_verejne=False) | ||||
| 			context['radky_vysledkovky_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False) | ||||
| 			context['hlavni_problemy_v_rocniku_s_neverejnymi'] = hlavni_problemy_f(problemy_rocniku(context["rocnik"], jen_verejne=False)) | ||||
| 		context['cisla'] = cisla_rocniku(context["rocnik"]) | ||||
| 		context['radky_vysledkovky'] = vysledkovka_rocniku(context["rocnik"]) | ||||
| 		context['radky_vysledkovky_s_neverejnymi'] = vysledkovka_rocniku( | ||||
| 			context["rocnik"], jen_verejne=False) | ||||
| 		context['hlavni_problemy_v_rocniku'] = hlavni_problemy_rocniku(context["rocnik"]) | ||||
| 		context['hlavni_problemy_v_rocniku_s_neverejnymi'] = hlavni_problemy_rocniku(context["rocnik"], jen_verejne=False) | ||||
| 		context['hlavni_problemy_v_rocniku'] = hlavni_problemy_f(problemy_rocniku(context["rocnik"])) | ||||
| 		end = time.time() | ||||
| 		print("Kontext:", end-start) | ||||
| 
 | ||||
| 		return context | ||||
| 
 | ||||
|  | @ -973,7 +969,7 @@ class ClankyResitelView(generic.ListView): | |||
| 		queryset = [] | ||||
| 		skupiny_clanku = group_by_rocnik(clanky) | ||||
| 		for skupina in skupiny_clanku: | ||||
| 			skupina.sort(key=lambda clanek: clanek.kod_v_rocniku()) | ||||
| 			skupina.sort(key=lambda clanek: clanek.kod_v_rocniku) | ||||
| 			for clanek in skupina: | ||||
| 				queryset.append(clanek) | ||||
| 		return queryset | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| import seminar.models as m | ||||
| from django.db.models import Q, Sum, Count | ||||
| from seminar.utils import aktivniResitele, resi_v_rocniku, cisla_rocniku, hlavni_problemy_rocniku, hlavni_problem, hlavni_problemy_cisla, problemy_cisla, podproblemy_v_cislu | ||||
| from seminar.utils import aktivniResitele, resi_v_rocniku, cisla_rocniku, hlavni_problem, hlavni_problemy_f, problemy_cisla, podproblemy_v_cislu | ||||
| import time | ||||
| ### Výsledky | ||||
| 
 | ||||
| def sloupec_s_poradim(setrizene_body): | ||||
|  | @ -126,15 +127,16 @@ class RadekVysledkovkyRocniku(object): | |||
| 
 | ||||
| def setrid_resitele_a_body(slov_resitel_body): | ||||
| 	setrizeni_resitele_id = [dvojice[0] for dvojice in slov_resitel_body] | ||||
| 	setrizeni_resitele = [m.Resitel.objects.get(id=i) for i in setrizeni_resitele_id] | ||||
| 	setrizene_body = [dvojice[1] for dvojice in slov_resitel_body] | ||||
| 	return setrizeni_resitele_id, setrizeni_resitele, setrizene_body | ||||
| 	return setrizeni_resitele_id,  setrizene_body | ||||
| 
 | ||||
| def vysledkovka_rocniku(rocnik, jen_verejne=True): | ||||
| 	""" Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve | ||||
| 	formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" | ||||
| 	""" | ||||
| 	 | ||||
| 	start = time.time() | ||||
| 
 | ||||
| 	## TODO možná chytřeji vybírat aktivní řešitele | ||||
| 	# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají  | ||||
| 	# u alespoň jedné hodnoty něco jiného než NULL | ||||
|  | @ -150,7 +152,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): | |||
| 	resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele) | ||||
| 
 | ||||
| 	# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší | ||||
| 	setrizeni_resitele_id, setrizeni_resitele, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) | ||||
| 	setrizeni_resitele_id, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) | ||||
| 	poradi = sloupec_s_poradim(setrizene_body) | ||||
| 
 | ||||
| 	# získáme body odjakživa | ||||
|  | @ -159,6 +161,10 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): | |||
| 	# vytvoříme jednotlivé sloupce výsledkovky | ||||
| 	radky_vysledkovky = [] | ||||
| 	i = 0 | ||||
| 	setrizeni_resitele_dict = {} # Tento slovnik se vyrab | ||||
| 	for r in m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba'): | ||||
| 		setrizeni_resitele_dict[r.id] = r | ||||
| 	 | ||||
| 	for ar_id in setrizeni_resitele_id: | ||||
| 		# seznam počtu bodů daného řešitele pro jednotlivá čísla | ||||
| 		body_cisla_sezn = [] | ||||
|  | @ -168,7 +174,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): | |||
| 		# vytáhneme informace pro daného řešitele | ||||
| 		radek = RadekVysledkovkyRocniku( | ||||
| 			poradi[i], # pořadí | ||||
| 			m.Resitel.objects.get(id=ar_id), # řešitel (z id) | ||||
| 			setrizeni_resitele_dict[ar_id], # řešitel (z id) | ||||
| 			body_cisla_sezn, # seznam bodů za čísla | ||||
| 			setrizene_body[i], # body za ročník (spočítané výše s pořadím) | ||||
| 			resitel_odjakzivabody_slov[ar_id], # body odjakživa | ||||
|  | @ -176,7 +182,11 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True): | |||
| 		radky_vysledkovky.append(radek) | ||||
| 		i += 1 | ||||
| 
 | ||||
| 	end = time.time() | ||||
| 	print("Vysledkovka rocniku",end-start) | ||||
| 
 | ||||
| 	return radky_vysledkovky | ||||
| 
 | ||||
| class RadekVysledkovkyCisla(object): | ||||
| 	"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. | ||||
| 	Umožňuje snazší práci v templatu (lepší, než seznam).""" | ||||
|  | @ -225,17 +235,18 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): | |||
| 	# TODO setřídit hlavní problémy čísla podle id, ať jsou ve stejném pořadí pokaždé | ||||
| 	# pro každý hlavní problém zavedeme slovník s body za daný hlavní problém  | ||||
| 	# pro jednotlivé řešitele (slovník slovníků hlavních problémů) | ||||
| 
 | ||||
| 	print("Scitam cislo",cislo) | ||||
| 
 | ||||
| 	if hlavni_problemy is None: | ||||
| 		hlavni_problemy = hlavni_problemy_cisla(cislo) | ||||
| 		hlavni_problemy = hlavni_problemy_f(problemy_cisla(cislo)) | ||||
| 
 | ||||
| 	def ne_clanek_ne_konfera(problem): | ||||
| 		return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera)) | ||||
| 		inst = problem.get_real_instance() | ||||
| 		return not(isinstance(inst, m.Clanek) or isinstance(inst, m.Konfera)) | ||||
| 
 | ||||
| 	temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) | ||||
| 
 | ||||
| 	def cosi(problem): | ||||
| 		return problem.id | ||||
| 
 | ||||
| 	hlavni_problemy_slovnik = {} | ||||
| 	for hp in temata_a_spol: | ||||
| 		hlavni_problemy_slovnik[hp.id] = {} | ||||
|  | @ -257,6 +268,7 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): | |||
| 	reseni_do_cisla = m.Reseni.objects.prefetch_related('problem', 'resitele',  | ||||
| 				'hodnoceni_set').filter(hodnoceni__cislo_body=cislo) | ||||
| 	 | ||||
| 	start = time.time()	 | ||||
| 	# projdeme všechna řešení do čísla a přičteme body každému řešiteli do celkových | ||||
| 	# bodů i do bodů za problém | ||||
| 	for reseni in reseni_do_cisla: | ||||
|  | @ -280,13 +292,15 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy=None): | |||
| 						continue | ||||
| 					pricti_body(cislobody, resitel, body) | ||||
| 					pricti_body(nadproblem_slovnik, resitel, body) | ||||
| 	end = time.time() | ||||
| 	print("for cykly:", end-start) | ||||
| 	return hlavni_problemy_slovnik, cislobody | ||||
| 
 | ||||
| 
 | ||||
| def secti_body_za_cislo_podle_temat(cislo, aktivni_resitele, podproblemy=None, temata=None): | ||||
| 	""" Spočítá u řešitelů body za číslo za úlohy v jednotlivých hlavních problémech (témata).""" | ||||
| 	if temata is None: | ||||
| 		temata = hlavni_problemy_cisla(cislo) | ||||
| 		temata = hlavni_problemy_f(problemy_cisla(cislo)) | ||||
| 
 | ||||
| 	if podproblemy is None: | ||||
| 		podproblemy_v_cislu(cislo, hlavni_problemy=temata) | ||||
|  | @ -356,7 +370,7 @@ def vysledkovka_cisla(cislo, context=None): | |||
| 	if context is None: | ||||
| 		context = {} | ||||
| 	problemy = problemy_cisla(cislo) | ||||
| 	hlavni_problemy = hlavni_problemy_cisla(cislo, problemy) | ||||
| 	hlavni_problemy = hlavni_problemy_f(problemy) | ||||
| 	## TODO možná chytřeji vybírat aktivní řešitele | ||||
| 	# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají  | ||||
| 	# u alespoň jedné hodnoty něco jiného než NULL | ||||
|  | @ -373,7 +387,6 @@ def vysledkovka_cisla(cislo, context=None): | |||
| 
 | ||||
| 	# řešitelé setřídění podle bodů za číslo sestupně | ||||
| 	setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] | ||||
| 	setrizeni_resitele = [m.Resitel.objects.get(id=i) for i in setrizeni_resitele_id] | ||||
| 			 | ||||
| 	# spočítáme pořadí řešitelů | ||||
| 	setrizeni_resitele_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn] | ||||
|  | @ -384,6 +397,7 @@ def vysledkovka_cisla(cislo, context=None): | |||
| 	i = 0 | ||||
| 
 | ||||
| 	def ne_clanek_ne_konfera(problem): | ||||
| 		 | ||||
| 		return not(isinstance(problem.get_real_instance(), m.Clanek) or isinstance(problem.get_real_instance(), m.Konfera)) | ||||
| 
 | ||||
| 	temata_a_spol = list(filter(ne_clanek_ne_konfera, hlavni_problemy)) | ||||
|  | @ -399,6 +413,11 @@ def vysledkovka_cisla(cislo, context=None): | |||
| 
 | ||||
| 	je_nejake_ostatni = len(hlavni_problemy) - len(temata_a_spol) > 0 | ||||
| 
 | ||||
| 	setrizeni_resitele_slovnik = {} | ||||
| 	setrizeni_resitele = m.Resitel.objects.filter(id__in=setrizeni_resitele_id).select_related('osoba') | ||||
| 	for r in setrizeni_resitele: | ||||
| 		setrizeni_resitele_slovnik[r.id] = r | ||||
| 
 | ||||
| 	for ar_id in setrizeni_resitele_id: | ||||
| 		# získáme seznam bodů za problémy pro daného řešitele | ||||
| 		body_problemy = [] | ||||
|  | @ -412,7 +431,7 @@ def vysledkovka_cisla(cislo, context=None): | |||
| 		# vytáhneme informace pro daného řešitele | ||||
| 		radek = RadekVysledkovkyCisla( | ||||
| 			poradi[i], # pořadí | ||||
| 			m.Resitel.objects.get(id=ar_id), # řešitel (z id) | ||||
| 			setrizeni_resitele_slovnik[ar_id], # řešitel (z id) | ||||
| 			body_problemy, # seznam bodů za hlavní problémy čísla | ||||
| 			cislobody[ar_id], # body za číslo | ||||
| 			setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Kateřina Č
						Kateřina Č