Merge branch 'graph' into main
This commit is contained in:
commit
8a203161ed
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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(',','.')
|
|
@ -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):
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Reference in New Issue