Skip to content

Commit

Permalink
Merge pull request #111 from zediious/gameservers-charts
Browse files Browse the repository at this point in the history
Gameservers charts
  • Loading branch information
zediious authored Nov 9, 2023
2 parents 4be3639 + d1d7a99 commit 249c496
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 8 deletions.
12 changes: 7 additions & 5 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dependencies:
- python=3.11.5
- pip
- pip:
- django==4.2.5
- django==4.2.7
- requests==2.31.0
- argon2-cffi==21.3.0
- argon2-cffi-bindings==21.2.0
Expand All @@ -14,18 +14,20 @@ dependencies:
- django-bootstrap5==23.3
- dnspython==2.4.2
- mcstatus==11.0.1
- pillow==10.0.1
- pillow==10.1.0
- prompt-toolkit==3.0.39
- wcwidth==0.2.7
- wcwidth==0.2.9
- daphne==4.0.0
- whitenoise==6.5.0
- whitenoise==6.6.0
- django-tinymce==3.6.1
- django-js-asset==2.1.0
- python-dotenv==1.0.0
- mysqlclient==2.1.1
- django-jazzmin==2.6.0
- discord.py==2.3.2
- django-ranged-response==0.2.0
- django-simple-captcha==0.5.18
- django-simple-captcha==0.5.20
- six==1.16.0
- django-resized==1.0.2
- pandas==2.1.2
- plotly==5.18.0
34 changes: 34 additions & 0 deletions raptorWeb/gameservers/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django import forms

from raptorWeb.gameservers.models import Server

class StatisticFilterForm(forms.Form):
start = forms.DateTimeField(
required=False,
widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}))

end = forms.DateTimeField(
required=False,
widget=forms.DateTimeInput(attrs={'type': 'datetime-local'}))

server = forms.ModelChoiceField(
queryset=Server.objects.filter(archived=False),
empty_label="Choose a Server")

class StatisticFilterFormFireFox(forms.Form):
"""
Firefox does not support the datetime-local HTML5 widget
and as such needs to be supplied with only a date widget.
"""
start = forms.DateTimeField(
required=False,
widget=forms.DateTimeInput(attrs={'type': 'date'}))

end = forms.DateTimeField(
required=False,
widget=forms.DateTimeInput(attrs={'type': 'date'}))

server = forms.ModelChoiceField(
queryset=Server.objects.filter(archived=False),
to_field_name='modpack_name',
empty_label="Choose a Server")
4 changes: 4 additions & 0 deletions raptorWeb/gameservers/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
path('html/server_banned_items_poll/', views.Server_List_Base.as_view(template_name='gameservers/server_list_banneditems.html'), name="server_banned_items_poll"),
path('html/server_voting_poll/', views.Server_List_Base.as_view(template_name='gameservers/server_list_voting.html'), name="server_voting_poll"),
path('html/server_announcements_poll/', views.Server_List_Base.as_view(template_name='gameservers/server_list_announcements.html'), name="server_announcements_poll"),
# Forms
path('html/forms/statistic_filter', views.Statistic_Filter_Form.as_view(), name="statistic_filter"),
# Statistics
path('html/statistics/player_counts', views.Player_Count_Statistics.as_view(), name="player_statistics_chart"),
# Command API
path('action/import_server_data/', views.Import_Servers.as_view(), name="action_import_server_data"),
path('action/export_server_data/', views.Export_Servers.as_view(), name="action_export_server_data")
Expand Down
82 changes: 81 additions & 1 deletion raptorWeb/gameservers/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
from os.path import join
from logging import getLogger

from django.views.generic import ListView, TemplateView
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.shortcuts import render
from django.conf import settings

from raptorWeb.gameservers.models import ServerManager, ServerStatistic, Server, Player
from raptorWeb.gameservers.models import ServerManager, ServerStatistic, Server, Player, PlayerCountHistoric
from raptorWeb.gameservers.forms import StatisticFilterForm, StatisticFilterFormFireFox

import plotly.express as plot_express

LOGGER = getLogger('gameservers.views')
GAMESERVERS_TEMPLATE_DIR: str = getattr(settings, 'GAMESERVERS_TEMPLATE_DIR')
SCRAPE_SERVER_ANNOUNCEMENT: bool = getattr(settings, 'SCRAPE_SERVER_ANNOUNCEMENT')
SERVER_PAGINATION_COUNT: int = getattr(settings, 'SERVER_PAGINATION_COUNT')
Expand Down Expand Up @@ -60,6 +68,78 @@ def get(self, request, *args, **kwargs):

else:
return HttpResponseRedirect('/')


class Statistic_Filter_Form(TemplateView):
"""
Return a form to submit server and date filter data
"""
def get(self, request: HttpRequest, *args: tuple, **kwargs: dict) -> HttpResponse:
if 'Firefox' not in str(request.META['HTTP_USER_AGENT']):
return render(request, template_name=join(GAMESERVERS_TEMPLATE_DIR, 'player_statistics_form.html'), context={
'stat_filter_form': StatisticFilterForm()})

return render(request, template_name=join(GAMESERVERS_TEMPLATE_DIR, 'player_statistics_form.html'), context={
'stat_filter_form': StatisticFilterFormFireFox()})


class Player_Count_Statistics(TemplateView):
"""
Return a plotly chart containing PlayerCountHistoric data
"""
def get(self, request: HttpRequest, *args: tuple, **kwargs: dict) -> HttpResponse:
start = request.GET.get('start')
end = request.GET.get('end')
modpack_name = request.GET.get('server')

try:
found_server = Server.objects.get(modpack_name=modpack_name)
except Server.DoesNotExist:
return HttpResponse("<div class='alert bg-danger'>Queried server not found.</div>")

count_data = PlayerCountHistoric.objects.filter(server=found_server)

if (start != '' and end != ''
or start != '' or end != ''):
if start == end and 'T' not in start:
start += 'T00:00'
end += 'T23:59'

if start:
count_data = count_data.filter(
checked_time__gte=start
)

if end:
count_data = count_data.filter(
checked_time__lte=end
)

x_data = [count.checked_time for count in count_data]
y_data = [count.player_count for count in count_data]

if x_data == [] and y_data == []:
return HttpResponse("<div class='alert bg-danger'>No data found for selected time.</div>")

figure = plot_express.line(
x=x_data,
y=y_data,
title="Player Counts over Time",
template='plotly_dark',
labels={'x': "Time of Query", 'y': 'Player Count'}
)

figure.update_layout(title={
'font_size': 22,
'xanchor': 'center',
'x': 0.5
})

chart = figure.to_html()


return render(request, template_name=join(GAMESERVERS_TEMPLATE_DIR, 'player_statistics_chart.html'), context={
"chart": chart})


class Import_Servers(TemplateView):
Expand Down
2 changes: 1 addition & 1 deletion raptorWeb/static/css/raptormc.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion raptorWeb/static/css/raptormc.css.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions raptorWeb/static/css/raptormc.scss
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ body {
font-size: xx-large;
}

#gameservers_chart_rendered {
width: 50%
}

#profile_picture_box {
width: 60px
}
Expand Down Expand Up @@ -241,6 +245,10 @@ body {
font-size: medium;
}

#gameservers_chart_rendered {
width: 85%
}

.pageContent > * {
font-size: small;
}
Expand Down
7 changes: 7 additions & 0 deletions raptorWeb/templates/gameservers/player_statistics_chart.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


<div class="d-flex justify-content-center">
<div id="gameservers_chart_rendered">
{{ chart|safe }}
</div>
</div>
17 changes: 17 additions & 0 deletions raptorWeb/templates/gameservers/player_statistics_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% load django_bootstrap5 %}

<form class="form p-3"
hx-get="{% url 'gameservers:player_statistics_chart'%}"
hx-target='#fetched_chart'
hx-swap='innerHTML'
>

{% csrf_token %}
{{ form.captcha }}
{% bootstrap_form stat_filter_form %}
{% bootstrap_button button_type="submit" content="Filter" %}

</form>

<div id="fetched_chart">
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div id="filter_form"
hx-get="{% url 'gameservers:statistic_filter'%}"
hx-trigger='load'
hx-target='#filter_form'
hx-swap='innerHTML'>
</div>
8 changes: 8 additions & 0 deletions raptorWeb/templates/raptormc/panel/panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

{% block page_actions %}{% endblock %}

{% block sidebar%}
{% include "raptormc/panel/sidebar.html" %}
{% endblock %}

{% block page_content %}

<div class="m-5 mt-4 p-5">
Expand All @@ -31,6 +35,10 @@

</div>
</div>

<div class="m-5 mt-2 p-5 container-flex">
{% include "raptormc/panel/gameservers_statistics.html" %}
</div>
{% endblock %}

{% block extrajs %}
Expand Down
26 changes: 26 additions & 0 deletions raptorWeb/templates/raptormc/panel/sidebar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% load static %}

<aside class="main-sidebar elevation-4 {{ jazzmin_ui.sidebar_classes }}" id="jazzy-sidebar">
<a href="{% url 'admin:index' %}" class="brand-link {{ jazzmin_ui.brand_classes }}" id="jazzy-logo">
<img src="{% static jazzmin_settings.site_logo %}" alt="{{ jazzmin_settings.site_header }} Logo" class="{{ jazzmin_settings.site_logo_classes }} brand-image elevation-3" style="opacity: .8">
<span class="brand-text font-weight-light">{{ jazzmin_settings.site_brand }}</span>
</a>

<div class="sidebar">
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
</div>

<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column {{ jazzmin_ui.sidebar_list_classes }}" data-widget="treeview" role="menu" data-collapsible="false">

<li class="nav-item">
<a href="{% url 'admin:index' %}" class="nav-link">
<i class="nav-icon fas fa-th-large"></i>
<p>Dashboard</p>
</a>
</li>

</ul>
</nav>
</div>
</aside>

0 comments on commit 249c496

Please sign in to comment.