Merge branch 'data_migrations' into treenode_editor
This commit is contained in:
		
						commit
						9ba5c65326
					
				
					 18 changed files with 631 additions and 494 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								Schema_new.dia
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Schema_new.dia
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -14,8 +14,31 @@ div.container { | ||||||
| 	margin: auto; | 	margin: auto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .org-logged-in div.container { | ||||||
|  | 	margin-top: 20px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| div.login-bar { | div.login-bar { | ||||||
| 	background: #6a0043; | 	background: #6a0043; | ||||||
|  | 	color: #f9d59e; | ||||||
|  | 	width: 100%; | ||||||
|  | 
 | ||||||
|  | 	position: fixed; | ||||||
|  | 	margin-top: -20px; | ||||||
|  | 	min-height: 20px; | ||||||
|  | 	z-index: 20; | ||||||
|  | 
 | ||||||
|  | 	padding-left: 5px; | ||||||
|  | 	padding-right: 5px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.login-bar div { | ||||||
|  | 	display: inline; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | a.login-ref-admin { | ||||||
|  | 	display: inline; | ||||||
|  | 	color: #fffbf6; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* odkazy a nadpisy */ | /* odkazy a nadpisy */ | ||||||
|  | @ -28,7 +51,10 @@ a:focus, a:hover, a:active { | ||||||
| 	color: #e84e10; | 	color: #e84e10; | ||||||
| 	text-decoration: none; | 	text-decoration: none; | ||||||
| } | } | ||||||
| a:focus a:hover | 
 | ||||||
|  | img { | ||||||
|  | 	filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4)); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| h1 {	/*todo: odlišit 1 a 2 */ | h1 {	/*todo: odlišit 1 a 2 */ | ||||||
| 	font-size: 200%; | 	font-size: 200%; | ||||||
|  | @ -74,16 +100,16 @@ h6 { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .org-logged-in .mam-text-plugin { | .org-logged-in .mam-text-plugin { | ||||||
|   border: dashed 1px #f77; |   border: dashed 1px #6a0043; | ||||||
|   padding: 5px; |   padding: 5px; | ||||||
|   margin: -5px; |   margin: -5px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .mam-org-only { | .mam-org-only { | ||||||
|   background: #fff0d7; |   background: #eee4ec; | ||||||
|   padding: 10px; |   padding: 10px; | ||||||
|   margin: 10px -10px; |   margin: 10px -10px; | ||||||
|   border: orange 2px dashed; |   border: #6a0043 2px dashed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .mam-org-only .mam-org-only { | .mam-org-only .mam-org-only { | ||||||
|  | @ -123,6 +149,8 @@ h1 { | ||||||
| 	margin-top: 0px; | 	margin-top: 0px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Comments */ | /* Comments */ | ||||||
| 
 | 
 | ||||||
| #id_comment { | #id_comment { | ||||||
|  | @ -191,7 +219,7 @@ vikendovka | ||||||
| #header.NOCsoustredeni { background-image: url("../images/header/vylet.jpg");} | #header.NOCsoustredeni { background-image: url("../images/header/vylet.jpg");} | ||||||
| #header.NOCzadani { background-image: url("../images/header/stiny.jpg");} | #header.NOCzadani { background-image: url("../images/header/stiny.jpg");} | ||||||
| #header.NOCclanky { background-image: url("../images/header/ohen.jpg");} | #header.NOCclanky { background-image: url("../images/header/ohen.jpg");} | ||||||
| #header.NOCarchiv { background-image: url("../images/header/vikendovka.jpg");} | #header.NOCarchiv { background-image: url("../images/header/stiny.jpg");} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #header img.logo { | #header img.logo { | ||||||
|  | @ -407,6 +435,10 @@ ul.submenu { | ||||||
| /* malý tablet, mobil */ | /* malý tablet, mobil */ | ||||||
| @media (max-width: 650px) { | @media (max-width: 650px) { | ||||||
| 
 | 
 | ||||||
|  |   #hide-if-small.login-bar-flatpage { | ||||||
|  | 		display: none; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	#title { | 	#title { | ||||||
| 		display: none; | 		display: none; | ||||||
| 	} | 	} | ||||||
|  | @ -558,13 +590,21 @@ div.seznam_orgu { | ||||||
| 	text-align: center; | 	text-align: center; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.org_pole { | div.org_pole, div.rocnik_pole { | ||||||
| 	display: inline-block; | 	display: inline-block; | ||||||
| 	width: 30%; | 	width: 30%; | ||||||
| 	min-width: 300px; | 	min-width: 300px; | ||||||
| 	text-align: center; | 	text-align: center; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | div.cislo_pole { | ||||||
|  | 	display: inline-block; | ||||||
|  | 	width: 15%; | ||||||
|  | 	min-width: 165px; | ||||||
|  | 	text-align: center; | ||||||
|  | 	padding: 10px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| div.seznam_orgu h3 { | div.seznam_orgu h3 { | ||||||
| 	text-align: center; | 	text-align: center; | ||||||
| 	margin-top: 10px; | 	margin-top: 10px; | ||||||
|  | @ -576,16 +616,29 @@ div.org_email { | ||||||
| 	font-weight: bold; | 	font-weight: bold; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*otáčecí karty organizátorů*/ | /*otáčecí karty (orgové, archiv) */ | ||||||
| 
 | 
 | ||||||
| .flip-card { | .flip-card { | ||||||
|  width: 200px; |  | ||||||
|  height: 250px; |  | ||||||
|  perspective: 1000px; /* Remove this if you don't want the 3D effect */ |  perspective: 1000px; /* Remove this if you don't want the 3D effect */ | ||||||
|  margin-left: auto; |  margin-left: auto; | ||||||
|  margin-right: auto; |  margin-right: auto; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #organizatori.flip-card { | ||||||
|  | 	width: 200px; | ||||||
|  | 	height: 250px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #archiv.flip-card { | ||||||
|  | 	width: 210px; | ||||||
|  | 	height: 298px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #archiv-rocnik.flip-card { | ||||||
|  | 	width: 144px; | ||||||
|  | 	height: 205px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* This container is needed to position the front and back side */ | /* This container is needed to position the front and back side */ | ||||||
| .flip-card-inner { | .flip-card-inner { | ||||||
|  position: relative; |  position: relative; | ||||||
|  | @ -614,35 +667,59 @@ div.org_email { | ||||||
|  background-color: #bbb; |  background-color: #bbb; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| div.foto_org img { | div.flip-card-foto img { | ||||||
| 	width: 100%; | 	width: 100%; | ||||||
| 	height: 100%; | 	height: 100%; | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Style the back side */ | /* Style the back side */ | ||||||
| .flip-card-back { | .flip-card-back { | ||||||
|  /*background-color: #e84e10; |  | ||||||
|  color: #fffbf6; |  | ||||||
|  background-color: #fdedd5;*/ |  | ||||||
|  background-color: #f9d59e; |  background-color: #f9d59e; | ||||||
|  color: black;/**/ |  color: black; | ||||||
|  transform: rotateY(180deg); |  transform: rotateY(180deg); | ||||||
|  padding: 10px; |  padding: 10px; | ||||||
|  padding-top: 20px; |  padding-top: 20px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* graf na úvodní stránce */ | /* karty archiv */ | ||||||
| 
 | 
 | ||||||
| a span.popup { | div.popis_rocniku { | ||||||
| 	position: absolute; | 	text-align: left; | ||||||
| 	visibility: hidden; | 	font-weight: bold; | ||||||
|  | 	margin: 20px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| a span.popup:hover { | 
 | ||||||
| 	visibility:visible; | div.popis_rocniku a, div.cislo_odkazy a { | ||||||
| 	top:37px; left:37px; | 	font-weight: bold; | ||||||
|  |   color: black; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | div.popis_rocniku a:hover, | ||||||
|  | div.cislo_odkazy a:hover { | ||||||
|  | 	color: #6f2509; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.cislo_odkazy ul { | ||||||
|  | 		margin: 0px; | ||||||
|  | 		padding: 0px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* archiv ročník | ||||||
|  | div.cisla-v-rocniku { | ||||||
|  | 		font-weight: bold; | ||||||
|  | 		color:  #6f2509; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.cislo-v-rocniku-blok { | ||||||
|  | 	display: inline-block; | ||||||
|  | 	width: 150px; | ||||||
|  | 	height: 220px; | ||||||
|  | 		text-align: center; | ||||||
|  | }*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* galerie */ | /* galerie */ | ||||||
| 
 | 
 | ||||||
| /* velká fotka */ | /* velká fotka */ | ||||||
|  |  | ||||||
|  | @ -37,21 +37,21 @@ | ||||||
|   </head> |   </head> | ||||||
|   <body class='{% if user.is_staff %}org-logged-in{% endif %}'> |   <body class='{% if user.is_staff %}org-logged-in{% endif %}'> | ||||||
| 
 | 
 | ||||||
|    <div class="container"> |  | ||||||
| 
 |  | ||||||
|     {% if user.is_staff %} |     {% if user.is_staff %} | ||||||
|       <div class="login-bar" > |       <div class="login-bar" > | ||||||
|         {% if view.object %} |         {% if view.object %} | ||||||
|           Objekt {{ view.object }}: {{ view.object }} |           Objekt {{ view.object }}: {{ view.object }} | ||||||
| 	{% if view.object.admin_url %}<a href='{{ view.object.admin_url }}'>[admin]</a>{% endif %} |           {% if view.object.admin_url %}<a class="login-ref-admin" href='{{ view.object.admin_url }}'>[admin]</a>{% endif %} | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if flatpage %} |         {% if flatpage %} | ||||||
| 	Stránka <tt>{{ flatpage.url }}</tt>  ({{ flatpage.title }}) |           <div class="login-bar-flatpage" id="hide-if-small"> Stránka <tt>{{ flatpage.url }}</tt>  ({{ flatpage.title }})</div> | ||||||
| 	<a href='{% url 'admin:flatpages_flatpage_change' flatpage.id %}'>[admin]</a> |           <a class="login-ref-admin" href='{% url 'admin:flatpages_flatpage_change' flatpage.id %}'>[admin]</a> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|  |         <a class="login-ref-admin" href='/admin'>[admin mainpage]</a> | ||||||
|       </div> |       </div> | ||||||
|     {% endif %} |     {% endif %} | ||||||
| 
 | 
 | ||||||
|  |    <div class="container"> | ||||||
| 
 | 
 | ||||||
| 	  <div class='row'> | 	  <div class='row'> | ||||||
| 		<div class='col-md-12'> | 		<div class='col-md-12'> | ||||||
|  |  | ||||||
|  | @ -35,6 +35,7 @@ class ProblemAdmin(PolymorphicParentModelAdmin): | ||||||
| 		m.Tema, | 		m.Tema, | ||||||
| 		m.Clanek, | 		m.Clanek, | ||||||
| 		m.Uloha, | 		m.Uloha, | ||||||
|  | 		m.Konfera, | ||||||
| 		] | 		] | ||||||
| 
 | 
 | ||||||
| @admin.register(m.Tema) | @admin.register(m.Tema) | ||||||
|  | @ -52,6 +53,11 @@ class UlohaAdmin(PolymorphicChildModelAdmin): | ||||||
| 	base_model = m.Uloha | 	base_model = m.Uloha | ||||||
| 	show_in_index = True | 	show_in_index = True | ||||||
| 
 | 
 | ||||||
|  | @admin.register(m.Konfera) | ||||||
|  | class KonferaAdmin(PolymorphicChildModelAdmin): | ||||||
|  | 	base_model = m.Konfera | ||||||
|  | 	show_in_index = True | ||||||
|  | 
 | ||||||
| class TextAdminInline(admin.TabularInline): | class TextAdminInline(admin.TabularInline): | ||||||
| 	model = m.Text | 	model = m.Text | ||||||
| 	exclude = ['text_zkraceny_set','text_zkraceny'] | 	exclude = ['text_zkraceny_set','text_zkraceny'] | ||||||
|  | @ -82,7 +88,6 @@ class ReseniAdmin(ReverseModelAdmin): | ||||||
| 
 | 
 | ||||||
| admin.site.register(m.Hodnoceni) | admin.site.register(m.Hodnoceni) | ||||||
| admin.site.register(m.Pohadka) | admin.site.register(m.Pohadka) | ||||||
| admin.site.register(m.Konfera) |  | ||||||
| admin.site.register(m.Obrazek) | admin.site.register(m.Obrazek) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -97,8 +102,6 @@ class TreeNodeAdmin(PolymorphicParentModelAdmin): | ||||||
| 		m.CisloNode, | 		m.CisloNode, | ||||||
| 		m.MezicisloNode, | 		m.MezicisloNode, | ||||||
| 		m.TemaVCisleNode, | 		m.TemaVCisleNode, | ||||||
| 		m.KonferaNode, |  | ||||||
| 		m.ClanekNode, |  | ||||||
| 		m.UlohaZadaniNode, | 		m.UlohaZadaniNode, | ||||||
| 		m.PohadkaNode, | 		m.PohadkaNode, | ||||||
| 		m.UlohaVzorakNode, | 		m.UlohaVzorakNode, | ||||||
|  | @ -136,16 +139,6 @@ class TemaVCisleNodeAdmin(PolymorphicChildModelAdmin): | ||||||
| 	base_model = m.TemaVCisleNode | 	base_model = m.TemaVCisleNode | ||||||
| 	show_in_index = True | 	show_in_index = True | ||||||
| 
 | 
 | ||||||
| @admin.register(m.KonferaNode) |  | ||||||
| class KonferaNodeAdmin(PolymorphicChildModelAdmin): |  | ||||||
| 	base_model = m.KonferaNode |  | ||||||
| 	show_in_index = True |  | ||||||
| 
 |  | ||||||
| @admin.register(m.ClanekNode) |  | ||||||
| class ClanekNodeAdmin(PolymorphicChildModelAdmin): |  | ||||||
| 	base_model = m.ClanekNode |  | ||||||
| 	show_in_index = True |  | ||||||
| 
 |  | ||||||
| @admin.register(m.UlohaZadaniNode) | @admin.register(m.UlohaZadaniNode) | ||||||
| class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin): | class UlohaZadaniNodeAdmin(PolymorphicChildModelAdmin): | ||||||
| 	base_model = m.UlohaZadaniNode | 	base_model = m.UlohaZadaniNode | ||||||
|  |  | ||||||
							
								
								
									
										121
									
								
								seminar/migrations/0080_zruseni_claneknode_a_konferanode.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								seminar/migrations/0080_zruseni_claneknode_a_konferanode.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,121 @@ | ||||||
|  | # Generated by Django 2.2.12 on 2020-04-01 20:54 | ||||||
|  | # Fixed by Pavel, 2020-01-04 20:56 UTC | ||||||
|  | # This is quite possibly a bug in Django. | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  | 
 | ||||||
|  | def vyrob_dummy_problemy(apps, schema_editor): | ||||||
|  | 	Problem = apps.get_model('seminar', 'Problem') | ||||||
|  | 	Konfera = apps.get_model('seminar', 'Konfera') | ||||||
|  | 	for k in Konfera.objects.all(): | ||||||
|  | 		pr = Problem.objects.create(nazev=k.nazev, | ||||||
|  | 			garant=k.organizator) | ||||||
|  | 		pr.save() | ||||||
|  | 		k.problem_ptr = pr | ||||||
|  | 		k.save() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('contenttypes', '0002_remove_content_type_name'), | ||||||
|  |         ('seminar', '0079_clanek_resitelsky'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.DeleteModel( | ||||||
|  |             name='Konfery_Ucastnici', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='ucastnici', | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='OrgTextNode', | ||||||
|  |             fields=[ | ||||||
|  |                 ('treenode_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.TreeNode')), | ||||||
|  |                 ('org_verejny', models.BooleanField(default=True, help_text='Pokud ano, bude org pod článkem podepsaný', verbose_name='Org je veřejný?')), | ||||||
|  |                 ('organizator', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='seminar.Organizator', verbose_name='Organizátor')), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 'verbose_name': 'Organizátorský článek (Node)', | ||||||
|  |                 'verbose_name_plural': 'Organizátorské články (Node)', | ||||||
|  |                 'db_table': 'seminar_nodes_orgtextnode', | ||||||
|  |             }, | ||||||
|  |             bases=('seminar.treenode',), | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='id', | ||||||
|  |         ), | ||||||
|  |         migrations.RenameModel( | ||||||
|  |             old_name='OtisteneReseniNode', | ||||||
|  |             new_name='ReseniNode', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='clanek', | ||||||
|  |             name='cislo', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='clanek', | ||||||
|  |             name='resitelsky', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='reseni', | ||||||
|  |             name='text_zkraceny', | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='problem_ptr', | ||||||
|  |             field=models.OneToOneField(auto_created=True, null=False, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='seminar.Problem'), | ||||||
|  |             preserve_default=False, | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='nazev', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='organizator', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='poznamka', | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='reseni', | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='reseni', | ||||||
|  |             name='text_cely', | ||||||
|  |             field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='reseni_cely_set', to='seminar.ReseniNode', verbose_name='Plná verze textu řešení'), | ||||||
|  |         ), | ||||||
|  |         migrations.DeleteModel( | ||||||
|  |             name='ClanekNode', | ||||||
|  |         ), | ||||||
|  |         migrations.DeleteModel( | ||||||
|  |             name='KonferaNode', | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='Konfery_Ucastnici', | ||||||
|  |             fields=[ | ||||||
|  |                 ('id', models.AutoField(primary_key=True, serialize=False)), | ||||||
|  |                 ('poznamka', models.TextField(blank=True, help_text='Neveřejná poznámka k účasti (plain text)', verbose_name='neveřejná poznámka')), | ||||||
|  |                 ('konfera', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='seminar.Konfera', verbose_name='konfera')), | ||||||
|  |                 ('resitel', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='seminar.Resitel', verbose_name='řešitel')), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 'verbose_name': 'Účast na konfeře', | ||||||
|  |                 'verbose_name_plural': 'Účasti na konfeře', | ||||||
|  |                 'db_table': 'seminar_konfery_ucastnici', | ||||||
|  |                 'ordering': ['konfera', 'resitel'], | ||||||
|  |             }, | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='konfera', | ||||||
|  |             name='ucastnici', | ||||||
|  |             field=models.ManyToManyField(help_text='Seznam účastníků konfery', through='seminar.Konfery_Ucastnici', to='seminar.Resitel', verbose_name='účastníci konfery'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										24
									
								
								seminar/migrations/0081_auto_20200408_2221.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								seminar/migrations/0081_auto_20200408_2221.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | # Generated by Django 2.2.9 on 2020-04-08 20:21 | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import seminar.models | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('seminar', '0080_zruseni_claneknode_a_konferanode'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='cislo', | ||||||
|  |             name='titulka_nahled', | ||||||
|  |             field=models.ImageField(blank=True, help_text='Obrázek titulní strany, generuje se automaticky', null=True, upload_to='', verbose_name='Obrázek titulní strany'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='cislo', | ||||||
|  |             name='pdf', | ||||||
|  |             field=models.FileField(blank=True, help_text='PDF čísla, které si mohou řešitelé stáhnout', null=True, upload_to=seminar.models.cislo_pdf_filename, verbose_name='pdf'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
|  | @ -728,6 +728,9 @@ class Problem(SeminarModelBase,PolymorphicModel): | ||||||
| 		return '<Není zadaný>' | 		return '<Není zadaný>' | ||||||
| 
 | 
 | ||||||
| 	def verejne(self): | 	def verejne(self): | ||||||
|  | 		# FIXME: Tohle se liší podle typu problému, má se udělat polymorfně. | ||||||
|  | 		# Zatím je tu jen dummy fail-safe default: nic není veřejné. | ||||||
|  | 		return False | ||||||
| 		return (self.cislo_zadani and self.cislo_zadani.verejne()) | 		return (self.cislo_zadani and self.cislo_zadani.verejne()) | ||||||
| 	verejne.boolean = True | 	verejne.boolean = True | ||||||
| 
 | 
 | ||||||
|  | @ -735,10 +738,7 @@ class Problem(SeminarModelBase,PolymorphicModel): | ||||||
| 		return reverse('seminar_problem', kwargs={'pk': self.id}) | 		return reverse('seminar_problem', kwargs={'pk': self.id}) | ||||||
| 
 | 
 | ||||||
| 	def admin_url(self): | 	def admin_url(self): | ||||||
| 		if self.stav == Problem.STAV_ZADANY: | 			return reverse('admin:seminar_problem_change', args=(self.id, )) | ||||||
| 			return reverse('admin:seminar_problemzadany_change', args=(self.id, )) |  | ||||||
| 		else: |  | ||||||
| 			return reverse('admin:seminar_problemnavrh_change', args=(self.id, )) |  | ||||||
| 
 | 
 | ||||||
| # FIXME - k úloze | # FIXME - k úloze | ||||||
| 	def body_v_zavorce(self): | 	def body_v_zavorce(self): | ||||||
|  | @ -792,14 +792,6 @@ class Clanek(Problem): | ||||||
| 		verbose_name = 'Článek' | 		verbose_name = 'Článek' | ||||||
| 		verbose_name_plural = 'Články' | 		verbose_name_plural = 'Články' | ||||||
| 	 | 	 | ||||||
| 	cislo = models.ForeignKey(Cislo, verbose_name='číslo', blank=True, null=True, |  | ||||||
| 		on_delete=models.PROTECT) |  | ||||||
| 
 |  | ||||||
| 	resitelsky = models.BooleanField('Jde o řešitelský článek?', default=True) |  | ||||||
| 
 |  | ||||||
| 	# má OneToOneField s: |  | ||||||
| 	# ClanekNode |  | ||||||
| 
 |  | ||||||
| 	def kod_v_rocniku(self): | 	def kod_v_rocniku(self): | ||||||
| 		if self.stav == 'zadany': | 		if self.stav == 'zadany': | ||||||
| # Nemělo by být potřeba | # Nemělo by být potřeba | ||||||
|  | @ -808,15 +800,6 @@ class Clanek(Problem): | ||||||
| 			return "c{}".format(self.kod) | 			return "c{}".format(self.kod) | ||||||
| 		return '<Není zadaný>' | 		return '<Není zadaný>' | ||||||
| 
 | 
 | ||||||
| 	def save(self, *args, **kwargs): |  | ||||||
| 		super().save(*args, **kwargs) |  | ||||||
| 		# *Node.save() aktualizuje název *Nodu. |  | ||||||
| 		try: |  | ||||||
| 			self.claneknode.save() |  | ||||||
| 		except ObjectDoesNotExist: |  | ||||||
| 			# Neexistující *Node nemá smysl aktualizovat. |  | ||||||
| 			pass |  | ||||||
| 
 |  | ||||||
| class Text(SeminarModelBase): | class Text(SeminarModelBase): | ||||||
| 	class Meta: | 	class Meta: | ||||||
| 		db_table = 'seminar_texty' | 		db_table = 'seminar_texty' | ||||||
|  | @ -926,12 +909,9 @@ class Reseni(SeminarModelBase): | ||||||
| 	forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, | 	forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False, | ||||||
| 		 default=FORMA_EMAIL) | 		 default=FORMA_EMAIL) | ||||||
| 
 | 
 | ||||||
| 	text_cely = models.OneToOneField(Text, verbose_name='Plná verze textu řešení',  | 	text_cely = models.OneToOneField('ReseniNode', verbose_name='Plná verze textu řešení',  | ||||||
| 		blank=True, null=True, related_name="reseni_cely_set", | 		blank=True, null=True, related_name="reseni_cely_set", | ||||||
| 		on_delete=models.SET_NULL) | 		on_delete=models.PROTECT) | ||||||
| 
 |  | ||||||
| 	text_zkraceny = models.ManyToManyField(Text, verbose_name='zkrácené verze řešení', |  | ||||||
| 		help_text='Seznam úryvků z řešení',related_name="reseni_zkraceny_set") |  | ||||||
| 
 | 
 | ||||||
| 	poznamka = models.TextField('neveřejná poznámka', blank=True, | 	poznamka = models.TextField('neveřejná poznámka', blank=True, | ||||||
| 		help_text='Neveřejná poznámka k řešení (plain text)') | 		help_text='Neveřejná poznámka k řešení (plain text)') | ||||||
|  | @ -1141,15 +1121,11 @@ class Soustredeni_Organizatori(SeminarModelBase): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @reversion.register(ignore_duplicates=True) | @reversion.register(ignore_duplicates=True) | ||||||
| class Konfera(models.Model): | class Konfera(Problem): | ||||||
| 	class Meta: | 	class Meta: | ||||||
| 		db_table = 'seminar_konfera' | 		db_table = 'seminar_konfera' | ||||||
| 		verbose_name = 'Konfera' | 		verbose_name = 'Konfera' | ||||||
| 		verbose_name_plural = 'Konfery' | 		verbose_name_plural = 'Konfery' | ||||||
| 	# Interní ID |  | ||||||
| 	id = models.AutoField(primary_key = True) |  | ||||||
| 
 |  | ||||||
| 	nazev = models.CharField('název konfery', max_length=100, help_text = 'Název konfery') |  | ||||||
| 
 | 
 | ||||||
| 	anotace = models.TextField('anotace', blank=True, | 	anotace = models.TextField('anotace', blank=True, | ||||||
| 		help_text='Popis, o čem bude konfera.') | 		help_text='Popis, o čem bude konfera.') | ||||||
|  | @ -1157,9 +1133,6 @@ class Konfera(models.Model): | ||||||
| 	abstrakt = models.TextField('abstrakt', blank=True, | 	abstrakt = models.TextField('abstrakt', blank=True, | ||||||
| 		help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') | 		help_text='Abstrakt konfery tak, jak byl uveden ve sborníku') | ||||||
| 	 | 	 | ||||||
| 	organizator = models.ForeignKey(Organizator, verbose_name='organizátor', related_name='konfery', |  | ||||||
| 			on_delete = models.SET_NULL, null=True) |  | ||||||
| 
 |  | ||||||
| 	# FIXME: Umíme omezit jen na účastníky daného soustřeďka? | 	# FIXME: Umíme omezit jen na účastníky daného soustřeďka? | ||||||
| 	ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', | 	ucastnici = models.ManyToManyField(Resitel, verbose_name='účastníci konfery', | ||||||
| 		help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') | 		help_text='Seznam účastníků konfery', through='Konfery_Ucastnici') | ||||||
|  | @ -1167,13 +1140,6 @@ class Konfera(models.Model): | ||||||
| 	soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění',  | 	soustredeni = models.ForeignKey(Soustredeni, verbose_name='soustředění',  | ||||||
| 			related_name='konfery', on_delete = models.SET_NULL, null=True) | 			related_name='konfery', on_delete = models.SET_NULL, null=True) | ||||||
| 
 | 
 | ||||||
| 	poznamka = models.TextField('neveřejná poznámka', blank=True, |  | ||||||
| 		help_text='Neveřejná poznámka ke konfeře(plain text)') |  | ||||||
| 	# Jedno reseni se vztahuje nejvyse k jedne konfere |  | ||||||
| 	reseni = models.OneToOneField(Reseni, verbose_name='článek ke konfeře', related_name='konfery', |  | ||||||
| 		help_text='Účastnický přípěvek o konfeře', on_delete = models.SET_NULL,  |  | ||||||
| 		null=True, blank=True) |  | ||||||
| 
 |  | ||||||
| 	TYP_VELETRH = 'veletrh' | 	TYP_VELETRH = 'veletrh' | ||||||
| 	TYP_PREZENTACE = 'prezentace' | 	TYP_PREZENTACE = 'prezentace' | ||||||
| 	TYP_CHOICES = [ | 	TYP_CHOICES = [ | ||||||
|  | @ -1190,21 +1156,9 @@ class Konfera(models.Model): | ||||||
| 			help_text = 'Další materiály ke konfeře zabalené do jednoho souboru',  | 			help_text = 'Další materiály ke konfeře zabalené do jednoho souboru',  | ||||||
| 			upload_to = generate_filename_konfera, blank=True) | 			upload_to = generate_filename_konfera, blank=True) | ||||||
| 
 | 
 | ||||||
| 	# má OneToOneField s: |  | ||||||
| 	# KonferaNode |  | ||||||
| 
 |  | ||||||
| 	def __str__(self): | 	def __str__(self): | ||||||
| 		return "{}: ({})".format(self.nazev, self.soustredeni) | 		return "{}: ({})".format(self.nazev, self.soustredeni) | ||||||
| 
 | 
 | ||||||
| 	def save(self, *args, **kwargs): |  | ||||||
| 		super().save(*args, **kwargs) |  | ||||||
| 		# *Node.save() aktualizuje název *Nodu. |  | ||||||
| 		try: |  | ||||||
| 			self.konferanode.save() |  | ||||||
| 		except ObjectDoesNotExist: |  | ||||||
| 			# Neexistující *Node nemá smysl aktualizovat. |  | ||||||
| 			pass |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| # Vazebna tabulka. Mozna se generuje automaticky. | # Vazebna tabulka. Mozna se generuje automaticky. | ||||||
| @reversion.register(ignore_duplicates=True) | @reversion.register(ignore_duplicates=True) | ||||||
|  | @ -1417,36 +1371,30 @@ class TemaVCisleNode(TreeNode): | ||||||
| 	def getOdkazStr(self): | 	def getOdkazStr(self): | ||||||
| 		return str(self.tema) | 		return str(self.tema) | ||||||
| 
 | 
 | ||||||
| class KonferaNode(TreeNode): | class OrgTextNode(TreeNode): | ||||||
| 	class Meta: | 	class Meta: | ||||||
| 		db_table = 'seminar_nodes_konfera' | 		db_table = 'seminar_nodes_orgtextnode' | ||||||
| 		verbose_name = 'Konfera (Node)' | 		verbose_name = 'Organizátorský článek (Node)' | ||||||
| 		verbose_name_plural = 'Konfery (Node)' | 		verbose_name_plural = 'Organizátorské články (Node)' | ||||||
| 	konfera = models.OneToOneField(Konfera, | 	 | ||||||
| 		on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně | 	organizator = models.ForeignKey(Organizator, | ||||||
| 		verbose_name = "konfera", | 		null=False, | ||||||
| 		null=True, | 		blank=False, | ||||||
| 		blank=False) | 		on_delete=models.DO_NOTHING, | ||||||
|  | 		verbose_name="Organizátor", | ||||||
|  | 		) | ||||||
|  | 	org_verejny = models.BooleanField(default = True, | ||||||
|  | 		verbose_name = "Org je veřejný?", | ||||||
|  | 		help_text = "Pokud ano, bude org pod článkem podepsaný", | ||||||
|  | 		null=False, | ||||||
|  | 		) | ||||||
| 
 | 
 | ||||||
| 	def aktualizuj_nazev(self): | 	def aktualizuj_nazev(self): | ||||||
| 		self.nazev = "KonferaNode: "+str(self.konfera) | 		return f"OrgTextNode začínající následujícim: {self.first_child.nazev}" | ||||||
| 
 | 
 | ||||||
| class ClanekNode(TreeNode): | 	# FIXME!!! | ||||||
| 	class Meta: | 	#def getOdkazStr(self): | ||||||
| 		db_table = 'seminar_nodes_clanek' | 	#	return str(self.clanek) | ||||||
| 		verbose_name = 'Článek (Node)' |  | ||||||
| 		verbose_name_plural = 'Články (Node)' |  | ||||||
| 	clanek = models.OneToOneField(Clanek, |  | ||||||
| 		on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně |  | ||||||
| 		verbose_name = "článek", |  | ||||||
| 		null=True, |  | ||||||
| 		blank=False) |  | ||||||
| 
 |  | ||||||
| 	def aktualizuj_nazev(self): |  | ||||||
| 		self.nazev = "ClanekNode: "+str(self.clanek) |  | ||||||
| 
 |  | ||||||
| 	def getOdkazStr(self): |  | ||||||
| 		return str(self.clanek) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class UlohaZadaniNode(TreeNode): | class UlohaZadaniNode(TreeNode): | ||||||
|  | @ -1527,7 +1475,7 @@ class CastNode(TreeNode): | ||||||
| 	def getOdkazStr(self): | 	def getOdkazStr(self): | ||||||
| 		return str(self.nadpis) | 		return str(self.nadpis) | ||||||
| 
 | 
 | ||||||
| class OtisteneReseniNode(TreeNode): | class ReseniNode(TreeNode): | ||||||
| 	class Meta: | 	class Meta: | ||||||
| 		db_table = 'seminar_nodes_otistene_reseni' | 		db_table = 'seminar_nodes_otistene_reseni' | ||||||
| 		verbose_name = 'Otištěné řešení (Node)' | 		verbose_name = 'Otištěné řešení (Node)' | ||||||
|  |  | ||||||
|  | @ -8,18 +8,56 @@ | ||||||
|     {% endblock %}{% endblock %} |     {% endblock %}{% endblock %} | ||||||
|   </h2> |   </h2> | ||||||
| 
 | 
 | ||||||
|   <div class='nahledy_cisel'> |   <!-- <div class='nahledy_cisel'> | ||||||
|     {% autoescape off %}{{ nahledy }}{% endautoescape %} |     {% autoescape off %}{{ nahledy }}{% endautoescape %} | ||||||
|  |   </div>--> | ||||||
|  | 
 | ||||||
|  |     {% for rocnik, url_png in object_list.items %} | ||||||
|  | 
 | ||||||
|  |     <div class="rocnik_pole"> | ||||||
|  | 
 | ||||||
|  |       <h3> | ||||||
|  |       <a href='{{ rocnik.verejne_url }}'>Ročník {{ rocnik }}</a> | ||||||
|  |       </h3> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       {# karta ročníku - zepředu obrázek prvního čísla, zezadu odkaz na jednotlivá čísla a výsledkovku #} | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card" id="archiv"> | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card-inner"> | ||||||
|  |         <div class="flip-card-front"> | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card-foto"> | ||||||
|  |         <img src="{{ url_png }}" height=200px alt="{{ rocnik }}"> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|  |       </div> | ||||||
|  |        <div class="flip-card-back"> | ||||||
|  |       <div class="popis_rocniku"> | ||||||
|  |         Jednotlivá čísla: | ||||||
|         <ul> |         <ul> | ||||||
|     {% for r in object_list %} |           {% for cislo in rocnik.cisla.all reversed %} | ||||||
|     <li><a href='{{ r.verejne_url }}'>Ročník {{ r }}</a> |           <li><a href='{{ cislo.verejne_url }}'>{{ cislo.poradi }}. číslo</a> {% if cislo.pdf %}(<a href='{{ cislo.pdf.url }}'>pdf</a>) {% endif %} | ||||||
|  |           {% empty %} | ||||||
|  |           Žádná čísla k zobrazení | ||||||
|  |           {% endfor %} | ||||||
|  |           </ul> | ||||||
|  |           <a href='{{ rocnik.verejne_url }}'>Výsledková listina</a> <!-- FIXME:  url výsledkovky--> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       </div> | ||||||
|  |       </div> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       {# konec karty ročníku #} | ||||||
|  | 
 | ||||||
|  |     <hr> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|     {% empty %} |     {% empty %} | ||||||
|       Nejsou žádné ročníky |       Nejsou žádné ročníky | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|   </ul> |  | ||||||
| 
 | 
 | ||||||
| </div> | </div> | ||||||
| {% endblock content %} | {% endblock content %} | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -49,12 +49,12 @@ | ||||||
|   {% endif %} |   {% endif %} | ||||||
| 
 | 
 | ||||||
|   {% if cislo.verejna_vysledkovka %} |   {% if cislo.verejna_vysledkovka %} | ||||||
|   <h2>Výsledkovka ({% now "jS F Y H:i" %})</h2> |   <h2>Výsledkovka</h2> | ||||||
| 
 | 
 | ||||||
|   {% else %} |   {% else %} | ||||||
|     {% if user.is_staff %} |     {% if user.is_staff %} | ||||||
|       <div class='mam-org-only'> |       <div class='mam-org-only'> | ||||||
|       <h2>Výsledkovka (neveřejná, {% now "jS F Y H:i:s" %})</h2> |       <h2>Výsledkovka (neveřejná)</h2> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|   {% endif %} |   {% endif %} | ||||||
| 
 | 
 | ||||||
|  | @ -73,7 +73,7 @@ | ||||||
|       <tr> |       <tr> | ||||||
|         <td class='border-r'>{% autoescape off %}{{ rv.poradi }}{% endautoescape %} |         <td class='border-r'>{% autoescape off %}{{ rv.poradi }}{% endautoescape %} | ||||||
|             <th class='border-r'> |             <th class='border-r'> | ||||||
|             {% if rv.titul is not '' %} |             {% if rv.titul %} | ||||||
|               {{ rv.titul }}<sup>MM</sup> |               {{ rv.titul }}<sup>MM</sup> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|             {{ rv.resitel.osoba.plne_jmeno }} |             {{ rv.resitel.osoba.plne_jmeno }} | ||||||
|  | @ -92,8 +92,5 @@ | ||||||
|       </div> |       </div> | ||||||
|   {% endif %} |   {% endif %} | ||||||
| 
 | 
 | ||||||
|   Čas: {% now "jS F Y H:i:s" %} |  | ||||||
| 
 |  | ||||||
| </div>  | </div>  | ||||||
| {% endblock content %}  | {% endblock content %}  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| \setlength{\tabcolsep}{3pt} | \setlength{\tabcolsep}{3pt} | ||||||
| \begin{longtable}{|r|l|c|r|{% for p in problemy %}c@{\hskip.5em}{% endfor %}|r|r|}\hline | \begin{longtable}{|r|l|c|r|{% for p in problemy %}c@{\hskip.5em}{% endfor %}|r|r|}\hline | ||||||
| & & & & \multicolumn{ {{ problemy|length}} }{c|}{\textbf{Úlohy}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in problemy %}{% if p.typ == "uloha" %}\textbf{r{{p.kod}}}&{% elif p.typ == "tema" %}\textbf{t{{p.kod}}}&{% else  %}\textbf{ {{p.kod}} }&{% endif %}{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline | & & & & \multicolumn{ {{ problemy|length}} }{c|}{\textbf{Úlohy}} & & \\\textbf{Poř.}& \textbf{Jméno}& \textbf{R.}& \raisebox{0.7mm}{$\sum_{-1}$}& {% for p in problemy %}\textbf{ {{ p.kod_v_rocniku }} }&{% endfor %}\raisebox{0.7mm}{$\sum_0$}&\raisebox{0.7mm}{$\sum_1$}\\\hline | ||||||
| \endhead | \endhead | ||||||
| \hline | \hline | ||||||
| \endfoot  | \endfoot  | ||||||
| {% for rv in vysledkovka %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.inicial_krestni}} {{rv.resitel.prijmeni}}&{{rv.resitel.rocnik|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_ulohy %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_celkem_rocnik|default:0}}\\ | {% for rv in radky_vysledkovky %}{{rv.poradi}}&{% if rv.titul %}\titul{ {{ rv.titul}}}{% endif %}{{rv.resitel.osoba.jmeno|slice:":1"}}. {{rv.resitel.osoba.prijmeni}}&{{rv.rocnik_resitele|default:""}}&{{rv.body_celkem_odjakziva}}&{% for b in rv.body_problemy_sezn %}{{b}}&{% endfor %}{{rv.body_cislo}}&{{rv.body_rocnik|default:0}}\\ | ||||||
| {% endfor %} | {% endfor %} | ||||||
| \end{longtable} | \end{longtable} | ||||||
|  |  | ||||||
|  | @ -2,22 +2,11 @@ | ||||||
| 
 | 
 | ||||||
| {% block content %} | {% block content %} | ||||||
| <div> | <div> | ||||||
|   <h1> |   <h2> | ||||||
|     {% block nadpis1a %}{% block nadpis1b %} |     {% block nadpis1a %}{% block nadpis1b %} | ||||||
|       Ročník {{ rocnik.roman }} |       Ročník {{ rocnik }} | ||||||
|     {% endblock %}{% endblock %} |     {% endblock %}{% endblock %} | ||||||
|   </h1> |   </h2> | ||||||
| 
 |  | ||||||
|   <p>Ročník číslo {{ rocnik.rocnik }} ({{ rocnik.prvni_rok }}/{{ rocnik.druhy_rok }}) |  | ||||||
| 
 |  | ||||||
|   <ul> |  | ||||||
|   {% for c in rocnik.verejna_cisla %} |  | ||||||
|   <li><a href="{{ c.verejne_url }}">Číslo {{ c.kod }}</a> |  | ||||||
|       {% if c.pdf %} |  | ||||||
|         (<a href='{{ c.pdf.url }}'>pdf</a>) |  | ||||||
|       {% endif %} |  | ||||||
|   {% endfor %} |  | ||||||
|   </ul> |  | ||||||
| 
 | 
 | ||||||
|   {% if temata_v_rocniku %} |   {% if temata_v_rocniku %} | ||||||
|     <h2>Témata</h2> |     <h2>Témata</h2> | ||||||
|  | @ -28,6 +17,50 @@ | ||||||
|     </ul> |     </ul> | ||||||
|   {% endif %} |   {% endif %} | ||||||
| 
 | 
 | ||||||
|  | <div class="cisla-v-rocniku"> | ||||||
|  |   {% for c in rocnik.verejna_cisla %} | ||||||
|  |     <div class="cislo_pole"> | ||||||
|  | 
 | ||||||
|  |       <h6> Číslo {{ c.kod }}</h6> | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card" id="archiv-rocnik"> | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card-inner"> | ||||||
|  |         <div class="flip-card-front"> | ||||||
|  | 
 | ||||||
|  |       <div class="flip-card-foto"> | ||||||
|  |         {% if c.titulka_nahled %} | ||||||
|  |         <img src="{{ c.titulka_nahled.url }}" alt="{{ c.kod }}" height=180px> | ||||||
|  |         {% else %} | ||||||
|  |         <img src="" alt="no image" height=180px> | ||||||
|  |         {% endif %} | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       </div> | ||||||
|  |        <div class="flip-card-back"> | ||||||
|  | 
 | ||||||
|  |          <div class="cislo_odkazy"> | ||||||
|  |            <ul> | ||||||
|  |              <li> | ||||||
|  |                <a href="{{ c.verejne_url }}">archiv čísla</a> | ||||||
|  |              </li> | ||||||
|  |              {% if c.pdf %} | ||||||
|  |              <li> | ||||||
|  |                  <a href='{{ c.pdf.url }}'>pdf</a> | ||||||
|  |              </li> | ||||||
|  |              {% endif %} | ||||||
|  |            </ul> | ||||||
|  |          </div> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       </div> | ||||||
|  |       </div> | ||||||
|  |       </div> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |   {% endfor %} | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|   {% if vysledkovka %} |   {% if vysledkovka %} | ||||||
|     {% if user.is_staff %} |     {% if user.is_staff %} | ||||||
|       <div class='mam-org-only'> |       <div class='mam-org-only'> | ||||||
|  | @ -42,7 +75,7 @@ | ||||||
|   {% if user.is_staff and vysledkovka_s_neverejnymi %} |   {% if user.is_staff and vysledkovka_s_neverejnymi %} | ||||||
|     <div class='mam-org-only'> |     <div class='mam-org-only'> | ||||||
|     <h2>Výsledková listina včetně neveřejných bodů</h2> |     <h2>Výsledková listina včetně neveřejných bodů</h2> | ||||||
|       {% with vysledkovka_s_neverejnymi as vysledkovka %} |       {% with radky_vyledkovky_s_neverejnymi as radky_vysledkovky %} | ||||||
|         {% include "seminar/vysledkovka_rocnik.html" %} |         {% include "seminar/vysledkovka_rocnik.html" %} | ||||||
|       {% endwith %} |       {% endwith %} | ||||||
|     </div> |     </div> | ||||||
|  | @ -50,7 +83,3 @@ | ||||||
| 
 | 
 | ||||||
| </div> | </div> | ||||||
| {% endblock content %} | {% endblock content %} | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| {% with lb="{" %} | {% with lb="{" %} | ||||||
| {% with rb="}" %} | {% with rb="}" %} | ||||||
| \setlength{\tabcolsep}{3pt} | \setlength{\tabcolsep}{3pt} | ||||||
| \begin{longtable}{|r|l|c|r|{% for cislo in vysledkovka.cisla %}c{% if not forloop.last %}@{\hskip.5em}{% endif %}{% endfor %}|r|} | \begin{longtable}{|r|l|c|r|{% for cislo in cisla %}c{% if not forloop.last %}@{\hskip.5em}{% endif %}{% endfor %}|r|}\hline | ||||||
| \hline | & & & & \multicolumn{{ lb }}{{ cisla|length }}}{c|}{\textbf{Číslo}} & \\\textbf{Poř.} & \textbf{Jméno} & \textbf{R.} & \raisebox{0.7mm}{$\sum_{-1}$} & {% for cislo in cisla %}\textbf{{ lb }}{{ cislo.poradi }}{{ rb }} & {% endfor %}\raisebox{0.7mm}{$\sum_1$} \\\hline | ||||||
| & & & & \multicolumn{{ lb }}{{ vysledkovka.cisla|length }}}{c|}{\textbf{Číslo}} & \\\textbf{Poř.} & \textbf{Jméno} & \textbf{R.} & \raisebox{0.7mm}{$\sum_{-1}$} & {% for cislo in vysledkovka.cisla %}\textbf{{ lb }}{{ cislo.cislo }}{{ rb }} & {% endfor %}\raisebox{0.7mm}{$\sum_1$} \\\hline |  | ||||||
| \endhead | \endhead | ||||||
| \hline | \hline | ||||||
| \endfoot | \endfoot | ||||||
| {% for rv in vysledkovka.radky %}{{ rv.poradi }} & {% if rv.titul %}\titul{{ lb }}{{ rv.titul }}}~{% endif %}{{ rv.resitel.jmeno|slice:":1" }}.~{{ rv.resitel.prijmeni }} & {% if rv.resitel.rocnik %}{{ rv.resitel.rocnik }}.{% endif %} & {{ rv.body_odjakziva }} {% for b in rv.body_cisla %} & {{ b }}{% endfor %} & {{ rv.body_rocnik }} \\ | {% for rv in radky_vysledkovky %}{{ rv.poradi }} & {% if rv.titul %}\titul{{ lb }}{{ rv.titul }}}~{% endif %}{{ rv.resitel.osoba.jmeno|slice:":1" }}.~{{ rv.resitel.osoba.prijmeni }} & {% if rv.rocnik_resitele %}{{ rv.rocnik_resitele }}{% endif %} & {{ rv.body_celkem_odjakziva }} {% for b in rv.body_cisla_sezn %} & {{ b }}{% endfor %} & {{ rv.body_rocnik }} \\ | ||||||
| {% endfor %}\end{longtable} | {% endfor %}\end{longtable} | ||||||
| {% endwith %} | {% endwith %} | ||||||
| {% endwith %} | {% endwith %} | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| {% if broken %} | {% if broken %} | ||||||
| %% POZOR! %% Dva resitele maji stejne makro!!! | POZOR! Kolize jmen! Dva řešitelé mají stejné makro! | ||||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |  | ||||||
| {% endif %} | {% endif %} | ||||||
| 
 | 
 | ||||||
| {% autoescape off %} | {% autoescape off %} | ||||||
|  |  | ||||||
|  | @ -46,12 +46,12 @@ | ||||||
| 
 | 
 | ||||||
|     {# karta organizátora - zepředu fotka, zezadu popis, u neaktivních data kdy organizovali #} |     {# karta organizátora - zepředu fotka, zezadu popis, u neaktivních data kdy organizovali #} | ||||||
| 
 | 
 | ||||||
|     <div class="flip-card"> |     <div class="flip-card" id="organizatori"> | ||||||
| 
 | 
 | ||||||
|     <div class="flip-card-inner"> |     <div class="flip-card-inner"> | ||||||
|       <div class="flip-card-front"> |       <div class="flip-card-front"> | ||||||
| 
 | 
 | ||||||
|     <div class="foto_org"> |     <div class="flip-card-foto"> | ||||||
|     {% if org.osoba.foto %} |     {% if org.osoba.foto %} | ||||||
|       <a href="{{org.osoba.foto.url}}"><img src="{{org.osoba.foto_male.url}}" height="{{org.osoba.foto_male.height}}" alt="{{org.osoba.jmeno}} {{org.osoba.prijmeni}}"></a> |       <a href="{{org.osoba.foto.url}}"><img src="{{org.osoba.foto_male.url}}" height="{{org.osoba.foto_male.height}}" alt="{{org.osoba.jmeno}} {{org.osoba.prijmeni}}"></a> | ||||||
|     {% else %} {# pokud osoba nemá fotku, zobrazuje se defaultní obrázek #} |     {% else %} {# pokud osoba nemá fotku, zobrazuje se defaultní obrázek #} | ||||||
|  |  | ||||||
|  | @ -4,23 +4,23 @@ | ||||||
|     <th class='border-r'>Jméno |     <th class='border-r'>Jméno | ||||||
|     <th class='border-r'>R. |     <th class='border-r'>R. | ||||||
|     <th class='border-r'>Odjakživa |     <th class='border-r'>Odjakživa | ||||||
|         {% for c in vysledkovka.cisla %} |         {% for c in cisla %} | ||||||
|     <th class='border-r'><a href="{{ c.verejne_url }}"> |     <th class='border-r'><a href="{{ c.verejne_url }}"> | ||||||
|             {{c.rocnik.rocnik}}.{{ c.cislo }}</a> |             {{c.rocnik.rocnik}}.{{ c.poradi }}</a> | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|     <th class='border-r'>Celkem |     <th class='border-r'>Celkem | ||||||
| 
 | 
 | ||||||
| {% for rv in vysledkovka.radky %} | {% for rv in radky_vysledkovky %} | ||||||
|   <tr> |   <tr> | ||||||
|     <td class='border-r'>{% autoescape off %}{{ rv.poradi }}{% endautoescape %} |     <td class='border-r'>{% autoescape off %}{{ rv.poradi }}{% endautoescape %} | ||||||
|     <th class='border-r'> |     <th class='border-r'> | ||||||
|       {% if rv.titul %} |       {% if rv.titul %} | ||||||
|         {{ rv.titul }}<sup>MM</sup> |         {{ rv.titul }}<sup>MM</sup> | ||||||
|       {% endif %} |       {% endif %} | ||||||
|       {{ rv.resitel.plne_jmeno }} |       {{ rv.resitel.osoba.plne_jmeno }} | ||||||
|     <td class='border-r'>{{ rv.resitel.rocnik }} |     <td class='border-r'>{{ rv.rocnik_resitele }} | ||||||
|     <td class='border-r'>{{ rv.body_odjakziva }} |     <td class='border-r'>{{ rv.body_celkem_odjakziva }} | ||||||
|     {% for b in rv.body_cisla %} |     {% for b in rv.body_cisla_sezn %} | ||||||
|     <td class='border-r'>{{ b }} |     <td class='border-r'>{{ b }} | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|     <td class='border-r'><b>{{ rv.body_rocnik }}</b> |     <td class='border-r'><b>{{ rv.body_rocnik }}</b> | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ from django.db import transaction | ||||||
| import unidecode | import unidecode | ||||||
| import logging | import logging | ||||||
| 
 | 
 | ||||||
| from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, KonferaNode, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode | from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode | ||||||
| 
 | 
 | ||||||
| from django.contrib.flatpages.models import FlatPage | from django.contrib.flatpages.models import FlatPage | ||||||
| from django.contrib.sites.models import Site | from django.contrib.sites.models import Site | ||||||
|  | @ -270,9 +270,12 @@ def gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size) | ||||||
| 					#print("Generuji {}-té řešení".format(ri)) | 					#print("Generuji {}-té řešení".format(ri)) | ||||||
| 					if rnd.randint(1, 10) == 6: | 					if rnd.randint(1, 10) == 6: | ||||||
| 					# cca desetina řešení od více řešitelů | 					# cca desetina řešení od více řešitelů | ||||||
| 						res_vyber = rnd.sample(resitele_cisla, rnd.randint(2, 5)) | 						res_vyber = rnd.sample(resitele_cisla,  | ||||||
|  | 							rnd.randint(2, 5)) | ||||||
| 					else: | 					else: | ||||||
| 						res_vyber = rnd.sample(resitele_cisla, 1) | 						res_vyber = rnd.sample(resitele_cisla, 1) | ||||||
|  | 					if resitele[0] in res_vyber: | ||||||
|  | 						res_vyber.remove(resitele[0]) | ||||||
| 					res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0]) | 					res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0]) | ||||||
| 					# problem a resitele přiřadíme později, ManyToManyField | 					# problem a resitele přiřadíme později, ManyToManyField | ||||||
| 					# se nedá vyplnit v create() | 					# se nedá vyplnit v create() | ||||||
|  | @ -336,7 +339,7 @@ def gen_konfery(size, rnd, organizatori, resitele, soustredeni): | ||||||
| 			nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), | 			nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']), | ||||||
| 			anotace=lorem.paragraph(), | 			anotace=lorem.paragraph(), | ||||||
| 			abstrakt=lorem.paragraph(), | 			abstrakt=lorem.paragraph(), | ||||||
| 			organizator=rnd.choice(organizatori), | 			garant=rnd.choice(organizatori), | ||||||
| 			soustredeni=rnd.choice(soustredeni), | 			soustredeni=rnd.choice(soustredeni), | ||||||
| 			typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) | 			typ_prezentace=rnd.choice(['veletrh', 'prezentace'])) | ||||||
| 		ucastnici_sous = list(konfera.soustredeni.ucastnici.all()) | 		ucastnici_sous = list(konfera.soustredeni.ucastnici.all()) | ||||||
|  | @ -346,9 +349,6 @@ def gen_konfery(size, rnd, organizatori, resitele, soustredeni): | ||||||
| 		#	Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) | 		#	Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera) | ||||||
| 		konfera.save() | 		konfera.save() | ||||||
| 		konfery.append(konfera) | 		konfery.append(konfera) | ||||||
| 
 |  | ||||||
| 		konferanode = KonferaNode.objects.create(konfera=konfera) |  | ||||||
| 		konferanode.save() |  | ||||||
| 	return konfery | 	return konfery | ||||||
| 
 | 
 | ||||||
| def gen_cisla(rnd, rocniky): | def gen_cisla(rnd, rocniky): | ||||||
|  | @ -407,7 +407,8 @@ def gen_temata(rnd, rocniky, rocnik_cisla, organizatori): | ||||||
| 	poc_oboru = rnd.randint(1, 2) | 	poc_oboru = rnd.randint(1, 2) | ||||||
| 
 | 
 | ||||||
| 	rocnik_temata = [] | 	rocnik_temata = [] | ||||||
| 	# Věříme, že rocnik_cisla je pole polí čísel podle ročníků, tak si necháme dát vždycky jeden ročník a k němu příslušná čísla. | 	# Věříme, že rocnik_cisla je pole polí čísel podle ročníků, tak si necháme dát  | ||||||
|  | 	# vždycky jeden ročník a k němu příslušná čísla. | ||||||
| 	for rocnik, cisla in zip(rocniky, rocnik_cisla): | 	for rocnik, cisla in zip(rocniky, rocnik_cisla): | ||||||
| 		kod = 1 | 		kod = 1 | ||||||
| 		letosni_temata = [] | 		letosni_temata = [] | ||||||
|  |  | ||||||
|  | @ -81,18 +81,20 @@ urlpatterns = [ | ||||||
| 	path('aesop-export/index.csv', export.ExportIndexView.as_view(), name='seminar_export_index'), | 	path('aesop-export/index.csv', export.ExportIndexView.as_view(), name='seminar_export_index'), | ||||||
| 
 | 
 | ||||||
| 	# Stranky viditelne pouze pro orgy: | 	# Stranky viditelne pouze pro orgy: | ||||||
| 	#path( | 	path( | ||||||
| 	#    'rocnik/(?P<rocnik>\d+)/vysledkovka.tex', | 	    'rocnik/<int:rocnik>/vysledkovka.tex', | ||||||
| 	#    staff_member_required(views.RocnikVysledkovkaView.as_view()), | 	    staff_member_required(views.RocnikVysledkovkaView.as_view()), | ||||||
| 	#    name='seminar_cislo_vysledkovka' | 	    name='seminar_rocnik_vysledkovka' | ||||||
| 	#), | 	), | ||||||
| 	#path('cislo/(?P<rocnik>\d+).(?P<cislo>[0-9-]+)/vysledkovka.tex', | 	path('cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex', | ||||||
| 	 #   staff_member_required(views.CisloVysledkovkaView.as_view()), name='seminar_cislo_vysledkovka'), | 	    staff_member_required(views.CisloVysledkovkaView.as_view()),  | ||||||
|  | 	    name='seminar_cislo_vysledkovka' | ||||||
|  | 	), | ||||||
| 	path('cislo/<int:rocnik>.<int:cislo>/obalky.pdf', | 	path('cislo/<int:rocnik>.<int:cislo>/obalky.pdf', | ||||||
| 		staff_member_required(views.cisloObalkyView), name='seminar_cislo_obalky'), | 		staff_member_required(views.cisloObalkyView), name='seminar_cislo_obalky'), | ||||||
| 
 | 
 | ||||||
| 	#path('cislo/(?P<rocnik>\d+).(?P<cislo>[0-9-]+)/tituly.tex', | 	path('cislo/<int:rocnik>.<int:cislo>/tituly.tex', | ||||||
| 	 #   staff_member_required(views.TitulyView), name='seminar_cislo_titul'), | 	    	staff_member_required(views.TitulyView), name='seminar_cislo_titul'), | ||||||
| 	path('stav', | 	path('stav', | ||||||
| 		staff_member_required(views.StavDatabazeView), name='stav_databaze'), | 		staff_member_required(views.StavDatabazeView), name='stav_databaze'), | ||||||
| 	path('cislo/<int:rocnik>.<int:cislo>/obalkovani', | 	path('cislo/<int:rocnik>.<int:cislo>/obalkovani', | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ import traceback | ||||||
| import sys | import sys | ||||||
| import csv | import csv | ||||||
| import logging | import logging | ||||||
|  | import time | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def verejna_temata(rocnik): | def verejna_temata(rocnik): | ||||||
|  | @ -340,93 +341,32 @@ class ArchivView(generic.ListView): | ||||||
| 	def get_context_data(self, **kwargs): | 	def get_context_data(self, **kwargs): | ||||||
| 		context = super(ArchivView, self).get_context_data(**kwargs) | 		context = super(ArchivView, self).get_context_data(**kwargs) | ||||||
| 
 | 
 | ||||||
| 		vyska = 297  # px | 		cisla = Cislo.objects.filter(poradi=1) | ||||||
| 		sirka = 210  # px | 		urls ={} | ||||||
| 
 |  | ||||||
| 		# nejnovějších 10 zveřejněných čísel |  | ||||||
| 		# cisla = Cislo.objects.filter(verejne_db=True)[:10] |  | ||||||
| 		cisla = Cislo.objects.filter(poradi=1)[:10]		 |  | ||||||
| 
 |  | ||||||
| 		# op == os.path, udělá z argumentů cestu |  | ||||||
| 		png_dir = op.join(settings.MEDIA_ROOT, "cislo", "png") |  | ||||||
| 
 |  | ||||||
| 		# seznam [(url obrázku, číslo)] |  | ||||||
| 		urls = [] |  | ||||||
| 
 | 
 | ||||||
| 		for i, c in enumerate(cisla): | 		for i, c in enumerate(cisla): | ||||||
| 			if not c.pdf: | 			if c.titulka_nahled: | ||||||
| 				continue | 				urls[c.rocnik] = c.titulka_nahled.url | ||||||
| 			filename = os.path.split(c.pdf.file.name)[1].split(".")[0] | 			else: | ||||||
| 			png_filename = "{}-{}px.png".format(filename, vyska) | 				urls[c.rocnik] = op.join(settings.MEDIA_URL, "cislo", "png", "default.png") | ||||||
| 
 | 
 | ||||||
| 			# Pokud obrázek neexistuje nebo není aktuální, vytvoř jej | 		context["object_list"] = urls | ||||||
| 			png_path = op.join(png_dir, png_filename) |  | ||||||
| 			if not op.exists(png_path) or \ |  | ||||||
| 					op.getmtime(png_path) < op.getmtime(c.pdf.path): |  | ||||||
| 		 | 		 | ||||||
| 				subprocess.call([ |  | ||||||
| 					"convert", |  | ||||||
| 					"-density", "300x300", |  | ||||||
| 					"-geometry", "{}x{}".format(vyska, sirka), |  | ||||||
| 					"-background", "white", |  | ||||||
| 					"-flatten", |  | ||||||
| 					"-rotate", str(90 * i), |  | ||||||
| 					"{}[0]".format(c.pdf.path),  # titulní strana |  | ||||||
| 					png_path |  | ||||||
| 				]) |  | ||||||
| 
 |  | ||||||
| 			urls.append( |  | ||||||
| 				(op.join(settings.MEDIA_URL, "cislo", "png", png_filename), c) |  | ||||||
| 			) |  | ||||||
| 			vyska, sirka = sirka, vyska / 2 |  | ||||||
| 
 |  | ||||||
| 		tags = [] |  | ||||||
| 
 |  | ||||||
| 		def spirala(urls, tags, idx): |  | ||||||
| 			"""Rekurzivně prochází urls a generuje strom elementů do tags""" |  | ||||||
| 			if idx >= len(urls): |  | ||||||
| 				return |  | ||||||
| 
 |  | ||||||
| 			img_url, cislo = urls[idx] |  | ||||||
| 			tags.append( |  | ||||||
| 				"<div style='top:{}%;left:{}%;width:{}%;height:{}%;'>" |  | ||||||
| 				.format( |  | ||||||
| 					50 if idx % 4 == 2 else 0, |  | ||||||
| 					50 if idx % 4 == 1 else 0, |  | ||||||
| 					50 if idx % 2 == 1 else 100, |  | ||||||
| 					50 if idx > 0 and idx % 2 == 0 else 100 |  | ||||||
| 				) |  | ||||||
| 			) |  | ||||||
| 			tags.append("<a href='{}' title='{}'>".format( |  | ||||||
| 				cislo.verejne_url(), cislo.kod() |  | ||||||
| 			)) |  | ||||||
| 			tags.append( |  | ||||||
| 				"<img src='{}' style='top:{}%;left:{}%;width:{}%;height:{}%;'>" |  | ||||||
| 				.format( |  | ||||||
| 					img_url, |  | ||||||
| 					50 if idx % 4 == 3 else 0, |  | ||||||
| 					50 if idx % 4 == 2 else 0, |  | ||||||
| 					50 if idx % 2 == 0 else 100, |  | ||||||
| 					50 if idx % 2 == 1 else 100 |  | ||||||
| 				) |  | ||||||
| 			) |  | ||||||
| 			tags.append("</a>") |  | ||||||
| 			spirala(urls, tags, idx + 1) |  | ||||||
| 			tags.append("</div>") |  | ||||||
| 		spirala(urls, tags, 0) |  | ||||||
| 
 |  | ||||||
| 		context["nahledy"] = "\n".join(tags) |  | ||||||
| 		return context | 		return context | ||||||
| 
 | 
 | ||||||
| ### Výsledky | ### Výsledky | ||||||
| 
 | 
 | ||||||
| # ze setřízeného(!) seznamu všech bodů vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.) | # ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník  | ||||||
| def sloupec_s_poradim(seznam_s_body): | # vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.), | ||||||
|  | # podle toho, jak jdou za sebou ve výsledkovce | ||||||
|  | def sloupec_s_poradim(setrizene_body): | ||||||
|  | 
 | ||||||
|  | 	# ze seznamu obsahujícího setřízené body spočítáme sloupec s pořadím	 | ||||||
| 	aktualni_poradi = 1 | 	aktualni_poradi = 1 | ||||||
| 	sloupec_s_poradim = [] | 	sloupec_s_poradim = [] | ||||||
| 
 | 
 | ||||||
| 	# seskupíme seznam všech bodů podle hodnot | 	# seskupíme seznam všech bodů podle hodnot | ||||||
| 	for index in range(0, len(seznam_s_body)): | 	for index in range(0, len(setrizene_body)): | ||||||
| 		# pokud je pořadí větší než číslo řádku, tak jsme vypsali větší rozsah a chceme | 		# pokud je pořadí větší než číslo řádku, tak jsme vypsali větší rozsah a chceme | ||||||
| 		# vypsat už jen prázdné místo, než dojdeme na správný řádek | 		# vypsat už jen prázdné místo, než dojdeme na správný řádek | ||||||
| 		if (index + 1) < aktualni_poradi: | 		if (index + 1) < aktualni_poradi: | ||||||
|  | @ -434,10 +374,10 @@ def sloupec_s_poradim(seznam_s_body): | ||||||
| 			continue | 			continue | ||||||
| 		velikost_skupiny = 0 | 		velikost_skupiny = 0 | ||||||
| 		# zjistíme počet po sobě jdoucích stejných hodnot | 		# zjistíme počet po sobě jdoucích stejných hodnot | ||||||
| 		while seznam_s_body[index] == seznam_s_body[index + velikost_skupiny]: | 		while setrizene_body[index] == setrizene_body[index + velikost_skupiny]: | ||||||
| 			velikost_skupiny = velikost_skupiny + 1 | 			velikost_skupiny = velikost_skupiny + 1 | ||||||
| 			# na konci musíme ošetřit přetečení seznamu | 			# na konci musíme ošetřit přetečení seznamu | ||||||
| 			if (index + velikost_skupiny) > len(seznam_s_body) - 1: | 			if (index + velikost_skupiny) > len(setrizene_body) - 1: | ||||||
| 				break | 				break | ||||||
| 		# pokud je velikost skupiny 1, vypíšu pořadí | 		# pokud je velikost skupiny 1, vypíšu pořadí | ||||||
| 		if velikost_skupiny == 1: | 		if velikost_skupiny == 1: | ||||||
|  | @ -450,28 +390,12 @@ def sloupec_s_poradim(seznam_s_body): | ||||||
| 		aktualni_poradi = aktualni_poradi + velikost_skupiny | 		aktualni_poradi = aktualni_poradi + velikost_skupiny | ||||||
| 	return sloupec_s_poradim | 	return sloupec_s_poradim | ||||||
| 
 | 
 | ||||||
| ## spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy | # vrátí všechna čísla daného ročníku   | ||||||
| #def __soucet_resitele_problemu(problem, resitel, cislo, soucet): | def cisla_rocniku(rocnik, jen_verejne=True): | ||||||
| #	# sečteme body za daný problém přes všechna řešení daného problému  | 	if jen_verejne: | ||||||
| #	# od daného řešitele | 		return rocnik.verejna_cisla() | ||||||
| #	reseni_resitele = s.Reseni_Resitele.objects.filter(resitele=resitel) | 	else: | ||||||
| #	hodnoceni_resitele = problem.hodnoceni.filter(reseni__in=reseni_resitele,  | 		return rocnik.cisla.all() | ||||||
| #				cislo_body=cislo) |  | ||||||
| #	# XXX chyba na řádku výše - řešení může mít více řešitelů, asi chceme contains |  | ||||||
| #	# nebo in |  | ||||||
| #	for r in hodnoceni_resitele: |  | ||||||
| #		soucet += r.body |  | ||||||
| # |  | ||||||
| #	# a přičteme k tomu hodnocení všech podproblémů |  | ||||||
| #	for p in problem.podproblem.all():  |  | ||||||
| #	# i přes jméno by to měla být množina jeho podproblémů |  | ||||||
| #		soucet += __soucet_resitele_problemu(p, resitel, soucet) |  | ||||||
| #	return soucet |  | ||||||
| 
 |  | ||||||
| ## spočítá součet všech bodů ze všech podproblémů daného problému daného řešitele |  | ||||||
| #def body_resitele_problemu_v_cisle(problem, resitel, cislo): |  | ||||||
| #	# probably FIXED: nezohledňuje číslo, do kterého se body počítají |  | ||||||
| #	return __soucet_resitele_problemu(problem, resitel, cislo, 0) |  | ||||||
| 
 | 
 | ||||||
| # pro daný problém vrátí jeho nejvyšší nadproblém | # pro daný problém vrátí jeho nejvyšší nadproblém | ||||||
| def hlavni_problem(problem): | def hlavni_problem(problem): | ||||||
|  | @ -479,6 +403,17 @@ def hlavni_problem(problem): | ||||||
| 		problem = problem.nadproblem | 		problem = problem.nadproblem | ||||||
| 	return problem | 	return problem | ||||||
| 
 | 
 | ||||||
|  | def hlavni_problemy_rocniku(rocnik, jen_verejne=True): | ||||||
|  | 	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 | ||||||
|  | 
 | ||||||
| # vrátí list všech problémů s body v daném čísle, které již nemají nadproblém | # vrátí list všech problémů s body v daném čísle, které již nemají nadproblém | ||||||
| def hlavni_problemy_cisla(cislo): | def hlavni_problemy_cisla(cislo): | ||||||
| 	hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all()	 | 	hodnoceni = cislo.hodnoceni.select_related('problem', 'reseni').all()	 | ||||||
|  | @ -504,31 +439,12 @@ def hlavni_problemy_cisla(cislo): | ||||||
| 
 | 
 | ||||||
| # vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník | # vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník | ||||||
| def body_resitelu_odjakziva(rocnik, resitele): | def body_resitelu_odjakziva(rocnik, resitele): | ||||||
| 	body_odjakziva = {} | 	# Následující řádek přidá ke každému řešiteli údaj ".body" se součtem jejich bodů | ||||||
| 
 | 	resitele_s_body = Resitel.objects.annotate(body=Sum('reseni__hodnoceni__body')) | ||||||
| 	for r in resitele: | 	# Teď jen z QuerySetu řešitelů anotovaných body vygenerujeme slovník indexovaný řešitelským id obsahující body | ||||||
| 		body_odjakziva[str(r.id)] = 0 | 	# ... ale jen ro řešitele, které dostaneme jako parametr. | ||||||
| # POZOR! Aktuálně počítá jen za posledních 10 let od zadaného ročníku | 	# TODO: Zjistit, co ten parametr říká a proč je potřeba | ||||||
| #	# Body za posledních 10 let je dobrá aproximace pro naše potřeby (výsledkovka | 	body_odjakziva = {int(res.id) : res.body for res in resitele_s_body if res in resitele} | ||||||
| #	# s aktivními řešiteli) |  | ||||||
| # |  | ||||||
| #	body_pred_roky = [] |  | ||||||
| #	for i in range(0, 10): |  | ||||||
| #		body_pred_roky.append(body_resitelu_za_rocnik(rocnik-i, resitele)) |  | ||||||
| # |  | ||||||
| #	for r in resitele: |  | ||||||
| #		for i in range(0,10): |  | ||||||
| #			body_odjakziva[str(r.id)] += body_pred_roky[i][str(r.id)] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Nasledující řešení je sice správné, ale moc pomalé:	 |  | ||||||
| 	for res in Reseni.objects.prefetch_related('resitele', 'hodnoceni_set').all(): |  | ||||||
| 		for r in res.resitele.all(): |  | ||||||
| 			# daný řešitel nemusí být v naší podmnožině |  | ||||||
| 			if r not in resitele: continue |  | ||||||
| 			 |  | ||||||
| 			for hodn in res.hodnoceni_set.all(): |  | ||||||
| 				pricti_body(body_odjakziva, r, hodn.body) |  | ||||||
| 	return body_odjakziva | 	return body_odjakziva | ||||||
| 
 | 
 | ||||||
| # vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník | # vrátí slovník řešitel:body obsahující počty bodů zadaných řešitelů za daný ročník | ||||||
|  | @ -536,73 +452,89 @@ def body_resitelu_za_rocnik(rocnik, aktivni_resitele): | ||||||
| 	body_za_rocnik = {} | 	body_za_rocnik = {} | ||||||
| 	# inicializujeme na 0 pro všechny aktivní řešitele | 	# inicializujeme na 0 pro všechny aktivní řešitele | ||||||
| 	for ar in aktivni_resitele: | 	for ar in aktivni_resitele: | ||||||
| 		body_za_rocnik[str(ar.id)] = 0 | 		body_za_rocnik[ar.id] = 0 | ||||||
| 	 | 	 | ||||||
| 	# spočítáme body řešitelům přes všechna řešení s hodnocením v daném ročníku | 	# spočítáme body řešitelům přes všechna řešení s hodnocením v daném ročníku | ||||||
|  | 	print("Před dotazem:{}".format(time.time()))	 | ||||||
| 	reseni = Reseni.objects.prefetch_related('resitele', 'hodnoceni_set').filter(hodnoceni__cislo_body__rocnik=rocnik) | 	reseni = Reseni.objects.prefetch_related('resitele', 'hodnoceni_set').filter(hodnoceni__cislo_body__rocnik=rocnik) | ||||||
|  | 	print("Po dotazu:{}".format(time.time()))	 | ||||||
| 	for res in reseni: | 	for res in reseni: | ||||||
| 		for resitel in res.resitele.all(): | 		for resitel in res.resitele.all(): | ||||||
| 			for hodn in res.hodnoceni_set.all(): | 			for hodn in res.hodnoceni_set.all(): | ||||||
| 				pricti_body(body_za_rocnik, resitel, hodn.body) | 				pricti_body(body_za_rocnik, resitel, hodn.body) | ||||||
|  | 	print("Po for-cyklu:{}".format(time.time()))	 | ||||||
| 	return body_za_rocnik | 	return body_za_rocnik | ||||||
| 
 | 
 | ||||||
| # TODO: předělat na nový model | class RadekVysledkovkyRocniku(object): | ||||||
| #def vysledkovka_rocniku(rocnik, jen_verejne=True): | 	"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. | ||||||
| #	"""Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve | 	Umožňuje snazší práci v templatu (lepší, než seznam).""" | ||||||
| #	formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" | 
 | ||||||
| #	""" | 	def __init__(self, poradi, resitel, body_cisla_sezn, body_rocnik, body_odjakziva, rok): | ||||||
| # | 		self.poradi = poradi | ||||||
| #	#vyberu vsechny vysledky z rocniku | 		self.resitel = resitel | ||||||
| #	cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo') | 		self.rocnik_resitele = resitel.rocnik(rok) | ||||||
| #	if jen_verejne: | 		self.body_rocnik = body_rocnik | ||||||
| #		cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True) | 		self.body_celkem_odjakziva = body_odjakziva | ||||||
| # | 		self.body_cisla_sezn = body_cisla_sezn | ||||||
| #	#pokud žádné nejsou, výsledkovka se nezobrazí | 		self.titul = resitel.get_titul(body_odjakziva) | ||||||
| #	if not cisla_v_rocniku: | 
 | ||||||
| #		return None | def vysledkovka_rocniku(rocnik, jen_verejne=True): | ||||||
| # | 	"""Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve | ||||||
| #	#vybere vsechny vysledky z posledniho (verejneho) cisla a setridi sestupne dle bodu | 	formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html" | ||||||
| #	vysledky = list(cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].poradi).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel')) | 	""" | ||||||
| # | 	 | ||||||
| #	class Vysledkovka: | 	## TODO možná chytřeji vybírat aktivní řešitele | ||||||
| #		def __init__(self): | 	# aktivní řešitelé - chceme letos něco poslal, TODO později vyfiltrujeme ty, kdo mají  | ||||||
| #			self.rocnik = rocnik.rocnik | 	# u alespoň jedné hodnoty něco jiného než NULL | ||||||
| #			self.radky = [] | 	aktivni_resitele = list(Resitel.objects.filter( | ||||||
| #			self.cisla = [] | 			rok_maturity__gte=rocnik.druhy_rok())) | ||||||
| # | 			# TODO: zkusit hodnoceni__rocnik... | ||||||
| #	vysledkovka = Vysledkovka() | 			#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik) | ||||||
| #	vysledkovka.cisla = (rocnik.verejne_vysledkovky_cisla() if jen_verejne else rocnik.cisla.all().order_by('cislo')) | 	cisla = cisla_rocniku(rocnik, jen_verejne) | ||||||
| # | 	body_cisla_slov = {} | ||||||
| #	# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině | 	print("Jen veřejná: {}, čísla: {}".format(jen_verejne, cisla)) | ||||||
| #	for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky): | 	for cislo in cisla: | ||||||
| #		v.poradi = poradi | 		# získáme body za číslo | ||||||
| #		v.resitel.rocnik = v.resitel.rocnik(rocnik) | 		_, cislobody = secti_body_za_cislo(cislo, aktivni_resitele) | ||||||
| # | 		body_cisla_slov[cislo.id] = cislobody | ||||||
| #		verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__rocnik=rocnik, cislo=cisla_v_rocniku[0].poradi) | 
 | ||||||
| #		if jen_verejne: | 	# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně | ||||||
| #			verejne_vysl_odjakziva = verejne_vysl_odjakziva.filter(cislo__verejna_vysledkovka=True) | 	resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele) | ||||||
| # | 	 | ||||||
| #		v.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = v.resitel)[0].body | 	# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší | ||||||
| #		v.titul = v.resitel.get_titul(v.body_odjakziva) | 	setrizeni_resitele_id = [dvojice[0] for dvojice in resitel_rocnikbody_sezn] | ||||||
| #		v.body_rocnik = v.body | 	setrizeni_resitele = [Resitel.objects.get(id=i) for i in setrizeni_resitele_id] | ||||||
| #		v.body_cisla = [] | 	setrizene_body = [dvojice[1] for dvojice in resitel_rocnikbody_sezn] | ||||||
| # | 	poradi = sloupec_s_poradim(setrizene_body) | ||||||
| #		#pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0 | 
 | ||||||
| #		for cis in vysledkovka.cisla: | 	# získáme body odjakživa | ||||||
| #			if not jen_verejne or cis.verejna_vysledkovka: | 	resitel_odjakzivabody_slov = body_resitelu_odjakziva(rocnik, aktivni_resitele) | ||||||
| #				#seznam vysledku se spravnym rocnikem a cislem pro resitele | 
 | ||||||
| #				#zobrazim jen je-li vysledkovka verejna | 	# vytvoříme jednotlivé sloupce výsledkovky | ||||||
| #				body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik=rocnik).filter(cislo = cis).filter(resitel = v.resitel) | 	radky_vysledkovky = [] | ||||||
| #				if body_za_cislo: | 	i = 0 | ||||||
| #					#neprazdne vysledky by mely obsahovat prave jeden vysledek | 	for ar_id in setrizeni_resitele_id: | ||||||
| #					v.body_cisla.append(body_za_cislo[0].body) | 		# seznam počtu bodů daného řešitele pro jednotlivá čísla | ||||||
| #				else: | 		body_cisla_sezn = [] | ||||||
| #					#resitel nema za cislo body | 		for cislo in cisla: | ||||||
| #					v.body_cisla.append(0) | 			body_cisla_sezn.append(body_cisla_slov[cislo.id][ar_id]) | ||||||
| # | 
 | ||||||
| #		vysledkovka.radky.append(v) | 		# vytáhneme informace pro daného řešitele | ||||||
| # | 		radek = RadekVysledkovkyRocniku( | ||||||
| #	return vysledkovka | 			poradi[i], # pořadí | ||||||
|  | 			Resitel.objects.get(id=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 | ||||||
|  | 			rocnik) # ročník semináře pro získání ročníku řešitele | ||||||
|  | 		print("{}: číslobody - {}, ročníkbody - {}," | ||||||
|  | 			"odjakživabody - {}".format(radek.resitel, radek.body_cisla_sezn,  | ||||||
|  | 			radek.body_rocnik, radek.body_celkem_odjakziva)) | ||||||
|  | 		radky_vysledkovky.append(radek) | ||||||
|  | 		print("Přikládám {}-tý řádek.".format(i)) | ||||||
|  | 		i += 1 | ||||||
|  | 
 | ||||||
|  | 	return radky_vysledkovky | ||||||
| 	 | 	 | ||||||
| 
 | 
 | ||||||
| class RocnikView(generic.DetailView): | class RocnikView(generic.DetailView): | ||||||
|  | @ -626,10 +558,16 @@ class RocnikView(generic.DetailView): | ||||||
| 	def get_context_data(self, **kwargs): | 	def get_context_data(self, **kwargs): | ||||||
| 		context = super(RocnikView, self).get_context_data(**kwargs) | 		context = super(RocnikView, self).get_context_data(**kwargs) | ||||||
| 
 | 
 | ||||||
| 		#context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"]) | 		# vysledkovka = True zajistí vykreslení, | ||||||
| 		#context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False) | 		# zkontrolovat, kdy se má a nemá vykreslovat | ||||||
| 		#context['temata_v_rocniku'] = verejna_temata(context["rocnik"]) | 		context['vysledkovka'] = True | ||||||
| 		# FIXME: opravit vylistování témat v ročníku | 		context['cisla_s_neverejnymi'] = cisla_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) | ||||||
| 
 | 
 | ||||||
| 		return context | 		return context | ||||||
| 
 | 
 | ||||||
|  | @ -637,29 +575,36 @@ class RocnikView(generic.DetailView): | ||||||
| class ProblemView(generic.DetailView): | class ProblemView(generic.DetailView): | ||||||
| 	model = Problem | 	model = Problem | ||||||
| 
 | 
 | ||||||
| 	def _je_clanek(self, problem): | 	# Používáme funkci, protože přímo template_name neumí mít v přiřazení dost logiky. Ledaže by se to udělalo polymorfně... | ||||||
| 		return problem.typ in [Problem.TYP_ORG_CLANEK, Problem.TYP_RES_CLANEK] |  | ||||||
| 
 |  | ||||||
| 	def get_template_names(self, **kwargs): | 	def get_template_names(self, **kwargs): | ||||||
| 		context = super(ProblemView, self).get_context_data(**kwargs) | 		# FIXME: Switch podle typu není hezký, ale nechtělo se mi to přepisovat celé. Správně by se tohle mělo řešit polymorfismem. | ||||||
| 		return ['seminar/archiv/problem_' + ('clanek.html' if self._je_clanek(context['problem']) else 'uloha_tema.html')] | 		spravne_templaty = { | ||||||
|  | 				s.Uloha: "uloha", | ||||||
|  | 				s.Tema: "tema", | ||||||
|  | 				s.Konfera: "konfera", | ||||||
|  | 				s.Clanek: "clanek", | ||||||
|  | 				} | ||||||
|  | 		context = super().get_context_data(**kwargs) | ||||||
|  | 		return ['seminar/archiv/problem_' + spravne_templaty[context['object'].__class__]  + '.html'] | ||||||
| 
 | 
 | ||||||
| 	def get_context_data(self, **kwargs): | 	def get_context_data(self, **kwargs): | ||||||
| 		context = super(ProblemView, self).get_context_data(**kwargs) | 		context = super().get_context_data(**kwargs) | ||||||
| 		if not context['problem'].verejne() and not self.request.user.is_staff: | 		# Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče. | ||||||
|  | 		if not context['object'].verejne() and not self.request.user.is_staff: | ||||||
| 			raise PermissionDenied() | 			raise PermissionDenied() | ||||||
| 		if context['problem'].typ == Problem.TYP_RES_CLANEK: | 		if isinstance(context['object'], Clanek): | ||||||
| 			context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni') | 			context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni') | ||||||
| 		return context | 		return context | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RadekVysledkovky(object): | class RadekVysledkovkyCisla(object): | ||||||
| 	"""Obsahuje věci, které se hodí vědět při konstruování výsledkovky. | 	"""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).""" | 	Umožňuje snazší práci v templatu (lepší, než seznam).""" | ||||||
| 
 | 
 | ||||||
| 	def __init__(self, poradi, resitel, body_problemy_sezn,  | 	def __init__(self, poradi, resitel, body_problemy_sezn,  | ||||||
| 				body_cislo, body_rocnik, body_odjakziva): | 				body_cislo, body_rocnik, body_odjakziva, rok): | ||||||
| 		self.resitel = resitel | 		self.resitel = resitel | ||||||
|  | 		self.rocnik_resitele = resitel.rocnik(rok) | ||||||
| 		self.body_cislo = body_cislo | 		self.body_cislo = body_cislo | ||||||
| 		self.body_rocnik = body_rocnik | 		self.body_rocnik = body_rocnik | ||||||
| 		self.body_celkem_odjakziva = body_odjakziva | 		self.body_celkem_odjakziva = body_odjakziva | ||||||
|  | @ -674,36 +619,39 @@ def pricti_body(slovnik, resitel, body): | ||||||
| 	# daného řešitele, předěláme na 0 | 	# daného řešitele, předěláme na 0 | ||||||
| 	# (v dalším kroku přičteme reálný počet bodů), | 	# (v dalším kroku přičteme reálný počet bodů), | ||||||
| 	# rozlišujeme tím mezi 0 a neodevzdaným řešením | 	# rozlišujeme tím mezi 0 a neodevzdaným řešením | ||||||
| 	if slovnik[str(resitel.id)] == "": | 	if slovnik[resitel.id] == "": | ||||||
| 		slovnik[str(resitel.id)] = 0 | 		slovnik[resitel.id] = 0 | ||||||
| 	 | 	 | ||||||
| 	slovnik[str(resitel.id)] += body | 	slovnik[resitel.id] += body | ||||||
| 
 | 
 | ||||||
| def secti_body_za_rocnik(cislo, aktivni_resitele): | def secti_body_za_rocnik(rocnik, aktivni_resitele): | ||||||
| 	# spočítáme všem řešitelům jejich body za ročník | 	# 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) | 	resitel_rocnikbody_slov = body_resitelu_za_rocnik(rocnik, aktivni_resitele) | ||||||
| 	# zeptáme se na dvojice (řešitel, body) za ročník a setřídíme sestupně | 	# 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(), | 	resitel_rocnikbody_sezn = sorted(resitel_rocnikbody_slov.items(), | ||||||
| 					key = lambda x: x[1], reverse = True) | 					key = lambda x: x[1], reverse = True) | ||||||
| 	return resitel_rocnikbody_sezn | 	return resitel_rocnikbody_sezn | ||||||
| 
 | 
 | ||||||
| # spočítá u řešitelů body za číslo a za jednotlivé hlavní problémy (témata) | # 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): | 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é | 	# 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 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ů) | 	# pro jednotlivé řešitele (slovník slovníků hlavních problémů) | ||||||
|  | 	if hlavni_problemy is None: | ||||||
|  | 		hlavni_problemy = hlavni_problemy_cisla(cislo) | ||||||
|  | 
 | ||||||
| 	hlavni_problemy_slovnik = {} | 	hlavni_problemy_slovnik = {} | ||||||
| 	for hp in hlavni_problemy: | 	for hp in hlavni_problemy: | ||||||
| 		hlavni_problemy_slovnik[str(hp.id)] = {} | 		hlavni_problemy_slovnik[hp.id] = {} | ||||||
| 
 | 
 | ||||||
| 	# zakládání prázdných záznamů pro řešitele | 	# zakládání prázdných záznamů pro řešitele | ||||||
| 	cislobody = {} | 	cislobody = {} | ||||||
| 	for ar in aktivni_resitele: | 	for ar in aktivni_resitele: | ||||||
| 		# řešitele převedeme na řetězec pomocí unikátního id | 		# řešitele převedeme na řetězec pomocí unikátního id | ||||||
| 		cislobody[str(ar.id)] = "" | 		cislobody[ar.id] = "" | ||||||
| 		for hp in hlavni_problemy: | 		for hp in hlavni_problemy: | ||||||
| 			slovnik = hlavni_problemy_slovnik[str(hp.id)] | 			slovnik = hlavni_problemy_slovnik[hp.id] | ||||||
| 			slovnik[str(ar.id)] = "" | 			slovnik[ar.id] = "" | ||||||
| 	 | 	 | ||||||
| 	# vezmeme všechna řešení s body do daného čísla | 	# vezmeme všechna řešení s body do daného čísla | ||||||
| 	reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'resitele',  | 	reseni_do_cisla = Reseni.objects.prefetch_related('problem', 'resitele',  | ||||||
|  | @ -716,7 +664,7 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy): | ||||||
| 		# řešení může řešit více problémů | 		# řešení může řešit více problémů | ||||||
| 		for prob in list(reseni.problem.all()): | 		for prob in list(reseni.problem.all()): | ||||||
| 			nadproblem = hlavni_problem(prob) | 			nadproblem = hlavni_problem(prob) | ||||||
| 			nadproblem_slovnik = hlavni_problemy_slovnik[str(nadproblem.id)] | 			nadproblem_slovnik = hlavni_problemy_slovnik[nadproblem.id] | ||||||
| 			 | 			 | ||||||
| 			# a mít více hodnocení | 			# a mít více hodnocení | ||||||
| 			for hodn in list(reseni.hodnoceni_set.all()): | 			for hodn in list(reseni.hodnoceni_set.all()): | ||||||
|  | @ -728,13 +676,11 @@ def secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy): | ||||||
| 					pricti_body(nadproblem_slovnik, resitel, body) | 					pricti_body(nadproblem_slovnik, resitel, body) | ||||||
| 	return hlavni_problemy_slovnik, cislobody | 	return hlavni_problemy_slovnik, cislobody | ||||||
| 
 | 
 | ||||||
| 
 | def vysledkovka_cisla(cislo, context=None): | ||||||
| def spocti_vysledkovku_cisla(cislo, context=None): |  | ||||||
| 	if context is None: | 	if context is None: | ||||||
| 		context = {} | 		context = {} | ||||||
| 	 | 	 | ||||||
| 	hlavni_problemy = hlavni_problemy_cisla(cislo) | 	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 | 	## 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í  | 	# 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 | 	# u alespoň jedné hodnoty něco jiného než NULL | ||||||
|  | @ -747,10 +693,10 @@ def spocti_vysledkovku_cisla(cislo, context=None): | ||||||
| 	hlavni_problemy_slovnik, cislobody = secti_body_za_cislo(cislo, aktivni_resitele, hlavni_problemy) | 	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ě | 	# 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) | 	resitel_rocnikbody_sezn = secti_body_za_rocnik(cislo.rocnik, aktivni_resitele) | ||||||
| 
 | 
 | ||||||
| 	# získáme body odjakživa | 	# získáme body odjakživa | ||||||
| 	resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik.druhy_rok(),  | 	resitel_odjakzivabody_slov = body_resitelu_odjakziva(cislo.rocnik,  | ||||||
| 								aktivni_resitele) | 								aktivni_resitele) | ||||||
| 
 | 
 | ||||||
| 	# řešitelé setřídění podle bodů za číslo sestupně | 	# řešitelé setřídění podle bodů za číslo sestupně | ||||||
|  | @ -768,22 +714,22 @@ def spocti_vysledkovku_cisla(cislo, context=None): | ||||||
| 		# získáme seznam bodů za problémy pro daného řešitele | 		# získáme seznam bodů za problémy pro daného řešitele | ||||||
| 		problemy = [] 		 | 		problemy = [] 		 | ||||||
| 		for hp in hlavni_problemy: | 		for hp in hlavni_problemy: | ||||||
| 			problemy.append(hlavni_problemy_slovnik[str(hp.id)][ar_id]) | 			problemy.append(hlavni_problemy_slovnik[hp.id][ar_id]) | ||||||
| 		# vytáhneme informace pro daného řešitele | 		# vytáhneme informace pro daného řešitele | ||||||
| 		radek = RadekVysledkovky( | 		radek = RadekVysledkovkyCisla( | ||||||
| 			poradi[i], # pořadí | 			poradi[i], # pořadí | ||||||
| 			Resitel.objects.get(id=ar_id), # řešitel (z id) | 			Resitel.objects.get(id=ar_id), # řešitel (z id) | ||||||
| 			problemy, # seznam bodů za hlavní problémy čísla | 			problemy, # seznam bodů za hlavní problémy čísla | ||||||
| 			cislobody[ar_id], # body za číslo | 			cislobody[ar_id], # body za číslo | ||||||
| 			setrizeni_resitele_body[i], # body za ročník (spočítané výše s pořadím) | 			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 | 			resitel_odjakzivabody_slov[ar_id], # body odjakživa | ||||||
|  | 			cislo.rocnik) # ročník semináře pro zjištění ročníku řešitele | ||||||
| 		print("{}: body za problémy - {}, číslobody - {}, ročníkbody - {}, odjakživabody - {}".format(radek.resitel,  | 		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)) | 			radek.body_problemy_sezn, radek.body_cislo, radek.body_rocnik, radek.body_celkem_odjakziva)) | ||||||
| 		radky_vysledkovky.append(radek) | 		radky_vysledkovky.append(radek) | ||||||
| 		print("Přikládám {}-tý řádek.".format(i)) | 		print("Přikládám {}-tý řádek.".format(i)) | ||||||
| 		i += 1 | 		i += 1 | ||||||
| 
 | 
 | ||||||
| 	print("Následuje předávání do kontextu.") |  | ||||||
| 	# vytahané informace předáváme do kontextu | 	# vytahané informace předáváme do kontextu | ||||||
| 	context['cislo'] = cislo | 	context['cislo'] = cislo | ||||||
| 	context['radky_vysledkovky'] = radky_vysledkovky | 	context['radky_vysledkovky'] = radky_vysledkovky | ||||||
|  | @ -817,45 +763,8 @@ class CisloView(generic.DetailView): | ||||||
| 
 | 
 | ||||||
| 		cislo = context['cislo'] | 		cislo = context['cislo'] | ||||||
| 		# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky | 		# vrátíme context (aktuálně obsahuje jen věci ohledně výsledkovky | ||||||
| 		return spocti_vysledkovku_cisla(cislo, context) | 		return vysledkovka_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 |  | ||||||
| #		problem_index = {} |  | ||||||
| #		for i in range(len(problemy)): |  | ||||||
| #			#umoznuje zjistit index podle id problemu |  | ||||||
| # |  | ||||||
| #		vysledky_resitele = {} |  | ||||||
| #		vysledkovka = [] |  | ||||||
| # |  | ||||||
| #		# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině |  | ||||||
| #		for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky): |  | ||||||
| #			v.poradi = poradi |  | ||||||
| #			v.body_celkem_rocnik = v.body |  | ||||||
| #			v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body |  | ||||||
| #			v.resitel.rocnik = v.resitel.rocnik(v.cislo.rocnik) |  | ||||||
| # |  | ||||||
| #			# je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil |  | ||||||
| #			v.body_ulohy = [''] * len(problemy) |  | ||||||
| # |  | ||||||
| #			v.titul = v.resitel.get_titul(v.body_celkem_odjakziva) |  | ||||||
| # |  | ||||||
| #			body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo']) |  | ||||||
| #			v.body_cislo = body_cislo_q[0].body if body_cislo_q else 0 |  | ||||||
| # |  | ||||||
| #			vysledkovka.append(v) |  | ||||||
| # |  | ||||||
| #			# připravíme si odkaz na řádek, abychom do něj mohli doplnit body za jednotlivé úlohy |  | ||||||
| #			vysledky_resitele[v.resitel.id] = v |  | ||||||
| # |  | ||||||
| #		# za každé řešení doplníme k příslušnému řešiteli a úloze body |  | ||||||
| #		for r in reseni: |  | ||||||
| #			vysledky_resitele[r.resitel.id].body_ulohy[problem_index[r.problem.id]] = r.body |  | ||||||
| # |  | ||||||
| #		context['vysledkovka'] = vysledkovka |  | ||||||
| #		context['problemy'] = problemy |  | ||||||
| #		context['v_cisle_zadane'] = v_cisle_zadane |  | ||||||
| #		context['resene_problemy'] = resene_problemy |  | ||||||
| 
 | 
 | ||||||
| class ArchivTemataView(generic.ListView): | class ArchivTemataView(generic.ListView): | ||||||
| 	model = Problem | 	model = Problem | ||||||
|  | @ -864,25 +773,24 @@ class ArchivTemataView(generic.ListView): | ||||||
| 
 | 
 | ||||||
| ### Generovani vysledkovky | ### Generovani vysledkovky | ||||||
| 
 | 
 | ||||||
| #class CisloVysledkovkaView(CisloView):i | class CisloVysledkovkaView(CisloView): | ||||||
| #	poradi | titul. jmeno prijmeni | ulohy | za cislo | celkem | odjakziva | 	"View vytvořené pro stránku zobrazující výsledkovku čísla v TeXu." | ||||||
| # | 
 | ||||||
| # | 	model = Cislo | ||||||
| # | 	template_name = 'seminar/archiv/cislo_vysledkovka.tex' | ||||||
| #	model = Cislo | 	#content_type = 'application/x-tex; charset=UTF8' | ||||||
| #	template_name = 'seminar/archiv/cislo_vysledkovka.tex' | 	#umozni rovnou stahnout TeXovsky dokument | ||||||
| #	#content_type = 'application/x-tex; charset=UTF8' | 	content_type = 'text/plain; charset=UTF8' | ||||||
| #	#umozni rovnou stahnout TeXovsky dokument | 	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani | ||||||
| #	content_type = 'text/plain; charset=UTF8' | 
 | ||||||
| #	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani | class RocnikVysledkovkaView(RocnikView): | ||||||
| # | 	"View vytvořené pro stránku zobrazující výsledkovku ročníku v TeXu." | ||||||
| #class RocnikVysledkovkaView(RocnikView): | 	model = Rocnik | ||||||
| #	model = Rocnik | 	template_name = 'seminar/archiv/rocnik_vysledkovka.tex' | ||||||
| #	template_name = 'seminar/archiv/rocnik_vysledkovka.tex' | 	#content_type = 'application/x-tex; charset=UTF8' | ||||||
| #	#content_type = 'application/x-tex; charset=UTF8' | 	#umozni rovnou stahnout TeXovsky dokument | ||||||
| #	#umozni rovnou stahnout TeXovsky dokument | 	content_type = 'text/plain; charset=UTF8' | ||||||
| #	content_type = 'text/plain; charset=UTF8' | 	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani | ||||||
| #	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani |  | ||||||
| 
 | 
 | ||||||
| ### Generovani obalek | ### Generovani obalek | ||||||
| class CisloObalkyStruct: | class CisloObalkyStruct: | ||||||
|  | @ -961,30 +869,31 @@ def oldObalkovaniView(request, rocnik, cislo): | ||||||
| 
 | 
 | ||||||
| ### Tituly | ### Tituly | ||||||
| 
 | 
 | ||||||
| # TODO udelat neco jako get_objects_or_404 | def TitulyView(request, rocnik, cislo): | ||||||
| # FIXME: prepsat, aby nepouzivalo VysledkyK... | 	rocnik_obj = Rocnik.objects.get(rocnik = rocnik) | ||||||
| #def TitulyView(request, rocnik, cislo): | 	resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok) | ||||||
| #	rocnik_obj = Rocnik.objects.get(rocnik = rocnik) | 	cislo_obj = Cislo.objects.get(rocnik = rocnik_obj, poradi = cislo) | ||||||
| #	resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok) | 
 | ||||||
| #	cislo_obj = Cislo.objects.get(rocnik = rocnik_obj, cislo = cislo) | 	asciijmena = [] | ||||||
| # | 	jmenovci = False # detekuje, zda jsou dva řešitelé jmenovci (modulo nabodeníčka), pokud ano, vrátí se jako true | ||||||
| #	asciijmena = [] | 	slovnik_s_body = body_resitelu_odjakziva(rocnik_obj, resitele) | ||||||
| #	broken = False | 
 | ||||||
| # | 	for resitel in resitele: | ||||||
| #	for resitel in resitele: | 		resitel.titul = resitel.get_titul(slovnik_s_body[resitel.id]) | ||||||
| #		try: | 		jmeno = resitel.osoba.jmeno+resitel.osoba.prijmeni | ||||||
| #			vys = VysledkyKCisluOdjakziva.objects.get(resitel = resitel, cislo = cislo_obj) | 		# převedeme jména a příjmení řešitelů do ASCII | ||||||
| #			body = vys.body | 		ascii_jmeno_bytes = unicodedata.normalize('NFKD', jmeno).encode("ascii","ignore") | ||||||
| #		except ObjectDoesNotExist: | 		# vrátí se byte string, převedeme na standardní string | ||||||
| #			body = 0 | 		ascii_jmeno_divnoznaky = str(ascii_jmeno_bytes, "utf-8", "ignore").replace(" ","") | ||||||
| #		resitel.titul = resitel.get_titul(body) | 		resitel.ascii = ''.join(a for a in ascii_jmeno_divnoznaky if a.isalnum()) | ||||||
| #		resitel.ascii = unicodedata.normalize('NFKD',resitel.jmeno+resitel.prijmeni).encode("ascii","ignore").replace(" ","") | 		if resitel.ascii not in asciijmena: | ||||||
| #		if resitel.ascii not in asciijmena: | 			asciijmena.append(resitel.ascii) | ||||||
| #			asciijmena.append(resitel.ascii) | 		else: | ||||||
| #		else: | 			jmenovci = True | ||||||
| #			broken = True | 	 | ||||||
| # | 	return render(request, 'seminar/archiv/tituly.tex', | ||||||
| #	return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken},content_type="text/plain") | 		{'resitele': resitele,'jmenovci':jmenovci},content_type="text/plain") | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ### Soustredeni | ### Soustredeni | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Pavel 'LEdoian' Turinsky
						Pavel 'LEdoian' Turinsky