Merge branch 'graph' into main

This commit is contained in:
ix 2021-09-08 04:00:39 +02:00
commit ed928f6f33
6 changed files with 412 additions and 102 deletions

View File

@ -1,11 +1,18 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
{% load i18n %} {% load i18n %}
{% load key_value %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-9"> <div class="col-sm-12 col-md-9">
<div> <div>
<h4>Challenges Solved by {{ user.username }}</h4> <h4>Challenges Solved by {{ user.username }}</h4>
{% if solves%} {% if solves%}
<div class="table table-dark">
<div class="card-body">
<div id="time-chart"></div>
</div>
</div>
<table class="table table-dark"> <table class="table table-dark">
<thead> <thead>
<tr> <tr>
@ -46,5 +53,271 @@
</ul> </ul>
</div> </div>
</div> </div>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script>
Highcharts.theme = {
colors: ['#2b908f', '#90ee7e', '#f45b5b', '#7798BF', '#aaeeee', '#ff0066',
'#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'],
chart: {
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
stops: [
[0, '#1D1D1D'],
[1, '#1D1D1D']
]
},
style: {
fontFamily: '\'Unica One\', sans-serif'
},
plotBorderColor: '#606063'
},
title: {
style: {
color: '#E0E0E3',
textTransform: 'uppercase',
fontSize: '20px'
}
},
subtitle: {
style: {
color: '#E0E0E3',
textTransform: 'uppercase'
}
},
xAxis: {
gridLineColor: '#707073',
labels: {
style: {
color: '#E0E0E3'
}
},
lineColor: '#707073',
minorGridLineColor: '#505053',
tickColor: '#707073',
title: {
style: {
color: '#A0A0A3'
}
}
},
yAxis: {
gridLineColor: '#707073',
labels: {
style: {
color: '#E0E0E3'
}
},
lineColor: '#707073',
minorGridLineColor: '#505053',
tickColor: '#707073',
tickWidth: 1,
title: {
style: {
color: '#A0A0A3'
}
}
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.85)',
style: {
color: '#F0F0F0'
}
},
plotOptions: {
series: {
dataLabels: {
color: '#F0F0F3',
style: {
fontSize: '13px'
}
},
marker: {
lineColor: '#333'
}
},
boxplot: {
fillColor: '#505053'
},
candlestick: {
lineColor: 'white'
},
errorbar: {
color: 'white'
}
},
legend: {
backgroundColor: '#1D1D1D',
itemStyle: {
color: '#E0E0E3'
},
itemHoverStyle: {
color: '#FFF'
},
itemHiddenStyle: {
color: '#606063'
},
title: {
style: {
color: '#C0C0C0'
}
}
},
credits: {
style: {
color: '#666'
}
},
labels: {
style: {
color: '#707073'
}
},
drilldown: {
activeAxisLabelStyle: {
color: '#F0F0F3'
},
activeDataLabelStyle: {
color: '#F0F0F3'
}
},
navigation: {
buttonOptions: {
symbolStroke: '#DDDDDD',
theme: {
fill: '#505053'
}
}
},
// scroll charts
rangeSelector: {
buttonTheme: {
fill: '#505053',
stroke: '#000000',
style: {
color: '#CCC'
},
states: {
hover: {
fill: '#707073',
stroke: '#000000',
style: {
color: 'white'
}
},
select: {
fill: '#000003',
stroke: '#000000',
style: {
color: 'white'
}
}
}
},
inputBoxBorderColor: '#505053',
inputStyle: {
backgroundColor: '#333',
color: 'silver'
},
labelStyle: {
color: 'silver'
}
},
navigator: {
handles: {
backgroundColor: '#666',
borderColor: '#AAA'
},
outlineColor: '#CCC',
maskFill: 'rgba(255,255,255,0.1)',
series: {
color: '#7798BF',
lineColor: '#A6C7ED'
},
xAxis: {
gridLineColor: '#505053'
}
},
scrollbar: {
barBackgroundColor: '#808083',
barBorderColor: '#808083',
buttonArrowColor: '#CCC',
buttonBackgroundColor: '#606063',
buttonBorderColor: '#606063',
rifleColor: '#FFF',
trackBackgroundColor: '#404043',
trackBorderColor: '#404043'
}
};
// Apply the theme
Highcharts.setOptions(Highcharts.theme);
Highcharts.chart('time-chart', {
title: {
text: 'Points earned for each category'
},
yAxis: {
title: {
text: 'Points earned'
}
},
xAxis: {
type: 'datetime',
// Use the date format in the
// labels property of the chart
labels: {
formatter: function() {
return Highcharts.dateFormat('%d.%b %Y',
this.value);
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
pointStart: {{ user.date_joined|timestamp_fromdate }},
series: {
label: {
connectorAllowed: false
},
allowPointSelect: true,
marker: {
enabled: true
}
}
},
series: [
{
name: 'Total',
data: {{ solved|safe }}
},
{% for cat in cats %}
{
name: '{{ cat.name }}',
data: {{ pointDatas|keyvalue:cat.name|safe }},
visible: false,
},
{% endfor %}
],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
</script>
{% endblock %} {% endblock %}

View File

View File

@ -0,0 +1,11 @@
from django import template
register = template.Library()
@register.filter
def keyvalue(dict, key):
return dict[key]
@register.filter
def timestamp_fromdate(date):
return str(date.timestamp() * 1000).replace(',','.')

View File

@ -2,7 +2,7 @@ from django.shortcuts import render, redirect, get_object_or_404
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django import forms from django import forms
from ctfs.models import CTF_flags from ctfs.models import Category, CTF_flags
from ..forms import UserForm,UserProfileInfoForm, UserInfosUpdateForm, UserUpdateForm from ..forms import UserForm,UserProfileInfoForm, UserInfosUpdateForm, UserUpdateForm
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -113,9 +113,35 @@ def edit(request):
@login_required @login_required
def profile(request, user_name): def profile(request, user_name):
globalLabels= []
globalDatas = []
user_obj = get_object_or_404(User, username=user_name) user_obj = get_object_or_404(User, username=user_name)
cats = Category.objects.all()
pointDatas = {}
for cat in cats:
# prepare categories
globalLabels.append(cat.name)
solved_count = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).order_by('-flag_date').count()
globalDatas.append(solved_count)
# get datas
somme = 0
solved = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).order_by('flag_date')
pointDatas[cat.name] = []
pointDatas[cat.name].append([user_obj.date_joined.timestamp() * 1000, 0])
for flag in solved:
somme += flag.ctf.points
pointDatas[cat.name].append([flag.flag_date.timestamp() * 1000, somme])
solves = CTF_flags.objects.filter(user=user_obj).order_by('-flag_date') solves = CTF_flags.objects.filter(user=user_obj).order_by('-flag_date')
return render(request,'accounts/profile.html', {'user':user_obj, 'solves':solves}) solved = []
somme = 0
solved.append([user_obj.date_joined.timestamp() * 1000, 0])
for s in solves.reverse():
somme += s.ctf.points
solved.append([s.flag_date.timestamp() * 1000,somme])
return render(request,'accounts/profile.html', {'user':user_obj, 'solves':solves,'solved':solved,'globalLabels': globalLabels, 'globalDatas': globalDatas, 'pointDatas': pointDatas})
# Create your views here. # Create your views here.
def rank(request, token): def rank(request, token):

View File

@ -17,7 +17,7 @@ pre {background-color: #000; color: #cecece; padding-left: 15px; font-weight: bo
.dropdown-item:hover {background-color: #1D1D1D; color: #FFFFFF} .dropdown-item:hover {background-color: #1D1D1D; color: #FFFFFF}
.flag_link {margin-right: 6px} .flag_link {margin-right: 6px}
.flag_img {margin-top: 10px;width: 28px;border-radius: 100%;} .flag_img {margin-top: 10px;width: 28px;}
.table-dark {background-color: #1D1D1D} .table-dark {background-color: #1D1D1D}
.table-dark td, .table-dark th, .table-dark thead th {border: none} .table-dark td, .table-dark th, .table-dark thead th {border: none}

View File

@ -17,7 +17,7 @@ pre {background-color: #000; color: #cecece; padding-left: 15px; font-weight: bo
.dropdown-item:hover {background-color: #1D1D1D; color: #FFFFFF} .dropdown-item:hover {background-color: #1D1D1D; color: #FFFFFF}
.flag_link {margin-right: 6px} .flag_link {margin-right: 6px}
.flag_img {margin-top: 10px;width: 28px;border-radius: 100%;} .flag_img {margin-top: 10px;width: 28px;}
.table-dark {background-color: #1D1D1D} .table-dark {background-color: #1D1D1D}
.table-dark td, .table-dark th, .table-dark thead th {border: none} .table-dark td, .table-dark th, .table-dark thead th {border: none}