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' %}
{% block content %}
{% load i18n %}
{% load key_value %}
<div class="row">
<div class="col-sm-12 col-md-9">
<div>
<h4>Challenges Solved by {{ user.username }}</h4>
{% if solves%}
<div class="table table-dark">
<div class="card-body">
<div id="time-chart"></div>
</div>
</div>
<table class="table table-dark">
<thead>
<tr>
@ -46,5 +53,271 @@
</ul>
</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 %}

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 import forms
from ctfs.models import CTF_flags
from ctfs.models import Category, CTF_flags
from ..forms import UserForm,UserProfileInfoForm, UserInfosUpdateForm, UserUpdateForm
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
@ -113,9 +113,35 @@ def edit(request):
@login_required
def profile(request, user_name):
globalLabels= []
globalDatas = []
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')
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.
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}
.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 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}
.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 td, .table-dark th, .table-dark thead th {border: none}