various visual and performance updates

This commit is contained in:
Yannik Schmidt
2020-09-30 07:10:17 +02:00
parent 08d3a5ae1b
commit 530624ffe8
10 changed files with 181 additions and 113 deletions

View File

@@ -12,8 +12,9 @@ class Round:
losersParsed = json.loads(losers)
self.startTime = startTime
self.winners = [ player.playerFromDict(wp) for wp in winnersParsed ]
self.losers = [ player.playerFromDict(lp) for lp in losersParsed ]
self.id = int(float(timestamp))
self.winners = [ player.playerFromDict(wp, int(duration)) for wp in winnersParsed ]
self.losers = [ player.playerFromDict(lp, int(duration)) for lp in losersParsed ]
self.winnerSide = winnerSide
self.duration = datetime.timedelta(seconds=int(duration))
@@ -28,10 +29,13 @@ class Round:
else:
self.mapName = "unavailiable"
self.confidence = int(confidence * 100)
if prediction == 0:
self.confidence = (int(confidence * 100) - 50)*2
self.quality = int(150 - self.confidence)
if self.confidence < 50:
self.prediction = "-"
elif prediction == 0:
self.prediction = self.winnerSideString
elif prediction == 1:
self.prediction = self.loserSideString
else:
self.prediction = "Error"
self.prediction = "Error"

View File

@@ -101,8 +101,7 @@ class DatabaseConnection:
cursor.execute("SELECT * FROM players WHERE name LIKE ?", (playerNamePrepared,))
playerRow = cursor.fetchone()
if not playerRow:
conn.close()
return (None, None)
return None
playerInLeaderboard = player.PlayerInLeaderboard(playerRow)
playerInLeaderboard.rank = self.getPlayerRank(playerInLeaderboard)
@@ -127,6 +126,7 @@ class DatabaseConnection:
cursor = self.connRounds.cursor()
cursor.execute('''SELECT * FROM rounds WHERE timestamp between ? and ?
AND duration > 120.0
order by timestamp DESC''', (start.timestamp(), end.timestamp()))
rounds = []
@@ -139,6 +139,14 @@ class DatabaseConnection:
cursorHist = self.connHistorical.cursor()
for p in roundObj.winners + roundObj.losers:
cursorHist.execute('''SELECT count(*) FROM playerHistoricalData
WHERE timestamp < ? AND id = ?''',
(roundObj.startTime.timestamp(), p.playerId))
if(cursorHist.fetchone()[0] < 10):
p.ratingChangeString = "Placements"
continue
cursorHist.execute('''SELECT mu,sima FROM playerHistoricalData
WHERE timestamp < ? AND id = ? LIMIT 1 ''',
(roundObj.startTime.timestamp(), p.playerId))
@@ -154,7 +162,21 @@ class DatabaseConnection:
p.sigma = sigmaPrev
p.muChange = muAfter - muPrev
p.sigmaChange = sigmaAfter - sigmaPrev
p.ratingChangeString = str( ( muAfter-2*sigmaAfter ) - ( muPrev-2*sigmaPrev) )
ratingChange = int( (muAfter-muPrev) - 2*(sigmaAfter-sigmaPrev) )
if(ratingChange < 0):
p.ratingChangeString = "- &nbsp;{:x>5}".format(abs(ratingChange))
else:
p.ratingChangeString = "+ {:x>5}".format(ratingChange)
p.ratingChangeString = p.ratingChangeString.replace("x", "&nbsp;")
roundObj.winnerRatingTotal = sum([p.mu - 2*p.sigma for p in roundObj.winners])
roundObj.losersRatingTotal = sum([p.mu - 2*p.sigma for p in roundObj.losers])
higher = max(roundObj.winnerRatingTotal, roundObj.losersRatingTotal)
lower = min(roundObj.winnerRatingTotal, roundObj.losersRatingTotal)
if higher/lower > 2.1:
roundObj.invalid = "Not rated because of team imbalance."
else:
roundObj.invalid = ""
return roundObj

View File

@@ -1,8 +1,10 @@
#!/usr/bin/python3
import flask
def playerFromDict(d):
return PlayerInLeaderboard([d["id"], d["name"], None, 0, 0, 0, 0])
def playerFromDict(d, duration):
p = PlayerInLeaderboard([d["id"], d["name"], None, 0, 0, 0, 0])
p.participation = min(int(d["active_time"]/duration*100), 100)
return p
class PlayerInLeaderboard:
def __init__(self, dbRow):
@@ -21,10 +23,11 @@ class PlayerInLeaderboard:
self.loses = self.games - self.wins
self.rank = None
self.lastGame = lastGame
self.participation = -1
self.muChange = None
self.sigmaChange = None
self.ratingChangeString = "--"
self.ratingChangeString = "N/A"
# determine winratio #
if self.games == 0:

View File

@@ -34,14 +34,21 @@ def singleRound():
timestamp = flask.request.args.get("id")
if not timestamp:
return ("", 404)
return ("ID Missing", 404)
if not timestamp.endswith(".0"):
timestamp = timestamp + ".0"
db = DatabaseConnection(app.config["DB_PATH"])
r = db.getRoundByTimestamp(timestamp)
if not r:
return ("Round not found", 404)
r = db.calcRatingChanges(r)
if not r:
return ("", 404)
r.winners = sorted(r.winners, key=lambda p: p.participation, reverse=True)
r.losers = sorted(r.losers, key=lambda p: p.participation, reverse=True)
return flask.render_template("single_round.html", r=r)
@app.route("/rounds-by-timestamp")
@@ -53,7 +60,7 @@ def rounds():
end = flask.request.args.get("end")
if not start or not end:
start = datetime.datetime.now() - datetime.timedelta(days=4000)
start = datetime.datetime.now() - datetime.timedelta(days=7)
end = datetime.datetime.now()
else:
start = datetime.datetime.fromtimestamp(start)
@@ -97,15 +104,19 @@ def player():
if histData:
datapoints = histData[playerId]
if datapoints:
tickCounter = 10
for dpk in datapoints.keys():
ratingString = str(int(datapoints[dpk]["mu"]) - 2*int(datapoints[dpk]["sigma"]))
ratingAmored = '"' + ratingString + '"'
csv_ratings += [ratingAmored]
t = datetime.datetime.fromtimestamp(int(float(dpk)))
tString = t.strftime("%m %Y")
tStringAmored = '"' + tString + '"'
csv_month_year += [tStringAmored]
tsMs = str(int(t.timestamp() * 1000))
ratingString = str(int(datapoints[dpk]["mu"]) - 2*int(datapoints[dpk]["sigma"]))
ratingAmored = '{ x : ' + tsMs + ', y : ' + ratingString + '}'
csv_ratings += [ratingAmored]
tickCounter -= 1
if tickCounter <= 0:
tickCounter = 10
csv_month_year += ['new Date({})'.format(tsMs)]
minRating = min(minRating, int(ratingString))
maxRating = max(maxRating, int(ratingString))
@@ -145,13 +156,13 @@ def leaderboard():
if playerName:
playerInLeaderboard = db.findPlayerByName(playerName)
if(playerInLeaderboard.games < 10):
return flask.redirect("/player?id={}".format(playerInLeaderboard.playerId))
rank = playerInLeaderboard.rank
if not playerInLeaderboard:
cannotFindPlayer = flask.Markup("<div class=noPlayerFound>No player of that name</div>")
start = 0
else:
rank = playerInLeaderboard.rank
if(playerInLeaderboard.games < 10):
return flask.redirect("/player?id={}".format(playerInLeaderboard.playerId))
searchName = playerInLeaderboard.name
start = rank - (rank % SEGMENT)

View File

@@ -2,23 +2,9 @@
<html lang="en">
<head>
<title>Leaderboard</title>
<meta name="Description" content="Open Web Leaderboard">
<link rel="shortcut icon" href="/static/defaultFavicon.ico">
<meta name="Description" content="Insurgency Leaderboard">
<script src="static/buttons.js" defer></script>
<!-- needed for @media-css mofiers -->
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link rel="stylesheet" href="/static/bootstrap/fontawesome.css">
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/bootstrap/css/mdb.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/static/site.css">
<script src="/static/bootstrap/js/jquery.js"></script>
<script src="/static/bootstrap/js/popper.js"></script>
<script src="/static/bootstrap/js/bootstrap.js"></script>
<script src="/static/bootstrap/js/mdb.min.js"></script>
{% include "default_head_content.html" %}
</head>
<body>
{% include 'navbar_leaderboard.html' %}

View File

@@ -10,7 +10,10 @@
<!-- left side -->
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
<a class="nav-link" href="/">Leaderboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/rounds">Rounds</a>
</li>
</ul>
</div>

View File

@@ -20,8 +20,11 @@
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item right mr-2">
<a class="nav-link" href="/rounds">Rounds</a>
</li>
<li class="nav-item right">
<input id="getPlayer" type="text" aria-label="search for player"
<input id="getPlayer" type="text" aria-label="search for player" class="mt-1"
placeholder="search player...">
</li>
{{ findPlayer }}

View File

@@ -3,24 +3,7 @@
<head>
<title>Player: {{ player.name }}</title>
<meta name="Description" content="Player: {{ player.name }}">
<link rel="stylesheet" type="text/css" href="/static/site.css">
<link rel="shortcut icon" href="/static/defaultFavicon.ico">
<!-- needed for @media-css mofiers -->
<meta content="width=device-width, initial-scale=1" name="viewport" />
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Bootstrap core CSS -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="static/bootstrap/css/mdb.min.css" rel="stylesheet">
<script src="static/bootstrap/js/jquery.js"></script>
<script src="static/bootstrap/js/popper.js"></script>
<script src="static/bootstrap/js/bootstrap.js"></script>
<script src="static/bootstrap/js/mdb.min.js"></script>
{% include "default_head_content.html" %}
</head>
<body class="bg-special">
{% include 'navbar.html' %}
@@ -66,10 +49,26 @@
scales: {
yAxes: [{
ticks : {
suggestedMin : {{ Y_MIN }},
suggestedMax : {{ Y_MAX }},
min : {{ Y_MIN }},
max : {{ Y_MAX }}
suggestedMin : {{ Y_MIN }},
suggestedMax : {{ Y_MAX }},
min : {{ Y_MIN }},
max : {{ Y_MAX }}
}
}],
xAxes: [{
type: 'time',
distribution: 'series',
time: {
round : false,
unit: "day"
},
ticks : {
autoSkip : true,
source : "labels"
},
gridLines: {
display: false,
offsetGridLines: true
}
}]
},

View File

@@ -3,24 +3,7 @@
<head>
<title>Rounds Played</title>
<meta name="Description" content="Insurgency games played on the AtlantisHQ">
<link rel="stylesheet" type="text/css" href="/static/site.css">
<link rel="shortcut icon" href="/static/defaultFavicon.ico">
<!-- needed for @media-css mofiers -->
<meta content="width=device-width, initial-scale=1" name="viewport" />
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Bootstrap core CSS -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="static/bootstrap/css/mdb.min.css" rel="stylesheet">
<script src="static/bootstrap/js/jquery.js"></script>
<script src="static/bootstrap/js/popper.js"></script>
<script src="static/bootstrap/js/bootstrap.js"></script>
<script src="static/bootstrap/js/mdb.min.js"></script>
{% include "default_head_content.html" %}
</head>
<body class="bg-special">
{% include 'navbar.html' %}
@@ -29,12 +12,13 @@
cellspacing="0" width="100%">
<thead>
<tr>
<th class="th-sm">Map</th>
<th class="th-sm">Winner</th>
<th class="th-sm">Duration</th>
<th class="th-sm">Start Time</th>
<th class="th-sm">Rating System Winner Prediction</th>
<th class="th-sm">Confidence</th>
<th class="th-sm font-weight-bold">Map</th>
<th class="th-sm font-weight-bold">Winner</th>
<th class="th-sm font-weight-bold">Duration</th>
<th class="th-sm font-weight-bold">Start Time</th>
<th class="th-sm font-weight-bold">Winner Prediction</th>
<th class="th-sm font-weight-bold">Prediction confidence</th>
<th class="th-sm font-weight-bold">Game-ID</th>
</tr>
</thead>
<tbody>
@@ -43,14 +27,29 @@
<td>{{ r.mapName }}</td>
<td>{{ r.winnerSideString }}</td>
<td>{{ r.duration }}</td>
<td>{{ r.startTime.strftime('%H:%M %d.%m.%Y') }}</td>
<td>{{ r.prediction }}</td>
<td>{{ r.startTime.strftime('%d.%m.%Y %H:%M') }}</td>
<td
{% if r.winnerSideString == r.prediction %}
style="color: green";
{% elif r.prediction != '-' %}
style="color: red";
{% endif %}
>
{{ r.prediction }}
</td>
<td>{{ r.confidence }}%</td>
<td><a href="/round-info?id={{ r.id }}">{{ r.id }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script defer>
$(document).ready(function () {
$('#tableMain').DataTable();
$('.dataTables_length').addClass('bs-select');
});
</script>
{% include 'footer.html' %}
</body>
</html>

View File

@@ -3,34 +3,72 @@
<head>
<title>Rounds Played</title>
<meta name="Description" content="Insurgency games played on the AtlantisHQ">
<link rel="stylesheet" type="text/css" href="/static/site.css">
<link rel="shortcut icon" href="/static/defaultFavicon.ico">
<!-- needed for @media-css mofiers -->
<meta content="width=device-width, initial-scale=1" name="viewport" />
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Bootstrap core CSS -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="static/bootstrap/css/mdb.min.css" rel="stylesheet">
<script src="static/bootstrap/js/jquery.js"></script>
<script src="static/bootstrap/js/popper.js"></script>
<script src="static/bootstrap/js/bootstrap.js"></script>
<script src="static/bootstrap/js/mdb.min.js"></script>
{% include 'default_head_content.html' %}
</head>
<body class="bg-special">
{% include 'navbar.html' %}
<div class="container mt-3 mb-3" role="main">
{% for p in r.winners %}
<h4>{{ p.name }}{{ p.ratingChangeString }}</h4>
{% endfor %}
{% for p in r.losers %}
<h4>{{ p.name }}{{ p.ratingChangeString }}</h4>
{% endfor %}
<h1>Round {{ r.id }}</h1>
<h4>{{ r.startTime }}</h4>
<h4>Map: {{ r.mapName }}</h4>
<h4>Duration: {{ r.duration }}</h4>
{% if r.invalid %}
<div>
<h5 style="color: red;">{{ r.invalid }}</h5>
</div>
{% endif %}
<hr>
<div class="row">
<div class="col-sm">
<h5>Winners ({{ r.winnerSideString }})</h5>
</div>
<div class="col-sm">
<h5>Losers ({{ r.loserSideString }})</h5>
</div>
</div>
<div class="row">
<div class="col-sm">
{% for p in r.winners %}
<div class="row">
<div class="col-sm" style="overflow: hidden;">
{{ p.name }}
</div>
<div class="col-sm">
{{ p.participation }}%
</div>
<div class="col-sm">
{% if not r.invalid %}
<small style="color: green;">
{{ p.ratingChangeString | safe }}
</small>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<div class="col-sm">
{% for p in r.losers %}
<div class="row">
<div class="col-sm" style="overflow: hidden;">
{{ p.name }}
</div>
<div class="col-sm">
{{ p.participation }}%
</div>
<div class="col-sm">
{% if not r.invalid %}
<small style="color: red;">
{{ p.ratingChangeString | safe }}
</small>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% include 'footer.html' %}
</body>