Výsledkovka čísla přesunuta do funkce a rozsekána na menší kusy, optimalizace kódu.
This commit is contained in:
		
							parent
							
								
									ec670a627e
								
							
						
					
					
						commit
						3b328e4b00
					
				
					 1 changed files with 152 additions and 160 deletions
				
			
		|  | @ -106,18 +106,22 @@ class TreeNodeView(generic.DetailView): | |||
| 		return context | ||||
| 	 | ||||
| 
 | ||||
| class AktualniZadaniView(TreeNodeView): | ||||
| 	def get_object(self): | ||||
| 		nastaveni = get_object_or_404(Nastaveni) | ||||
| 		return nastaveni.aktualni_cislo.cislonode | ||||
| 
 | ||||
| 	def get_context_data(self,**kwargs): | ||||
| 		nastaveni = get_object_or_404(Nastaveni) | ||||
| 		context = super().get_context_data(**kwargs) | ||||
| 		verejne = nastaveni.aktualni_cislo.verejne() | ||||
| 		context['verejne'] = verejne	 | ||||
| 		return context | ||||
| 
 | ||||
| #def AktualniZadaniView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
| #	verejne = nastaveni.aktualni_cislo.verejne() | ||||
| #	problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany') | ||||
| #	ulohy = problemy.filter(typ = 'uloha').order_by('kod') | ||||
| #	serialy = problemy.filter(typ = 'serial').order_by('kod') | ||||
| #	jednorazove_problemy = [ulohy, serialy] | ||||
| #	return render(request, 'seminar/zadani/AktualniZadani.html', | ||||
| #			{'nastaveni': nastaveni, | ||||
| #			 'jednorazove_problemy': jednorazove_problemy, | ||||
| #			 'temata': verejna_temata(nastaveni.aktualni_rocnik), | ||||
| #			 'verejne': verejne, | ||||
| #				}, | ||||
| #			) | ||||
| # | ||||
| #def ZadaniTemataView(request): | ||||
| #	nastaveni = get_object_or_404(Nastaveni) | ||||
| #	temata = verejna_temata(nastaveni.aktualni_rocnik) | ||||
|  | @ -285,6 +289,7 @@ class CojemamOrganizatoriStariView(generic.ListView): | |||
| 
 | ||||
| ### Archiv | ||||
| 
 | ||||
| 
 | ||||
| class ArchivView(generic.ListView): | ||||
| 	model = Rocnik | ||||
| 	template_name='seminar/archiv/cisla.html' | ||||
|  | @ -295,16 +300,13 @@ class ArchivView(generic.ListView): | |||
| 		vyska = 297  # px | ||||
| 		sirka = 210  # px | ||||
| 
 | ||||
| 		# nejnovějších 10 zveřejněných čísel | ||||
| 		cisla = Cislo.objects.filter(verejne_db=True)[:10] | ||||
| 
 | ||||
| 		# op = os.path, udělá z argumentů cestu | ||||
| 		png_dir = op.join(settings.MEDIA_ROOT, "cislo", "png") | ||||
| 
 | ||||
| 		# seznam [(url obrázku, číslo)] | ||||
| 		urls = [] | ||||
| 
 | ||||
| 		# c je číslo, i je pořadí čísla | ||||
| 		for i, c in enumerate(cisla): | ||||
| 			if not c.pdf: | ||||
| 				continue | ||||
|  | @ -433,7 +435,8 @@ def hlavni_problem(problem): | |||
| 
 | ||||
| # vrátí list všech problémů s body v daném čísle, které již nemají nadproblém | ||||
| def hlavni_problemy_cisla(cislo): | ||||
| 	hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all()	# hodnocení, která se vážou k danému číslu | ||||
| 	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] | ||||
|  | @ -454,12 +457,12 @@ def hlavni_problemy_cisla(cislo): | |||
| 	return hlavni_problemy | ||||
| 
 | ||||
| # vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník | ||||
| # POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku | ||||
| def body_resitelu_odjakziva(rocnik, resitele): | ||||
| 	body_odjakziva = {} | ||||
| 
 | ||||
| 	for r in resitele: | ||||
| 		body_odjakziva[str(r.id)] = 0 | ||||
| # POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku | ||||
| #	# Body za posledních 10 let je dobrá aproximace pro naše potřeby (výsledkovka | ||||
| #	# s aktivními řešiteli) | ||||
| # | ||||
|  | @ -497,38 +500,6 @@ def body_resitelu_za_rocnik(rocnik, aktivni_resitele): | |||
| 				pricti_body(body_za_rocnik, resitel, hodn.body) | ||||
| 	return body_za_rocnik | ||||
| 
 | ||||
| #def body_resitele_odjakziva(resitel): | ||||
| #	body = 0 | ||||
| #	resitelova_hodnoceni = Hodnoceni.objects.select_related('body').all().filter(reseni_resitele=resitel) | ||||
| #	# TODO: v radku nahore chceme _in nebo _contains | ||||
| #	for hodnoceni in resitelova_hodnoceni: | ||||
| #		body = body + hodnoceni.body | ||||
| #	return body | ||||
| 
 | ||||
| # spočítá součet všech bodů řešitele za dané číslo | ||||
| #def body_resitele_v_cisle(resitel, cislo): | ||||
| #	hlavni_problemy = hlavni_problemy_cisla(cislo) | ||||
| #	body_resitele = 0 | ||||
| #	for h in hlavni_problemy: | ||||
| #		body_resitele = body_resitele + body_resitele_problemu_v_cisle(h, resitel, cislo) | ||||
| #	# TODO: je rozdíl mezi odevzdanou úlohou za 0 a tím, když řešitel nic neodevzdal | ||||
| #	# řešit přes kontrolu velikosti množiny řešení daného problému do daného čísla? | ||||
| #	# Tady to ale nevadí, tady se počítá součet za číslo. | ||||
| #	return body_resitele | ||||
| 
 | ||||
| # spočítá součet všech bodů řešitele za daný rok (nebo jen do daného čísla včetně) | ||||
| #def body_resitele_v_rocniku(resitel, rocnik, do_cisla=None): | ||||
| #	# pokud do_cisla=None, tak do posledního čísla v ročníku | ||||
| #	# do_cisla je objekt Cislo | ||||
| #	cisla = rocnik.cisla.all() # funkce vrátí pole objektů | ||||
| #	# Cislo už lexikograficky setřízené, viz models | ||||
| #	body = 0 | ||||
| #	for cislo in cisla: | ||||
| #		if cislo.poradi == do_cisla.poradi: break | ||||
| #		# druhá část zaručuje, že máme výsledky do daného čísla včetně | ||||
| #		body = body + body_resitele_v_cisle(resitel, cislo) | ||||
| #	return body | ||||
| 
 | ||||
| # TODO: předělat na nový model | ||||
| #def vysledkovka_rocniku(rocnik, jen_verejne=True): | ||||
| #	"""Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve | ||||
|  | @ -662,6 +633,120 @@ def pricti_body(slovnik, resitel, body): | |||
| 	 | ||||
| 	slovnik[str(resitel.id)] += body | ||||
| 
 | ||||
| def secti_body_za_rocnik(cislo, aktivni_resitele): | ||||
| 	# spočítáme všem řešitelům jejich body za ročník | ||||
| 	resitel_rocnikbody_slov = body_resitelu_za_rocnik(cislo.rocnik, aktivni_resitele) | ||||
| 	# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně | ||||
| 	resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), | ||||
| 					key = lambda x: x[1], reverse = True) | ||||
| 	return resitel_rocnikbody_sezn | ||||
| 
 | ||||
| # spočítá u řešitelů body za číslo a za jednotlivé hlavní problémy (témata) | ||||
| def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy): | ||||
| 	# 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ů) | ||||
| 	hlavni_problemy_slovnik = {} | ||||
| 	for hp in hlavni_problemy: | ||||
| 		hlavni_problemy_slovnik[str(hp.id)] = {} | ||||
| 
 | ||||
| 	# zakládání prázdných záznamů pro řešitele | ||||
| 	cislobody = {} | ||||
| 	for ar in aktivni_resitele: | ||||
| 		# řešitele převedeme na řetězec pomocí unikátního id | ||||
| 		cislobody[str(ar.id)] = "" | ||||
| 		for hp in hlavni_problemy: | ||||
| 			slovnik = hlavni_problemy_slovnik[str(hp.id)] | ||||
| 			slovnik[str(ar.id)] = "" | ||||
| 	 | ||||
| 	# vezmeme všechna řešení s body do daného čísla | ||||
| 	reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'resitele',  | ||||
| 				'hodnoceni_set').filter(hodnoceni__cislo_body=cislo) | ||||
| 	 | ||||
| 	# 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: | ||||
| 		 | ||||
| 		# řešení může řešit více problémů | ||||
| 		for prob in list(reseni.problem.all()): | ||||
| 			nadproblem = hlavni_problem(prob) | ||||
| 			nadproblem_slovnik = hlavni_problemy_slovnik[str(nadproblem.id)] | ||||
| 			 | ||||
| 			# a mít více hodnocení | ||||
| 			for hodn in list(reseni.hodnoceni_set.all()): | ||||
| 				body = hodn.body	 | ||||
| 			 | ||||
| 				# a mít více řešitelů | ||||
| 				for resitel in list(reseni.resitele.all()): | ||||
| 					pricti_body(cislobody, resitel, body) | ||||
| 					pricti_body(nadproblem_slovnik, resitel, body) | ||||
| 	return hlavni_problemy_slovnik, cislobody | ||||
| 		 | ||||
| 
 | ||||
| def spocti_vysledkovku_cisla(cislo, context=None): | ||||
| 	if context is None: | ||||
| 		context = {} | ||||
| 	 | ||||
| 	hlavni_problemy = hlavni_problemy_cisla(cislo) | ||||
| 	## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele | ||||
| 	## 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 | ||||
| 	aktivni_resitele = list(Resitel.objects.filter( | ||||
| 			rok_maturity__gte=cislo.rocnik.druhy_rok())) | ||||
| 			# TODO: zkusit hodnoceni__rocnik... | ||||
| 			#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) | ||||
| 
 | ||||
| 	# získáme body za číslo | ||||
| 	hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) | ||||
| 
 | ||||
| 	# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně | ||||
| 	resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo, aktivni_resitele) | ||||
| 
 | ||||
| 	# získáme body odjakživa | ||||
| 	resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik.druhy_rok(),  | ||||
| 								aktivni_resitele) | ||||
| 
 | ||||
| 	# řešitelé setřídění podle bodů za číslo sestupně | ||||
| 	setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] | ||||
| 	setrizeni_resitele = [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] | ||||
| 	poradi = sloupec_s_poradim(setrizeni_resitele_body) | ||||
| 
 | ||||
| 	# vytvoříme jednotlivé sloupce výsledkovky | ||||
| 	radky_vysledkovky = [] | ||||
| 	i = 0 | ||||
| 	for ar_id in setrizeni_resitele_id: | ||||
| 		# získáme seznam bodů za problémy pro daného řešitele | ||||
| 		problemy = [] 		 | ||||
| 		for hp in hlavni_problemy: | ||||
| 			problemy.append(hlavni_problemy_slovnik[str(hp.id)][ar_id]) | ||||
| 		# vytáhneme informace pro daného řešitele | ||||
| 		radek = RadekVysledkovky( | ||||
| 			poradi[i], # pořadí | ||||
| 			Resitel.objects.get(id=ar_id), # řešitel (z id) | ||||
| 			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) | ||||
| 			resitel_odjakzivabody_slov[ar_id]) # body odjakživa | ||||
| 		print("{}: body za problémy - {}, číslobody - {}, ročníkbody - {}, odjakživabody - {}".format(radek.resitel,  | ||||
| 			radek.body_problemy_sezn, radek.body_cislo, radek.body_rocnik, radek.body_celkem_odjakziva)) | ||||
| 		radky_vysledkovky.append(radek) | ||||
| 		print("Přikládám {}-tý řádek.".format(i)) | ||||
| 		i += 1 | ||||
| 
 | ||||
| 	print("Následuje předávání do kontextu.") | ||||
| 	# vytahané informace předáváme do kontextu | ||||
| 	context['cislo'] = cislo | ||||
| 	context['radky_vysledkovky'] = radky_vysledkovky | ||||
| 	context['problemy'] = hlavni_problemy | ||||
| 	#context['v_cisle_zadane'] = TODO | ||||
| 	#context['resene_problemy'] = resene_problemy | ||||
| 	print("Předávám kontext.") | ||||
| 	return context | ||||
| 
 | ||||
| class CisloView(generic.DetailView): | ||||
| 	model = Cislo | ||||
| 	template_name = 'seminar/archiv/cislo.html' | ||||
|  | @ -685,101 +770,8 @@ class CisloView(generic.DetailView): | |||
| 		context = super(CisloView, self).get_context_data(**kwargs) | ||||
| 
 | ||||
| 		cislo = context['cislo'] | ||||
| 		hlavni_problemy = hlavni_problemy_cisla(cislo) | ||||
| 		# 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ů) | ||||
| 		hlavni_problemy_slovnik = {} | ||||
| 		for hp in hlavni_problemy: | ||||
| 			hlavni_problemy_slovnik[str(hp.id)] = {} | ||||
| 
 | ||||
| 		## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele | ||||
| 		## 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 | ||||
| 		aktivni_resitele = list(Resitel.objects.filter( | ||||
| 				rok_maturity__gte=cislo.rocnik.druhy_rok())) | ||||
| 				# TODO: zkusit hodnoceni__rocnik... | ||||
| 				#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) | ||||
| 		# zakládání prázdných záznamů pro řešitele | ||||
| 		cislobody = {} | ||||
| 		for ar in aktivni_resitele: | ||||
| 			# řešitele převedeme na řetězec pomocí unikátního id | ||||
| 			cislobody[str(ar.id)] = "" | ||||
| 			for hp in hlavni_problemy: | ||||
| 				slovnik = hlavni_problemy_slovnik[str(hp.id)] | ||||
| 				slovnik[str(ar.id)] = "" | ||||
| 		 | ||||
| 		# vezmeme všechna řešení s body do daného čísla | ||||
| 		reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'resitele', 'hodnoceni_set').filter(hodnoceni__cislo_body=cislo) | ||||
| 		 | ||||
| 		# 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: | ||||
| 			 | ||||
| 			# řešení může řešit více problémů | ||||
| 			for prob in list(reseni.problem.all()): | ||||
| 				nadproblem = hlavni_problem(prob) | ||||
| 				nadproblem_slovnik = hlavni_problemy_slovnik[str(nadproblem.id)] | ||||
| 				 | ||||
| 				# a více hodnocení | ||||
| 				for hodn in list(reseni.hodnoceni_set.all()): | ||||
| 					body = hodn.body	 | ||||
| 					 | ||||
| 					# a více řešitelů | ||||
| 					for resitel in list(reseni.resitele.all()): | ||||
| 						pricti_body(cislobody, resitel, body) | ||||
| 						pricti_body(nadproblem_slovnik, resitel, body) | ||||
| 
 | ||||
| 		# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně | ||||
| 		resitel_rocnikbody_slov = body_resitelu_za_rocnik(cislo.rocnik, aktivni_resitele) | ||||
| 		resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), | ||||
| 						key = lambda x: x[1], reverse = True) | ||||
| 	 | ||||
| 		# získáme body odjakživa | ||||
| 		resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik.druhy_rok(),  | ||||
| 									aktivni_resitele) | ||||
| 	 | ||||
| 		# řešitelé setřídění podle bodů za číslo sestupně | ||||
| 		setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] | ||||
| 		setrizeni_resitele = [Resitel.objects.get(id=i) for i in setrizeni_resitele_id] | ||||
| 				 | ||||
| 		# vytvoříme jednotlivé sloupce výsledkovky | ||||
| 		radky_vysledkovky = [] | ||||
| 		odjakziva_body = [] | ||||
| 		rocnik_body = [] | ||||
| 		cislo_body = [] | ||||
| 		hlavni_problemy_body = [] | ||||
| 		for ar_id in setrizeni_resitele_id: | ||||
| 			# vytáhneme ze slovníků body pro daného řešitele | ||||
| 			odjakziva_body.append(resitel_odjakzivabody_slov[ar_id]) | ||||
| 			rocnik_body.append(resitel_rocnikbody_slov[ar_id]) | ||||
| 			cislo_body.append(cislobody[ar_id]) | ||||
| 			problemy = [] | ||||
| 			for hp in hlavni_problemy: | ||||
| 				problemy.append(hlavni_problemy_slovnik[str(hp.id)][ar_id]) | ||||
| 			hlavni_problemy_body.append(problemy) | ||||
| 			print("{}: body za problémy - {}, číslobody - {}, ročníkbody - {}, odjakživabody - ".format(ar_id, problemy, cislobody[ar_id], resitel_rocnikbody_slov[ar_id])) | ||||
| 		# pořadí určíme pomocí funkce, které dáme celkové body za ročník vzestupně | ||||
| 		poradi = sloupec_s_poradim(rocnik_body) | ||||
| 
 | ||||
| 		radky_vysledkovky = [] | ||||
| 		for i in range(0, len(setrizeni_resitele_id)): | ||||
| 			radek = RadekVysledkovky(poradi[i], setrizeni_resitele[i], | ||||
| 				hlavni_problemy_body[i], cislo_body[i], rocnik_body[i], | ||||
| 				odjakziva_body[i]) | ||||
| 			radky_vysledkovky.append(radek) | ||||
| 			print("Přikládám {}-tý řádek.".format(i)) | ||||
| 
 | ||||
| 		print("Následuje předávání do kontextu.") | ||||
| 		# vytahané informace předáváme do kontextu | ||||
| 		context['cislo'] = cislo | ||||
| 		context['radky_vysledkovky'] = radky_vysledkovky | ||||
| 		context['problemy'] = hlavni_problemy | ||||
| #		context['v_cisle_zadane'] = TODO | ||||
| #		context['resene_problemy'] = resene_problemy | ||||
| 		print("Předávám kontext.") | ||||
| 		return context | ||||
| 		# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky | ||||
| 		return spocti_vysledkovku_cisla(cislo, context) | ||||
| 
 | ||||
| #		problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku())) | ||||
| #		#setridi problemy podle typu a poradi zadani | ||||
|  | @ -1006,7 +998,7 @@ def soustredeniUcastniciExportView(request,soustredeni): | |||
| class ClankyResitelView(generic.ListView): | ||||
| 	model = Problem | ||||
| 	template_name = 'seminar/clanky/resitelske_clanky.html' | ||||
| 	queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY, resitelsky=True).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik', 'kod') | ||||
| 	queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod') | ||||
| 
 | ||||
| # FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit | ||||
| #class ClankyOrganizatorView(generic.ListView)<F12>: | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Anet
						Anet