Podium added and working, logo and website of campuses added in campus model #76
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 3.2.11 on 2022-08-18 15:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0012_auto_20220801_2212'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='campus',
|
||||||
|
name='logo',
|
||||||
|
field=models.URLField(default='https://42.fr'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='campus',
|
||||||
|
name='url',
|
||||||
|
field=models.URLField(default='https://42.fr', max_length=100),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.11 on 2022-08-18 15:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0013_auto_20220818_1741'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
Danhia marked this conversation as resolved
|
|||||||
|
model_name='campus',
|
||||||
|
name='logo',
|
||||||
|
field=models.URLField(blank=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='campus',
|
||||||
|
name='url',
|
||||||
|
field=models.URLField(blank=True, max_length=100),
|
||||||
|
),
|
||||||
|
]
|
|
@ -28,6 +28,8 @@ class UserProfileInfo(models.Model):
|
||||||
class Campus(models.Model):
|
class Campus(models.Model):
|
||||||
id = models.IntegerField(primary_key=True, unique=True)
|
id = models.IntegerField(primary_key=True, unique=True)
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
|
url = models.URLField(max_length=100,blank=True)
|
||||||
|
logo = models.URLField(max_length=200,blank=True)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -4,9 +4,7 @@ register = template.Library()
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def get_chall_by_lang(chall, lang):
|
def get_chall_by_lang(chall, lang):
|
||||||
print(chall.slug)
|
|
||||||
filepath = "ctfs/templates/challenges/"+ lang + "/" + chall.slug + ".html"
|
filepath = "ctfs/templates/challenges/"+ lang + "/" + chall.slug + ".html"
|
||||||
print(filepath)
|
|
||||||
try:
|
try:
|
||||||
with open(filepath) as fp:
|
with open(filepath) as fp:
|
||||||
return fp.read()
|
return fp.read()
|
||||||
|
|
|
@ -2,28 +2,61 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-12 ctf-head">
|
||||||
|
<h1>{% trans "42Network Scoreboard" %}</h1>
|
||||||
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div>
|
<div class="row justify-content-md-center justify-content-sm-center">
|
||||||
<h4>Scoreboard</h4>
|
<div class="col-4 col-sm-3 col-md-2 podium podium-two text-center">
|
||||||
<table class="table table-dark">
|
<img src="{{ top3.1.0.logo }}" alt="{{ top3.1.0 }}" width="100%"/>
|
||||||
<thead>
|
<h3>#2 :</h3>
|
||||||
<tr>
|
<p>
|
||||||
<th scope="col">{% trans "Rank" %}</th>
|
Score : {{ top3.1.1 }}
|
||||||
<th scope="col">{% trans "Campus" %}</th>
|
<br>
|
||||||
<th scope="col">{% trans "Score" %}</th>
|
{{ top3.1.0 }}
|
||||||
</tr>
|
</p>
|
||||||
</thead>
|
</div>
|
||||||
<tbody>
|
<div class="col-4 col-sm-3 col-md-2 podium podium-one text-center">
|
||||||
{% for name, score in scores.items %}
|
<img src="{{ top3.0.0.logo }}" alt="{{ top3.0.0 }}" width="100%"/>
|
||||||
|
<h3>#1 : </h3>
|
||||||
|
<p>
|
||||||
|
Score : {{ top3.0.1 }}
|
||||||
|
<br>
|
||||||
|
{{ top3.0.0 }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-4 col-sm-3 col-md-2 podium podium-three text-center">
|
||||||
|
<img src="{{ top3.2.0.logo }}" alt="{{ top3.2.0 }}" width="100%"/>
|
||||||
|
<h3>#3 : </h3>
|
||||||
|
<p>
|
||||||
|
Score : {{ top3.2.1 }}
|
||||||
|
<br>
|
||||||
|
{{ top3.2.0 }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
ix marked this conversation as resolved
Danhia
commented
Did you hardcode the campuses logo for the podium ? Did you hardcode the campuses logo for the podium ?
|
|||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<table class="table table-dark">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{% trans "Rank" %}</th>
|
||||||
|
<th scope="col">{% trans "Campus" %}</th>
|
||||||
|
<th scope="col">{% trans "Score" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for name, score in scores.items %}
|
||||||
|
{% if forloop.counter0 > 2 %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row"># {{ forloop.counter0|add:1 }}</th>
|
<th scope="row"># {{ forloop.counter0|add:1 }}</th>
|
||||||
<th><a href="{% url 'scoreboard:campus' campus=name %}"> {{ name }}</a></th>
|
<th><a href="{% url 'scoreboard:campus' campus=name %}"> {{ name }}</a></th>
|
||||||
<td>{{ score}}</td>
|
<td>{{ score}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
</tbody>
|
{% endfor %}
|
||||||
</table>
|
</tbody>
|
||||||
</div>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -4,43 +4,43 @@
|
||||||
{% load is_member %}
|
{% load is_member %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 ctf-head">
|
<div class="col-12 ctf-head">
|
||||||
<h1>{% trans "Scoreboard" %}</h1>
|
<h1>{% trans "Global Scoreboard" %}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
<table class="table table-dark">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{% trans "Rank" %}</th>
|
||||||
|
<th scope="col">{% trans "Username" %}</th>
|
||||||
|
<th scope="col">{% trans "Website" %}</th>
|
||||||
|
<th scope="col">{% trans "Campus" %}</th>
|
||||||
|
<th scope="col">{% trans "Score" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for s in scores %}
|
||||||
|
{% ismember s.user.userprofileinfo as is_member %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row"># {{ forloop.counter0|add:scores.start_index }}</th>
|
||||||
|
<th><a class="profile_link {{is_member}}" href="{% url 'accounts:profile' user_name=s.user.username %}"> {{ s.user.username }}</a></th>
|
||||||
|
<td>
|
||||||
|
{% if s.user.userprofileinfo.portfolio_site %}
|
||||||
|
<a href="{{ s.user.userprofileinfo.portfolio_site }}" target="_blank">{{ s.user.userprofileinfo.portfolio_site }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if s.user.userprofileinfo.campus %}
|
||||||
|
<a href="{% url 'scoreboard:campus' campus=s.user.userprofileinfo.campus %}">
|
||||||
|
{{ s.user.userprofileinfo.campus }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ s.user.userprofileinfo.score }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div>
|
<div>
|
||||||
<table class="table table-dark">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">{% trans "Rank" %}</th>
|
|
||||||
<th scope="col">{% trans "Username" %}</th>
|
|
||||||
<th scope="col">{% trans "Website" %}</th>
|
|
||||||
<th scope="col">{% trans "Campus" %}</th>
|
|
||||||
<th scope="col">{% trans "Score" %}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for s in scores %}
|
|
||||||
{% ismember s.user.userprofileinfo as is_member %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row"># {{ forloop.counter0|add:scores.start_index }}</th>
|
|
||||||
<th><a class="profile_link {{is_member}}" href="{% url 'accounts:profile' user_name=s.user.username %}"> {{ s.user.username }}</a></th>
|
|
||||||
<td>
|
|
||||||
{% if s.user.userprofileinfo.portfolio_site %}
|
|
||||||
<a href="{{ s.user.userprofileinfo.portfolio_site }}" target="_blank">{{ s.user.userprofileinfo.portfolio_site }}</a>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if s.user.userprofileinfo.campus %}
|
|
||||||
<a href="{% url 'scoreboard:campus' campus=s.user.userprofileinfo.campus %}">
|
|
||||||
{{ s.user.userprofileinfo.campus }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>{{ s.user.userprofileinfo.score }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
<span class="step-links">
|
<span class="step-links">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from accounts.models import UserProfileInfo, Campus
|
from accounts.models import UserProfileInfo, Campus
|
||||||
|
import itertools
|
||||||
|
|
||||||
def scoreboard(request):
|
def scoreboard(request):
|
||||||
scores = UserProfileInfo.objects.filter(score__gt=0).select_related().order_by('-score', 'last_submission_date', 'user__username')
|
scores = UserProfileInfo.objects.filter(score__gt=0).select_related().order_by('-score', 'last_submission_date', 'user__username')
|
||||||
|
@ -19,12 +20,12 @@ def campus(request, campus):
|
||||||
def network(request):
|
def network(request):
|
||||||
campuses = Campus.objects.all()
|
campuses = Campus.objects.all()
|
||||||
scores = {}
|
scores = {}
|
||||||
|
|
||||||
for campus in campuses:
|
for campus in campuses:
|
||||||
users = UserProfileInfo.objects.filter(score__gt=0, campus__name__exact=campus).select_related().order_by('-score', 'last_submission_date', 'user__username')[:10]
|
users = UserProfileInfo.objects.filter(score__gt=0, campus__name__exact=campus).select_related().order_by('-score', 'last_submission_date', 'user__username')[:10]
|
||||||
scores[campus] = sum([u.score for u in users])
|
scores[campus] = sum([u.score for u in users])
|
||||||
|
|
||||||
sorted_scores = {k: v for k, v in sorted(scores.items(), key=lambda item: item[1], reverse=True)}
|
sorted_scores = {k: v for k, v in sorted(scores.items(), key=lambda item: item[1], reverse=True)}
|
||||||
return render(request, 'scoreboard/network.html', {'scores':sorted_scores})
|
top3 = list(itertools.islice(sorted_scores.items(), 3))
|
||||||
|
return render(request, 'scoreboard/network.html', {'scores':sorted_scores, 'top3': top3})
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
|
@ -313,3 +313,20 @@ footer {
|
||||||
color: #a9a9a9;
|
color: #a9a9a9;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.podium{
|
||||||
|
margin-top:80px;
|
||||||
|
margin-bottom:30px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.podium h3 {margin-top:-5%;}
|
||||||
|
.podium img{position:relative;top: -55px}
|
||||||
|
.podium-one{
|
||||||
|
background-color: #313131;
|
||||||
|
height: 25vh;}
|
||||||
|
.podium-two{
|
||||||
|
background-color: #252525;
|
||||||
|
height: 20vh;margin-top:auto;}
|
||||||
|
.podium-three{
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
height: 15vh;margin-top:auto;}
|
|
@ -65,7 +65,7 @@
|
||||||
{% trans "Scoreboard" %}
|
{% trans "Scoreboard" %}
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="{% url 'scoreboard:main' %}">{% trans "Main" %}</a>
|
<a class="dropdown-item" href="{% url 'scoreboard:main' %}">{% trans "Global" %}</a>
|
||||||
<a class="dropdown-item" href="{% url 'scoreboard:network' %}">{% trans "42 Network" %}</a>
|
<a class="dropdown-item" href="{% url 'scoreboard:network' %}">{% trans "42 Network" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue
Maybe you could merge this migration with the last one ?
C'est à dire ?
T'as une migration de création de champs, et une migration de modification de ces même champs, donc tu pourrais juste créer les champs directement avec les bons attributs
So apparently there is a feature in Django to squash migrations so we can worry about it later.
I will merge this PR as I currently really want to have the pretty scoreboard in production.