Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Commit

Permalink
Release 0.5
Browse files Browse the repository at this point in the history
Merge pull request #133 from PhlexPlexico/development
  • Loading branch information
PhlexPlexico authored Sep 6, 2019
2 parents d2f02c6 + a992985 commit 3cd5b75
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 37 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@



This is a web panel meant to be used in conjunction with the [get5](https://github.com/splewis/get5) CS:GO server plugin. It provides a more convenient way of managing matches and match servers.
This is a web panel meant to be used in conjunction with the [get5](https://github.com/splewis/get5) CS:GO server plugin. It provides a more convenient way of managing matches and match servers. **This webpanel is intended for competitive 5v5 leagues and scrims, and nothing more.**

This fork of get5 introduces a few new features that are used within get5 already, but were not originally ported over to the experimental web-panel. I've tried to make the web panel a little bit more secure (storing passwords, etc), and more handy for people to organize matches (Seasons and Leaderboards). Right now it's considered complete as it fits my needs and small-scale application. If you have any feature suggestions, *please create an issue*. It's extremely unlikely I'll put any more work into it, but pull requests are always welcome with features, provided they've been tested and pass CI!

Expand All @@ -29,7 +29,7 @@ Once you do this, the site will send an rcon command to the game server `get5_lo

As the match owner, you will be able to cancel the match. Additionally, on its matchpage there is a dropdown to run admin commands: add players to the teams if a ringer is needed, pause the match, load a match backup, list match backups, and run any rcon command.

Note: when using this web panel, the CS:GO game servers **must** be have both the core get5 plugin and the get5_apistats plugin. This means the server must also be running the [Steamworks](https://forums.alliedmods.net/showthread.php?t=229556) and [SMJansson](https://forums.alliedmods.net/showthread.php?t=184604) extensions, as well as [System2](https://github.com/dordnung/System2/releases) (for automated demo uploads, if you so choose). If you are using the public webpanel, please do not do FTP uploads, as they will not link properly on the web-panel.
Note: when using this web panel, the CS:GO game servers **must** be have both the core get5 plugin and the get5_apistats plugin. This means the server must also be running the [Steamworks](https://forums.alliedmods.net/showthread.php?t=229556) and [SMJansson](https://forums.alliedmods.net/showthread.php?t=184604) extensions, as well as [System2](https://github.com/dordnung/System2/releases) (for automated demo uploads, if you so choose). If you are using the public webpanel, please do not do FTP uploads, as they will not link properly on the web-panel itself, but will still upload to your personal FTP server.

## Screenshots

Expand Down
2 changes: 1 addition & 1 deletion get5/get5_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def create_test_data(self):
db.session.commit()

Match.create(user, team1.id, team2.id, '', '', 1, False,
'Map {MAPNUMBER}', ['de_dust2', 'de_cache', 'de_mirage'], season.id, 'always_knife', 'CT', server.id, 0, 0, None, False)
'Map {MAPNUMBER}', ['de_dust2', 'de_cache', 'de_mirage'], season.id, 'always_knife', 'CT', server.id, 0, 0, None, False, False)
db.session.commit()

vetoBan = Veto.create(1, 'EnvyUs', 'de_dust2', 'ban')
Expand Down
7 changes: 4 additions & 3 deletions get5/leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ def getPlayerLeaderboard(seasonid=None):
lstAllPlayerDict = []
playerValues = PlayerStats.query.all()
matchQuery = Match.query.filter(
Match.season_id == seasonid).with_entities(Match.id)
Match.season_id == seasonid,
Match.cancelled == False).with_entities(Match.id)
res = [int(r[0]) for r in matchQuery]
# Filter through every steam ID
for player in playerValues:
Expand Down Expand Up @@ -134,10 +135,10 @@ def seasonal_leaderboard(seasonid):
def seasonal_player_leaderboard(seasonid):
season = Season.query.get_or_404(seasonid)
playerValues = getPlayerLeaderboard(seasonid)
return render_template('statleaderboard.html', board=playerValues, season=season.name)
return render_template('statleaderboard.html', user=g.user, board=playerValues, season=season.name)


@leaderboard_blueprint.route('/leaderboard/players')
def player_leaderboard():
playerValues = getPlayerLeaderboard()
return render_template('statleaderboard.html', board=playerValues)
return render_template('statleaderboard.html', user=g.user, board=playerValues)
11 changes: 7 additions & 4 deletions get5/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ class MatchForm(Form):
private_match = BooleanField('Private Match?',
default=False)

enforce_teams = BooleanField('Enforce Auths on Team',
default=True)

def add_teams(self, user):
if self.team1_id.choices is None:
self.team1_id.choices = []
Expand Down Expand Up @@ -177,7 +180,7 @@ def add_seasons(self):
self.season_selection.choices = []
season_tuples = []
season_tuples.append((0, 'No Season'))
for seasons in Season.query.filter(Season.end_date >= datetime.now()).order_by(-Season.id):
for seasons in Season.query.filter((Season.end_date >= datetime.now()) | (Season.end_date.is_(None))).order_by(-Season.id):
season_tuples.append((seasons.id, seasons.name))
self.season_selection.choices += season_tuples

Expand Down Expand Up @@ -251,7 +254,8 @@ def match_create():
suc, new_auth = steamid.auth_to_steam64(auth)
if suc:
specList.append(new_auth)

if not specList:
specList = None
# End Spectator Feature

match = Match.create(
Expand All @@ -262,7 +266,7 @@ def match_create():
season_id, form.data['side_type'],
form.data['veto_first'], form.data['server_id'],
team1_series_score, team2_series_score, specList,
form.data['private_match'])
form.data['private_match'], form.data['enforce_teams'])

# Save plugin version data if we have it
if json_reply and 'plugin_version' in json_reply:
Expand Down Expand Up @@ -400,7 +404,6 @@ def merge(a, b):
matches = OrderedDict()
match_num = 0
sorted_player_dict = OrderedDict()
app.logger.info('{}'.format(map_stat_list))
for map_stats in map_stat_list:
for player in map_stats.player_stats:
player_dict = merge(
Expand Down
66 changes: 46 additions & 20 deletions get5/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def get_season_name(self):
return self.name

def set_data(self, user, name, start_date, end_date):
self.user_id = user.id
self.user_id = self.user_id
self.name = name
self.start_date = start_date
self.end_date = end_date
Expand Down Expand Up @@ -317,6 +317,9 @@ def get_recent_matches(self, limit=10):
else:
return recent_matches

def get_url(self):
return url_for('season.seasons', seasonid=self.id)

def __repr__(self):
return 'Season(id={}, user_id={}, name={}, start_date={}, end_date={})'.format(
self.id, self.user_id, self.name, self.start_date, self.end_date)
Expand Down Expand Up @@ -372,13 +375,13 @@ class Match(db.Model):
team2_series_score = db.Column(db.Integer, default=0)
spectator_auths = db.Column(db.PickleType)
private_match = db.Column(db.Boolean)

enforce_teams = db.Column(db.Boolean, default=True)
@staticmethod
def create(user, team1_id, team2_id, team1_string, team2_string,
max_maps, skip_veto, title, veto_mappool, season_id,
side_type, veto_first, server_id=None,
team1_series_score=None, team2_series_score=None,
spectator_auths=None, private_match=False):
spectator_auths=None, private_match=False, enforce_teams=True):
rv = Match()
rv.user_id = user.id
rv.team1_id = team1_id
Expand All @@ -402,6 +405,7 @@ def create(user, team1_id, team2_id, team1_string, team2_string,
rv.team2_series_score = team2_series_score
rv.spectator_auths = spectator_auths
rv.private_match = private_match
rv.enforce_teams = enforce_teams
db.session.add(rv)
return rv

Expand Down Expand Up @@ -457,6 +461,21 @@ def live(self):
def get_server(self):
return GameServer.query.filter_by(id=self.server_id).first()

def get_start_time(self):
return self.start_time

def get_end_time(self):
return self.end_time

def get_season(self):
if self.season_id:
return Season.query.get(self.season_id)
else:
return None

def get_season_id(self):
return self.season_id

def get_current_score(self):
if self.max_maps == 1:
mapstat = self.map_stats.first()
Expand Down Expand Up @@ -486,6 +505,9 @@ def send_to_server(self):
server.send_rcon_command(
'get5_web_api_key ' + self.api_key)

# ***HACK FIX TO ENSURE CHECK_AUTHS WORKS AS INTENDED***
server.send_rcon_command('map de_dust2')

if loadmatch_response: # There should be no response
return False

Expand Down Expand Up @@ -564,10 +586,9 @@ def add_if(key, value):
add_team_data('team2', self.team2_id, self.team2_string)

d['cvars'] = {}

d['cvars']['get5_web_api_url'] = url_for(
'home', _external=True, _scheme='http')

'home', _external=True, _scheme='http')
d['cvars']['get5_check_auths'] = "1" if self.enforce_teams else "0"
# Add in for spectators modification.
d['min_spectators_to_ready'] = 0

Expand All @@ -583,6 +604,9 @@ def add_if(key, value):
for spectator in self.spectator_auths:
d['spectators']["players"].append(spectator)

if not d['spectators']['players']:
d['spectators'] = None

if self.veto_mappool:
d['maplist'] = []
for map in self.veto_mappool.split():
Expand Down Expand Up @@ -675,20 +699,22 @@ def get_player_name(self):
return get_steam_name(self.steam_id)

def get_rating(self):
AverageKPR = 0.679
AverageSPR = 0.317
AverageRMK = 1.277
KillRating = float(self.kills) / float(self.roundsplayed) / AverageKPR
SurvivalRating = float(self.roundsplayed -
self.deaths) / self.roundsplayed / AverageSPR
killcount = float(self.k1 + 4 * self.k2 + 9 *
self.k3 + 16 * self.k4 + 25 * self.k5)
RoundsWithMultipleKillsRating = killcount / \
self.roundsplayed / AverageRMK
rating = (KillRating + 0.7 * SurvivalRating +
RoundsWithMultipleKillsRating) / 2.7
return rating

try:
AverageKPR = 0.679
AverageSPR = 0.317
AverageRMK = 1.277
KillRating = float(self.kills) / float(self.roundsplayed) / AverageKPR
SurvivalRating = float(self.roundsplayed -
self.deaths) / self.roundsplayed / AverageSPR
killcount = float(self.k1 + 4 * self.k2 + 9 *
self.k3 + 16 * self.k4 + 25 * self.k5)
RoundsWithMultipleKillsRating = killcount / \
self.roundsplayed / AverageRMK
rating = (KillRating + 0.7 * SurvivalRating +
RoundsWithMultipleKillsRating) / 2.7
return rating
except ZeroDivisionError:
return 0
def get_kdr(self):
if self.deaths == 0:
return float(self.kills)
Expand Down
4 changes: 2 additions & 2 deletions get5/season.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ class SeasonForm(Form):
@season_blueprint.route('/seasons')
def seasons():
seasons = Season.query.order_by(-Season.id)
seasoned_matches = Match.query.filter(Match.season_id.isnot(None), Match.cancelled==False)
return render_template('seasons.html', user=g.user, seasons=seasons,
my_seasons=False, all_seasons=True)
my_seasons=False, matches=seasoned_matches, all_seasons=True)


@season_blueprint.route('/season/create', methods=['GET', 'POST'])
Expand Down Expand Up @@ -94,7 +95,6 @@ def seasons_user(userid):
user = User.query.get_or_404(userid)
seasons = user.seasons.order_by(-Season.id)
is_owner = (g.user is not None) and (userid == g.user.id)
app.logger.info('User is {}'.format(g.user))
return render_template('seasons.html', user=g.user, seasons=seasons,
my_seasons=is_owner, all_matches=False, season_owner=user)

Expand Down
9 changes: 9 additions & 0 deletions get5/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@
<a class="dropdown-item" id="season_create" href="/season/create">Create a Season</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" id="Preview" href="#" role="button" aria-haspopup="true" aria-expanded="false">
Leaderboards
</a>
<div class="dropdown-menu" aria-labelledby="Preview">
<a class="dropdown-item" id="leaderboard" href="/leaderboard">Team Leaderboard</a><br/>
<a class="dropdown-item" id="player_leaderboard" href="/leaderboard/players">Individual Leaderboard</a><br/>
</div>
</li>
<li><a href="/logout">Logout</a></li>

{% endif %}
Expand Down
7 changes: 7 additions & 0 deletions get5/templates/match_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@
</div>
</div>

<div class="form-group">
{{ form.enforce_teams.label(class="col-sm-2 control-label") }}
<div class="col-sm-4">
{{ form.enforce_teams(class="form-control input-sm") }}
</div>
</div>

<div class="form-group">
{{ form.spectator_string.label(class="col-sm-2 control-label") }}
<div class="col-sm-4">
Expand Down
18 changes: 16 additions & 2 deletions get5/templates/matches.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ <h1>
<th>Team 1</th>
<th>Team 2</th>
<th>Status</th>
<th>Start Time</th>
<th>End Time</th>
{% if my_matches %}
<th>Server</th>
<th></th>
{% else %}
<th>Owner</th>
{% endif %}
<th>Season</th>
</tr>
</thead>
<tbody>
Expand All @@ -51,7 +54,14 @@ <h1>
<td>
{{ match.get_status_string() }}
</td>

{% if match.live() or match.finished() %}
<td>
{{ match.get_start_time() }}
</td>
<td>
{{ match.get_end_time() }}
</td>
{% endif %}
{% if my_matches %}
<td>{% if match.get_server() is not none %} {{ match.get_server().get_display() }} {% endif %}</td>
<td>
Expand All @@ -62,7 +72,11 @@ <h1>
{% else %}
<td> <a href="{{ match.get_user().get_url() }}"> {{ match.get_user().name }} </a> </td>
{% endif %}

{% if match.get_season() %}
<td> <a href="/season/{{ match.get_season_id() }}"> {{ match.get_season().name }} </a> </td>
{% else %}
<td> <a> N/A </a> </td>
{%endif%}
</tr>
{% endfor %}

Expand Down
14 changes: 11 additions & 3 deletions get5/templates/seasons.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{% extends "layout.html" %}

{% block content %}
<div id="content">

Expand All @@ -20,7 +19,9 @@ <h1>
<th>Season Name</th>
<th>Start Date</th>
<th>End Date</th>
<th>Leaderboard</th>
<th>Total Matches</th>
<th>Team Leaderboard</th>
<th>Individual Leaderboard</th>
</tr>
</thead>
<tbody>
Expand All @@ -39,10 +40,17 @@ <h1>
{{ season.end_date.strftime('%Y-%m-%d') }}
{% endif %}
</td>


<td>{{ matches | selectattr('season_id', 'equalto', season.id) | map(attribute='season_id') | list | length }}</td>

<td>
<a href="/leaderboard/season/{{season.id}}"> Leaderboard</a>
<a href="/leaderboard/season/{{season.id}}">Team Leaderboard</a>
</td>

<td>
<a href="/leaderboard/season/{{season.id}}/players">Indvidual Leaderboard</a>
</td>

{% if season.can_edit(user) %}
<td>
Expand Down
21 changes: 21 additions & 0 deletions migrations/versions/254a3741efe3_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Adding back in enforcement of teams.
Revision ID: 254a3741efe3
Revises: f5efc36b3cc9
Create Date: 2019-08-28 21:59:22.176239
"""

# revision identifiers, used by Alembic.
revision = '254a3741efe3'
down_revision = 'f5efc36b3cc9'

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

def upgrade():
op.add_column('match', sa.Column('enforce_teams', sa.Boolean(), nullable=True))

def downgrade():
op.drop_column('match', 'enforce_teams')

0 comments on commit 3cd5b75

Please sign in to comment.