mirror of
https://github.com/FAUSheppy/open-web-leaderboard.git
synced 2025-12-10 08:58:33 +01:00
Compare commits
12 Commits
ese-custom
...
6491afc272
| Author | SHA1 | Date | |
|---|---|---|---|
| 6491afc272 | |||
| 756b24a447 | |||
| 5f7713daaf | |||
| ee14c3fd7e | |||
|
|
c32155fd40 | ||
|
|
defcf5671d | ||
| 2133249947 | |||
| db3d2bb57e | |||
| c5b7963fff | |||
| 23fa7f9862 | |||
| 8f7b1b47ac | |||
| bdd7d9bf01 |
34
.github/workflows/main.yaml
vendored
Normal file
34
.github/workflows/main.yaml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: Container Build for open-web-leaderboard
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "master"
|
||||||
|
schedule:
|
||||||
|
- cron: "0 2 * * 0"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: prod
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Login to Docker Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ${{ secrets.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASS }}
|
||||||
|
-
|
||||||
|
name: open-web-leaderboard
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: true
|
||||||
|
tags: "${{ secrets.REGISTRY }}/atlantishq/open-web-leaderboard:latest"
|
||||||
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
FROM alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache py3-pip
|
||||||
|
RUN python3 -m pip install --no-cache-dir --break-system-packages waitress
|
||||||
|
COPY req.txt .
|
||||||
|
RUN python3 -m pip install --no-cache-dir --break-system-packages -r req.txt
|
||||||
|
|
||||||
|
RUN mkdir /app
|
||||||
|
WORKDIR /app
|
||||||
|
COPY ./ .
|
||||||
|
|
||||||
|
ENTRYPOINT ["waitress-serve"]
|
||||||
|
CMD ["--host", "0.0.0.0", "--port", "5000", "--call", "app:createApp"]
|
||||||
@@ -33,6 +33,7 @@ Players can be blacklisted by name via a *blacklist.json* file in the project ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Adding servers for player count live info
|
# Adding servers for player count live info
|
||||||
|
**THIS FEATURE IS DISABLED BECAUSE py-valve DOES NOT SUPPORT PYTHON>3.9**
|
||||||
Source-Servers can be added via the *servers.json*-file:
|
Source-Servers can be added via the *servers.json*-file:
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|||||||
10
Round.py
10
Round.py
@@ -36,12 +36,12 @@ class Round:
|
|||||||
self.blacklist = True
|
self.blacklist = True
|
||||||
|
|
||||||
|
|
||||||
if winnerSide == 1:
|
if winnerSide == 2:
|
||||||
self.winnerSideString = "Red"
|
self.winnerSideString = "Security"
|
||||||
self.loserSideString = "Blue"
|
self.loserSideString = "Insurgent"
|
||||||
else:
|
else:
|
||||||
self.winnerSideString = "Blue"
|
self.winnerSideString = "Insurgent"
|
||||||
self.loserSideString = "Red"
|
self.loserSideString = "Security"
|
||||||
if mapName:
|
if mapName:
|
||||||
self.mapName = mapName
|
self.mapName = mapName
|
||||||
else:
|
else:
|
||||||
|
|||||||
113
api.py
113
api.py
@@ -1,113 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
import riotwatcher
|
|
||||||
import json
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
import requests
|
|
||||||
import datetime as dt
|
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
REGION = "euw1"
|
|
||||||
DEFAULT_RATING = 1200
|
|
||||||
|
|
||||||
def tierToNumber(tier):
|
|
||||||
ratingmap = { 'CHALLENGER' : 4500,
|
|
||||||
'GRANDMASTER': 4000,
|
|
||||||
'MASTER' : 3500,
|
|
||||||
'DIAMOND' : 3000,
|
|
||||||
'PLATINUM' : 2500,
|
|
||||||
'GOLD' : 1500,
|
|
||||||
'SILVER' : 1000,
|
|
||||||
'BRONZE' : 500,
|
|
||||||
'IRON' : 0 }
|
|
||||||
return ratingmap[tier]
|
|
||||||
|
|
||||||
def divisionToNumber(division):
|
|
||||||
divisionmap = { "I" : 300,
|
|
||||||
"II" : 200,
|
|
||||||
"III" : 100,
|
|
||||||
"IV" : 0 }
|
|
||||||
return divisionmap[division]
|
|
||||||
|
|
||||||
DATABASE = "rating_cache.sqlite"
|
|
||||||
def checkPlayerKnown(playerName):
|
|
||||||
conn = sqlite3.connect(DATABASE)
|
|
||||||
cursor = conn.cursor()
|
|
||||||
backlog = dt.datetime.now() - dt.timedelta(days=7)
|
|
||||||
query = '''SELECT * from players where playerName = ? LIMIT 1;'''
|
|
||||||
cursor.execute(query, (playerName,))
|
|
||||||
try:
|
|
||||||
playerName, rating, lastUpdated = cursor.fetchone()
|
|
||||||
except TypeError:
|
|
||||||
print("sqlite cache '{}' not found".format(playerName))
|
|
||||||
return None
|
|
||||||
conn.close()
|
|
||||||
return (playerName, rating, lastUpdated)
|
|
||||||
|
|
||||||
def addToDB(playerName, rating):
|
|
||||||
|
|
||||||
conn = sqlite3.connect(DATABASE)
|
|
||||||
cursor = conn.cursor()
|
|
||||||
cursor.execute("INSERT INTO players VALUES(?,?,?);",(
|
|
||||||
playerName,
|
|
||||||
rating,
|
|
||||||
dt.datetime.now().timestamp()))
|
|
||||||
conn.commit()
|
|
||||||
print("Added {}".format(playerName))
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
|
|
||||||
def getPlayerRatingFromApi(playerName, WATCHER):
|
|
||||||
|
|
||||||
if not playerName:
|
|
||||||
return DEFAULT_RATING
|
|
||||||
|
|
||||||
tupel = checkPlayerKnown(playerName)
|
|
||||||
if tupel:
|
|
||||||
return tupel[1]
|
|
||||||
|
|
||||||
while(True):
|
|
||||||
try:
|
|
||||||
pTmp = WATCHER.summoner.by_name(REGION, playerName)
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
# not found #
|
|
||||||
if e.response.status_code == 404:
|
|
||||||
addToDB(playerName, DEFAULT_RATING)
|
|
||||||
return DEFAULT_RATING
|
|
||||||
# rate limit
|
|
||||||
elif e.response.status_code == 429:
|
|
||||||
print("Ratelimit reached")
|
|
||||||
#time.sleep(120)
|
|
||||||
#continue
|
|
||||||
return DEFAULT_RATING
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
if not pTmp:
|
|
||||||
addToDB(playerName, 0)
|
|
||||||
return DEFAULT_RATING
|
|
||||||
|
|
||||||
computed = DEFAULT_RATING
|
|
||||||
|
|
||||||
try:
|
|
||||||
pInfo = WATCHER.league.by_summoner(REGION, pTmp["id"])
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
if e.response.status_code == 429:
|
|
||||||
print("Ratelimit reached")
|
|
||||||
return DEFAULT_RATING
|
|
||||||
#time.sleep(120)
|
|
||||||
#continue
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
for queue in pInfo:
|
|
||||||
if queue["queueType"] != "RANKED_SOLO_5x5":
|
|
||||||
continue
|
|
||||||
computed = tierToNumber(queue["tier"]) + divisionToNumber(queue["rank"]) + \
|
|
||||||
int(queue["leaguePoints"])
|
|
||||||
print(computed)
|
|
||||||
|
|
||||||
addToDB(playerName, computed)
|
|
||||||
return computed
|
|
||||||
2
app.py
2
app.py
@@ -1,3 +1,5 @@
|
|||||||
import server
|
import server
|
||||||
def createApp(envivorment=None, start_response=None):
|
def createApp(envivorment=None, start_response=None):
|
||||||
|
with server.app.app_context():
|
||||||
|
server.create_app()
|
||||||
return server.app
|
return server.app
|
||||||
|
|||||||
19
database.py
19
database.py
@@ -31,7 +31,7 @@ class DatabaseConnection:
|
|||||||
'''Get the total number of players in the database'''
|
'''Get the total number of players in the database'''
|
||||||
|
|
||||||
cursor = self.connPlayers.cursor()
|
cursor = self.connPlayers.cursor()
|
||||||
cursor.execute("SELECT Count(*) FROM players")
|
cursor.execute("SELECT Count(*) FROM players where games >= 10 and not lastgame is null")
|
||||||
count = cursor.fetchone()[0]
|
count = cursor.fetchone()[0]
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@@ -79,8 +79,8 @@ class DatabaseConnection:
|
|||||||
|
|
||||||
cursor = self.connPlayers.cursor()
|
cursor = self.connPlayers.cursor()
|
||||||
limit = end - start
|
limit = end - start
|
||||||
print(limit, start)
|
sqlQuery = '''Select * FROM players where games >= 10
|
||||||
sqlQuery = '''Select * FROM players where games >= 1
|
and not lastgame is null
|
||||||
ORDER BY (mu - 2*sigma) DESC LIMIT ? OFFSET ?'''
|
ORDER BY (mu - 2*sigma) DESC LIMIT ? OFFSET ?'''
|
||||||
cursor.execute(sqlQuery, (limit, start))
|
cursor.execute(sqlQuery, (limit, start))
|
||||||
rows = cursor.fetchall()
|
rows = cursor.fetchall()
|
||||||
@@ -121,8 +121,11 @@ class DatabaseConnection:
|
|||||||
can't and shouldn't be used to identify a player'''
|
can't and shouldn't be used to identify a player'''
|
||||||
|
|
||||||
cursor = self.connPlayers.cursor()
|
cursor = self.connPlayers.cursor()
|
||||||
cursor.execute('''SELECT COUNT(*) from players
|
if(player.games < 10):
|
||||||
where (mu-2*sigma) > (?-2*?);''',
|
return -1
|
||||||
|
cursor.execute('''SELECT COUNT(*) from players where games >= 10
|
||||||
|
and not lastgame is null
|
||||||
|
and (mu-2*sigma) > (?-2*?);''',
|
||||||
(player.mu, player.sigma))
|
(player.mu, player.sigma))
|
||||||
rank = cursor.fetchone()[0]
|
rank = cursor.fetchone()[0]
|
||||||
return rank
|
return rank
|
||||||
@@ -178,9 +181,9 @@ class DatabaseConnection:
|
|||||||
WHERE timestamp < ? AND id = ?''',
|
WHERE timestamp < ? AND id = ?''',
|
||||||
(roundObj.startTime.timestamp(), p.playerId))
|
(roundObj.startTime.timestamp(), p.playerId))
|
||||||
|
|
||||||
#if(cursorHist.fetchone()[0] < 10):
|
if(cursorHist.fetchone()[0] < 10):
|
||||||
# p.ratingChangeString = "Placements"
|
p.ratingChangeString = "Placements"
|
||||||
# continue
|
continue
|
||||||
|
|
||||||
cursorHist.execute('''SELECT mu,sima FROM playerHistoricalData
|
cursorHist.execute('''SELECT mu,sima FROM playerHistoricalData
|
||||||
WHERE timestamp < ? AND id = ? order by timestamp DESC LIMIT 1 ''',
|
WHERE timestamp < ? AND id = ? order by timestamp DESC LIMIT 1 ''',
|
||||||
|
|||||||
93
medals.py
Normal file
93
medals.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import flask
|
||||||
|
|
||||||
|
medalDict = { "games-played-1" : { "name" : "Tourist",
|
||||||
|
"text" : "Played {} games on this server",
|
||||||
|
"color" : "white",
|
||||||
|
"text-color" : "black" },
|
||||||
|
|
||||||
|
"games-played-2" : { "name" : "Enlisted",
|
||||||
|
"text" : "Played {} games on this server",
|
||||||
|
"color": "green",
|
||||||
|
"text-color" : "white" },
|
||||||
|
|
||||||
|
"games-played-3" : { "name" : "Veteran",
|
||||||
|
"text" : "Played {} games on this server",
|
||||||
|
"color" : "yellow",
|
||||||
|
"text-color" : "black" },
|
||||||
|
|
||||||
|
"rating-cur-1" : { "name" : "Slightly skilled",
|
||||||
|
"text" : "Rated above 1500",
|
||||||
|
"color" : "beige",
|
||||||
|
"text-color" : "black" },
|
||||||
|
|
||||||
|
"rating-2k-1" : { "name" : "Contender",
|
||||||
|
"text" : "Played {} games above 2000 rating",
|
||||||
|
"color" : "coral",
|
||||||
|
"text-color" : "black" },
|
||||||
|
"rating-2k-2" : { "name" : "Known Contender",
|
||||||
|
"text" : "Played {} games above 2000 rating",
|
||||||
|
"color" : "lightgreen",
|
||||||
|
"text-color" : "black" },
|
||||||
|
|
||||||
|
"rating-3k-1" : { "name" : "Epic",
|
||||||
|
"text" : "Played {} games above 3000 rating",
|
||||||
|
"color" : "lightblue",
|
||||||
|
"text-color" : "black" },
|
||||||
|
"rating-3k-2" : { "name" : "Legend",
|
||||||
|
"text" : "Played {} games above 3000 rating",
|
||||||
|
"color" : "orange",
|
||||||
|
"text-color" : "black" },
|
||||||
|
"rating-3k-3" : { "name" : "All Along The Watchtower",
|
||||||
|
"text" : "Played {} games above 3000 rating",
|
||||||
|
"color" : "red",
|
||||||
|
"text-color" : "black" },
|
||||||
|
}
|
||||||
|
|
||||||
|
def medalGen(medal, formatInsert=None):
|
||||||
|
'''Gen HTML for metal'''
|
||||||
|
html = '\
|
||||||
|
<div style="background-color: {bg} !important; color: {color} !important;"\
|
||||||
|
class="btn btn-secondary"\
|
||||||
|
data-toggle="tooltip" data-placement="top" title="{tooltip}">\
|
||||||
|
{text}\
|
||||||
|
</div>\
|
||||||
|
'
|
||||||
|
tmp = html.format(bg=medal["color"], tooltip=medal["text"], text=medal["name"],
|
||||||
|
color=medal["text-color"])
|
||||||
|
if formatInsert:
|
||||||
|
tmp = tmp.format(formatInsert)
|
||||||
|
return flask.Markup(tmp)
|
||||||
|
|
||||||
|
def getMedals(ratingList, gamesPlayed, currentRating):
|
||||||
|
'''Get Medals this player should have'''
|
||||||
|
medals = []
|
||||||
|
|
||||||
|
if gamesPlayed > 500:
|
||||||
|
medals += [medalGen(medalDict["games-played-3"], gamesPlayed)]
|
||||||
|
elif gamesPlayed > 100:
|
||||||
|
medals += [medalGen(medalDict["games-played-2"], gamesPlayed)]
|
||||||
|
elif gamesPlayed > 50:
|
||||||
|
medals += [medalGen(medalDict["games-played-1"], gamesPlayed)]
|
||||||
|
|
||||||
|
games2k = len(list(filter(lambda x: x > 2000, ratingList)))
|
||||||
|
games3k = len(list(filter(lambda x: x > 3000, ratingList)))
|
||||||
|
|
||||||
|
if games2k > 100:
|
||||||
|
medals += [medalGen(medalDict["rating-2k-2"], games2k)]
|
||||||
|
elif games2k > 0:
|
||||||
|
medals += [medalGen(medalDict["rating-2k-1"], games2k)]
|
||||||
|
|
||||||
|
if games3k > 200:
|
||||||
|
medals += [medalGen(medalDict["rating-3k-3"], games3k)]
|
||||||
|
|
||||||
|
if games3k > 50:
|
||||||
|
medals += [medalGen(medalDict["rating-3k-2"], games3k)]
|
||||||
|
elif games3k > 5:
|
||||||
|
medals += [medalGen(medalDict["rating-3k-1"], games3k)]
|
||||||
|
|
||||||
|
if currentRating > 1500:
|
||||||
|
medals += [medalGen(medalDict["rating-cur-1"])]
|
||||||
|
|
||||||
|
return medals
|
||||||
|
|
||||||
|
|
||||||
BIN
rounds.sqlite
Normal file
BIN
rounds.sqlite
Normal file
Binary file not shown.
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "1",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "xXxMarethyuxXx",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "iTrash",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "JuckF Bierhuhn",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "TryhardYordle",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ChessGM lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "TheSlapstick",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Vyne",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE Felix",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 1456,
|
|
||||||
"startTime": "2021-04-25T22:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "0",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "ESE Felix",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Vyne",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE Kniveless",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "JuckF Bierhuhn",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "TryhardYordle",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "TheSlapstick",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "xXxMarethyuxXx",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ChessGM lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 1932,
|
|
||||||
"startTime": "2021-04-25T21:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "1",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Vyne",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE Felix",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ChessGM lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "TheSlapstick",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "xXxMarethyuxXx",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE Kniveless",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "JuckF Bierhuhn",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "TryhardYordle",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 2017,
|
|
||||||
"startTime": "2021-04-25T20:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"map" : "SR",
|
|
||||||
"winner-side" : 1,
|
|
||||||
"winners" : [
|
|
||||||
{
|
|
||||||
"playerId" : "TryhardYordle",
|
|
||||||
"playerName" : "TryhardYordle",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Schmohi",
|
|
||||||
"playerName" : "ESE Schmohi",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Area 522",
|
|
||||||
"playerName" : "Area 522",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "iTrash",
|
|
||||||
"playerName" : "iTrash",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Téa Jay",
|
|
||||||
"playerName" : "Téa Jay",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"losers" : [
|
|
||||||
{
|
|
||||||
"playerId" : "Phirop",
|
|
||||||
"playerName" : "Phirop",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ENTAC",
|
|
||||||
"playerName" : "ENTAC",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "BoringBookCover",
|
|
||||||
"playerName" : "BoringBookCover",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Litzuck",
|
|
||||||
"playerName" : "ESE Litzuck",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE MarsUltor",
|
|
||||||
"playerName" : "ESE MarsUltor",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1971
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration" : 1971,
|
|
||||||
"startTime" : "2021-05-24T20:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"map" : "SR",
|
|
||||||
"winner-side" : 0,
|
|
||||||
"winners" : [
|
|
||||||
{
|
|
||||||
"playerId" : "Vyne",
|
|
||||||
"playerName" : "Vyne",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Kniveless",
|
|
||||||
"playerName" : "ESE Kniveless",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Vinnie",
|
|
||||||
"playerName" : "ESE Vinnie",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Litzuck",
|
|
||||||
"playerName" : "ESE Litzuck",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE MarsUltor",
|
|
||||||
"playerName" : "ESE MarsUltor",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"losers" : [
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Schmohi",
|
|
||||||
"playerName" : "ESE Schmohi",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Nemesis",
|
|
||||||
"playerName" : "ESE Nemesis",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ENTAC",
|
|
||||||
"playerName" : "ENTAC",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Area 522",
|
|
||||||
"playerName" : "Area 552",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Subsidiary",
|
|
||||||
"playerName" : "Subsidiary",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1927
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"duration" : 1927,
|
|
||||||
"startTime" : "2021-05-31T20:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"map" : "SR",
|
|
||||||
"winner-side" : 1,
|
|
||||||
"winners" : [
|
|
||||||
{
|
|
||||||
"playerId" : "Vyne",
|
|
||||||
"playerName" : "Vyne",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Kniveless",
|
|
||||||
"playerName" : "ESE Kniveless",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Vinnie",
|
|
||||||
"playerName" : "ESE Vinnie",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Litzuck",
|
|
||||||
"playerName" : "ESE Litzuck",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE MarsUltor",
|
|
||||||
"playerName" : "ESE MarsUltor",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"losers" : [
|
|
||||||
{
|
|
||||||
"playerId" : "Muchlove the One",
|
|
||||||
"playerName" : "Muchlove the One",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Nemesis",
|
|
||||||
"playerName" : "ESE Nemesis",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ENTAC",
|
|
||||||
"playerName" : "ENTAC",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Area 522",
|
|
||||||
"playerName" : "Area 552",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Subsidiary",
|
|
||||||
"playerName" : "Subsidiary",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1864
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"duration" : 1864,
|
|
||||||
"startTime" : "2021-05-31T21:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"map" : "SR",
|
|
||||||
"winner-side" : 0,
|
|
||||||
"winners" : [
|
|
||||||
{
|
|
||||||
"playerId" : "Vyne",
|
|
||||||
"playerName" : "Vyne",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Kniveless",
|
|
||||||
"playerName" : "ESE Kniveless",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Muchlove the One",
|
|
||||||
"playerName" : "Muchlove the One",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Litzuck",
|
|
||||||
"playerName" : "ESE Litzuck",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ENTAC",
|
|
||||||
"playerName" : "ENTAC",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers" : [
|
|
||||||
{
|
|
||||||
"playerId" : "ESE MarsUltor",
|
|
||||||
"playerName" : "ESE MarsUltor",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Nemesis",
|
|
||||||
"playerName" : "ESE Nemesis",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Area 522",
|
|
||||||
"playerName" : "Area 552",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "Takki",
|
|
||||||
"playerName" : "Takki",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId" : "ESE Vinnie",
|
|
||||||
"playerName" : "ESE Vinnie",
|
|
||||||
"isFake" : false,
|
|
||||||
"activeTime" : 1450
|
|
||||||
}
|
|
||||||
|
|
||||||
],
|
|
||||||
"duration" : 1450,
|
|
||||||
"startTime" : "2021-05-31T23:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "0",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Victor Lustig",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "TSo",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE MarsUltor",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "Téa Jay",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Heinz sama",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Area 522",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Byndeskanzler",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE Schmohi",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 2019,
|
|
||||||
"startTime": "2021-06-07T20:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "1",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "ESE TomTom",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Byndeskanzler",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Area 522",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Heinz sama",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Téa Jay",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Victor Lustig",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE MarsUltor",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 1978,
|
|
||||||
"startTime": "2021-07-05T20:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "1",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "ESE TomTom",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Area 522",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Heinz sama",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Téa Jay",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Victor Lustig",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE MarsUltor",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Byndeskanzler",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 1978,
|
|
||||||
"startTime": "2021-07-05T21:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"map": "SR",
|
|
||||||
"winner-side": "0",
|
|
||||||
"winners": [
|
|
||||||
{
|
|
||||||
"playerId": "Phirop",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ENTAC",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Heinz sama",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Victor Lustig",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE MarsUltor",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"losers": [
|
|
||||||
{
|
|
||||||
"playerId": "Area 522",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "lbfxd",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Téa Jay",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "Byndeskanzler",
|
|
||||||
"isFake": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"playerId": "ESE TomTom",
|
|
||||||
"isFake": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"duration": 1804,
|
|
||||||
"startTime": "2021-07-05T22:00+02:00"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
curl -X POST -H "Content-Type: application/json" -d @2021-04-26-round-01.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-04-26-round-02.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-04-26-round-03.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-05-24-round-01.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-05-31-round-01.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-05-31-round-02.json http://localhost:10010/submitt-round
|
|
||||||
curl -X POST -H "Content-Type: application/json" -d @2021-05-31-round-03.json http://localhost:10010/submitt-round
|
|
||||||
13
rounds/data
13
rounds/data
@@ -1,13 +0,0 @@
|
|||||||
1
|
|
||||||
24:16
|
|
||||||
TryhardYordle
|
|
||||||
ChessGM lbfxd
|
|
||||||
TheSlapstick
|
|
||||||
Vyne
|
|
||||||
ESE Felix
|
|
||||||
Phirop
|
|
||||||
xXxMarethyuxXx
|
|
||||||
iTrash
|
|
||||||
JuckF Bierhuhn
|
|
||||||
ENTAC
|
|
||||||
2021-04-25T22:00+02:00
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
|
|
||||||
winnerside = input("Winnerseide (0/1 , 0=bue, 1=red): ")
|
|
||||||
duration = input("Duration: ")
|
|
||||||
duration = int(duration.split(":")[0])*60+int(duration.split(":")[1])
|
|
||||||
|
|
||||||
print("Blue Team")
|
|
||||||
blueTeam = []
|
|
||||||
for i in range(5):
|
|
||||||
pname = input("Name: ")
|
|
||||||
p = dict()
|
|
||||||
p.update({"playerId" : pname})
|
|
||||||
p.update({"isFake" : False})
|
|
||||||
blueTeam += [p]
|
|
||||||
|
|
||||||
print("Red Team")
|
|
||||||
redTeam = []
|
|
||||||
for i in range(5):
|
|
||||||
pname = input("Name: ")
|
|
||||||
p = dict()
|
|
||||||
p.update({"playerId" : pname})
|
|
||||||
p.update({"isFake" : False})
|
|
||||||
redTeam += [p]
|
|
||||||
|
|
||||||
if winnerside == 0:
|
|
||||||
winners = blueTeam
|
|
||||||
losers = redTeam
|
|
||||||
else:
|
|
||||||
winners = redTeam
|
|
||||||
losers = blueTeam
|
|
||||||
|
|
||||||
startTime = input("Start Time: ")
|
|
||||||
|
|
||||||
retDict = {}
|
|
||||||
retDict.update({ "map" : "SR" })
|
|
||||||
retDict.update({ "winner-side" : winnerside })
|
|
||||||
retDict.update({ "winners" : winners})
|
|
||||||
retDict.update({ "losers" : losers})
|
|
||||||
retDict.update({ "duration" : duration })
|
|
||||||
retDict.update({ "startTime" : startTime})
|
|
||||||
|
|
||||||
import json
|
|
||||||
print()
|
|
||||||
print(json.dumps(retDict, indent=4, sort_keys=False))
|
|
||||||
316
server.py
316
server.py
@@ -1,29 +1,21 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
import medals
|
||||||
import flask
|
import flask
|
||||||
import requests
|
import requests
|
||||||
import argparse
|
import argparse
|
||||||
import datetime
|
import datetime
|
||||||
import flask_caching as fcache
|
import flask_caching as fcache
|
||||||
import itertools
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import MapSummary
|
import MapSummary
|
||||||
import random
|
|
||||||
import secrets
|
|
||||||
import riotwatcher
|
|
||||||
import time
|
|
||||||
import statistics
|
|
||||||
|
|
||||||
from database import DatabaseConnection
|
from database import DatabaseConnection
|
||||||
import api
|
#import valve.source.a2s
|
||||||
|
#from valve.source import NoResponseError
|
||||||
|
|
||||||
|
|
||||||
app = flask.Flask("open-leaderboard")
|
app = flask.Flask("open-leaderboard")
|
||||||
|
|
||||||
WATCHER = None
|
|
||||||
KEY = None
|
|
||||||
|
|
||||||
|
|
||||||
if os.path.isfile("config.py"):
|
if os.path.isfile("config.py"):
|
||||||
app.config.from_object("config")
|
app.config.from_object("config")
|
||||||
|
|
||||||
@@ -50,8 +42,9 @@ def playersOnline():
|
|||||||
|
|
||||||
for s in SERVERS:
|
for s in SERVERS:
|
||||||
try:
|
try:
|
||||||
with valve.source.a2s.ServerQuerier((args.host, args.port)) as server:
|
pass
|
||||||
playerTotal += int(server.info()["player_count"])
|
#with valve.source.a2s.ServerQuerier((s["host"], s["port"])) as server:
|
||||||
|
# playerTotal += int(server.info()["player_count"])
|
||||||
except NoResponseError:
|
except NoResponseError:
|
||||||
error = "Server Unreachable"
|
error = "Server Unreachable"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -126,7 +119,7 @@ def rounds():
|
|||||||
end = flask.request.args.get("end")
|
end = flask.request.args.get("end")
|
||||||
|
|
||||||
if not start or not end:
|
if not start or not end:
|
||||||
start = datetime.datetime.now() - datetime.timedelta(days=365)
|
start = datetime.datetime.now() - datetime.timedelta(days=7)
|
||||||
end = datetime.datetime.now()
|
end = datetime.datetime.now()
|
||||||
else:
|
else:
|
||||||
start = datetime.datetime.fromtimestamp(start)
|
start = datetime.datetime.fromtimestamp(start)
|
||||||
@@ -144,227 +137,6 @@ def rounds():
|
|||||||
# display outcome
|
# display outcome
|
||||||
# display map
|
# display map
|
||||||
|
|
||||||
class Player:
|
|
||||||
def __init__(self, name, prio):
|
|
||||||
self.name = name
|
|
||||||
self.prio = prio
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
submission = dict()
|
|
||||||
@app.route("/role-submission", methods=['GET', 'POST'])
|
|
||||||
def roleSubmissionTool():
|
|
||||||
positions=["Top", "Jungle", "Mid", "Bottom", "Support" ]
|
|
||||||
|
|
||||||
ident = flask.request.args.get("id")
|
|
||||||
if flask.request.method == 'POST':
|
|
||||||
|
|
||||||
if not ident in submission:
|
|
||||||
submission.update({ ident : [] })
|
|
||||||
|
|
||||||
tmp = dict()
|
|
||||||
tmp.update({ "name" : flask.request.form["playername"] })
|
|
||||||
for p in positions:
|
|
||||||
tmp.update({ p : flask.request.form["prio_{}".format(p)] })
|
|
||||||
|
|
||||||
existed = False
|
|
||||||
for pl in submission[ident]:
|
|
||||||
if pl["name"] == tmp["name"]:
|
|
||||||
for p in positions:
|
|
||||||
pl.update({ p : flask.request.form["prio_{}".format(p)] })
|
|
||||||
existed = True
|
|
||||||
break;
|
|
||||||
|
|
||||||
if not existed:
|
|
||||||
submission[ident] += [tmp]
|
|
||||||
|
|
||||||
return flask.redirect("/balance-tool?id={}".format(ident))
|
|
||||||
else:
|
|
||||||
return flask.render_template("role_submission.html",
|
|
||||||
positions=positions,
|
|
||||||
ident=ident)
|
|
||||||
|
|
||||||
@app.route("/balance-tool-data")
|
|
||||||
def balanceToolData():
|
|
||||||
ident = flask.request.args.get("id")
|
|
||||||
retDict = dict()
|
|
||||||
if not ident in submission:
|
|
||||||
return flask.Response(json.dumps({ "no-data" : False }), 200, mimetype='application/json')
|
|
||||||
retDict.update({ "submissions" : submission[ident] })
|
|
||||||
return flask.Response(json.dumps(retDict), 200, mimetype='application/json')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
@app.route("/balance-tool", methods=['GET', 'POST'])
|
|
||||||
def balanceTool():
|
|
||||||
positions=["Top", "Jungle", "Mid", "Bottom", "Support"]
|
|
||||||
|
|
||||||
#db = DatabaseConnection(app.config["DB_PATH"])
|
|
||||||
|
|
||||||
if flask.request.method == 'POST':
|
|
||||||
|
|
||||||
players = []
|
|
||||||
threshold = 0.7
|
|
||||||
for k,v in flask.request.json.items():
|
|
||||||
if k == "acceptable-solution-threshold":
|
|
||||||
threshold = v
|
|
||||||
continue
|
|
||||||
for i in range(5):
|
|
||||||
if v[i] in positions:
|
|
||||||
v[i] = 5
|
|
||||||
else:
|
|
||||||
v[i] = int(v[i])
|
|
||||||
p = Player(k, v)
|
|
||||||
players += [p]
|
|
||||||
|
|
||||||
# theoretical minnimum #
|
|
||||||
theoMin = sum([ min(p.prio) for p in players ])
|
|
||||||
|
|
||||||
permutations = itertools.permutations(players)
|
|
||||||
|
|
||||||
best = 100
|
|
||||||
bestOption = None
|
|
||||||
alternateOptions = []
|
|
||||||
alternateOptionsAboveThreshold = []
|
|
||||||
for option in permutations:
|
|
||||||
|
|
||||||
cur = 0
|
|
||||||
|
|
||||||
for i in range(len(option)):
|
|
||||||
cur += option[i].prio[i%5]
|
|
||||||
|
|
||||||
if theoMin/cur > threshold:
|
|
||||||
alternateOptionsAboveThreshold.append(list(option))
|
|
||||||
|
|
||||||
qualityCur = int(theoMin/cur*100)
|
|
||||||
if cur < best:
|
|
||||||
best = cur
|
|
||||||
bestOption = list(option)
|
|
||||||
alternateOptions = []
|
|
||||||
alternateOptions.append(list(option))
|
|
||||||
print("Option Found Quality: {}%".format(str(qualityCur)))
|
|
||||||
elif cur == best or qualityCur > threshold*100:
|
|
||||||
alternateOptions.append(list(option))
|
|
||||||
|
|
||||||
alternateOptions += alternateOptionsAboveThreshold
|
|
||||||
retDict = { "left" : {}, "right" : {} }
|
|
||||||
bestOption = list(bestOption)
|
|
||||||
if len(bestOption) < 10:
|
|
||||||
for x in range(10-len(bestOption)):
|
|
||||||
bestOption += [Player("", [0,0,0,0,0])]
|
|
||||||
for o in alternateOptions:
|
|
||||||
for x in range(10-len(o)):
|
|
||||||
o += [Player("", [0,0,0,0,0])]
|
|
||||||
|
|
||||||
# fix options with rating #
|
|
||||||
bestOptionWithRating = None
|
|
||||||
bestOptionRatings = None
|
|
||||||
|
|
||||||
# alternate options rundown positional diff #
|
|
||||||
posCurrDiff = 100000
|
|
||||||
for o in alternateOptions:
|
|
||||||
firstHalf = o[:5]
|
|
||||||
secondHalf = o[5:]
|
|
||||||
|
|
||||||
firstHalfVal = [0, 0, 0, 0, 0]
|
|
||||||
secondHalfVal = [0, 0, 0, 0, 0]
|
|
||||||
|
|
||||||
countFirstHalf = 0
|
|
||||||
for pil in firstHalf:
|
|
||||||
if pil:
|
|
||||||
firstHalfVal[countFirstHalf] = api.getPlayerRatingFromApi(pil.name, WATCHER)
|
|
||||||
#print(pil.name, firstHalfVal[countFirstHalf])
|
|
||||||
countFirstHalf += 1
|
|
||||||
|
|
||||||
countSecondHalf = 0
|
|
||||||
for pil in secondHalf:
|
|
||||||
if pil:
|
|
||||||
secondHalfVal[countSecondHalf] = api.getPlayerRatingFromApi(pil.name, WATCHER)
|
|
||||||
#print(pil.name, secondHalfVal[countSecondHalf])
|
|
||||||
countSecondHalf += 1
|
|
||||||
|
|
||||||
posDiff = abs(statistics.median(firstHalfVal) - statistics.median(secondHalfVal))
|
|
||||||
|
|
||||||
# check if posdiff is better #
|
|
||||||
if posDiff < posCurrDiff:
|
|
||||||
bestOptionWithRating = o
|
|
||||||
bestOptionRatings = firstHalfVal + secondHalfVal
|
|
||||||
qualityRatings = -1
|
|
||||||
|
|
||||||
# find the best permutation of this solution #
|
|
||||||
for i in range(0,5):
|
|
||||||
teamDiff = abs(sum(firstHalfVal) - sum(secondHalfVal))
|
|
||||||
|
|
||||||
# first flip
|
|
||||||
tmp = firstHalfVal[i]
|
|
||||||
firstHalfVal[i] = secondHalfVal[i]
|
|
||||||
secondHalfVal[i] = tmp
|
|
||||||
teamDiffNew = abs(sum(firstHalfVal) - sum(secondHalfVal))
|
|
||||||
|
|
||||||
# if new is not better #
|
|
||||||
if not (teamDiffNew < teamDiff):
|
|
||||||
# flip it back #
|
|
||||||
tmp = firstHalfVal[i]
|
|
||||||
firstHalfVal[i] = secondHalfVal[i]
|
|
||||||
secondHalfVal[i] = tmp
|
|
||||||
# else flip the names too #
|
|
||||||
else:
|
|
||||||
tmp = firstHalf[i]
|
|
||||||
firstHalf[i] = secondHalf[i]
|
|
||||||
secondHalf[i] = tmp
|
|
||||||
# and reset the option #
|
|
||||||
bestOptionWithRating = firstHalf + secondHalf
|
|
||||||
bestOptionRatings = firstHalfVal + secondHalfVal
|
|
||||||
qualityRatings = min(sum(firstHalfVal)/sum(secondHalfVal),
|
|
||||||
sum(secondHalfVal)/sum(firstHalfVal))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
retDict["left"].update( { positions[i] : bestOptionWithRating[i].name })
|
|
||||||
retDict["right"].update({ positions[i] : bestOptionWithRating[i+5].name })
|
|
||||||
|
|
||||||
import sys
|
|
||||||
print(flask.request.json, file=sys.stderr)
|
|
||||||
print(retDict, file=sys.stderr)
|
|
||||||
renderContent = flask.render_template("balance_response_partial.html", d=retDict,
|
|
||||||
reqJson=flask.request.json,
|
|
||||||
positions=positions,
|
|
||||||
ratings=bestOptionRatings,
|
|
||||||
qualityPositions=int(theoMin/best*100),
|
|
||||||
qualityRatings=int(qualityRatings*100))
|
|
||||||
return flask.Response(
|
|
||||||
json.dumps({ "content": renderContent }), 200, mimetype='application/json')
|
|
||||||
else:
|
|
||||||
givenIdent = flask.request.args.get("id")
|
|
||||||
if givenIdent:
|
|
||||||
ident = givenIdent
|
|
||||||
else:
|
|
||||||
ident = secrets.token_urlsafe(16)
|
|
||||||
return flask.redirect("/balance-tool?id={}".format(ident))
|
|
||||||
return flask.render_template("json_builder.html",
|
|
||||||
positions=positions,
|
|
||||||
sides=["left", "right"],
|
|
||||||
ident=ident)
|
|
||||||
@app.route("/get-cache")
|
|
||||||
def getCacheLoc():
|
|
||||||
return (json.dumps(api.getCache()), 200)
|
|
||||||
|
|
||||||
@app.route("/player-api")
|
|
||||||
def playerApi():
|
|
||||||
result = api.getPlayerRatingFromApi(flask.request.args.get("id"), WATCHER)
|
|
||||||
if result:
|
|
||||||
return ("OK", 200)
|
|
||||||
else:
|
|
||||||
return ("Nope", 404)
|
|
||||||
|
|
||||||
@app.route("/player-api-cache")
|
|
||||||
def playerApiCache():
|
|
||||||
result = api.checkPlayerKnown(flask.request.args.get("id"))
|
|
||||||
if result and result[1] != 0:
|
|
||||||
return ("OK", 200)
|
|
||||||
else:
|
|
||||||
return ("Nope", 404)
|
|
||||||
|
|
||||||
@app.route("/player")
|
@app.route("/player")
|
||||||
def player():
|
def player():
|
||||||
'''Show Info about Player'''
|
'''Show Info about Player'''
|
||||||
@@ -389,16 +161,29 @@ def player():
|
|||||||
minRating = 3000
|
minRating = 3000
|
||||||
maxRating = 0
|
maxRating = 0
|
||||||
|
|
||||||
|
# data for medals #
|
||||||
|
medalsRatingList = []
|
||||||
|
|
||||||
if histData:
|
if histData:
|
||||||
datapoints = histData[playerId]
|
datapoints = histData[playerId]
|
||||||
if datapoints:
|
if datapoints:
|
||||||
|
|
||||||
tickCounter = 10
|
tickCounter = 10
|
||||||
for dpk in datapoints.keys():
|
for dpk in datapoints.keys():
|
||||||
|
|
||||||
|
# timestamp #
|
||||||
t = datetime.datetime.fromtimestamp(int(float(dpk)))
|
t = datetime.datetime.fromtimestamp(int(float(dpk)))
|
||||||
tsMs = str(int(t.timestamp() * 1000))
|
tsMs = str(int(t.timestamp() * 1000))
|
||||||
ratingString = str(int(datapoints[dpk]["mu"]) - 2*int(datapoints[dpk]["sigma"]))
|
|
||||||
|
computedRating = int(datapoints[dpk]["mu"]) - 2*int(datapoints[dpk]["sigma"])
|
||||||
|
|
||||||
|
# for medals #
|
||||||
|
medalsRatingList += [computedRating]
|
||||||
|
|
||||||
|
# for moment js #
|
||||||
|
ratingString = str(computedRating)
|
||||||
ratingAmored = '{ x : ' + tsMs + ', y : ' + ratingString + '}'
|
ratingAmored = '{ x : ' + tsMs + ', y : ' + ratingString + '}'
|
||||||
|
|
||||||
csv_timestamps += [str(tsMs)]
|
csv_timestamps += [str(tsMs)]
|
||||||
csv_ratings += [ratingAmored]
|
csv_ratings += [ratingAmored]
|
||||||
|
|
||||||
@@ -411,6 +196,8 @@ def player():
|
|||||||
maxRating = max(maxRating, int(ratingString))
|
maxRating = max(maxRating, int(ratingString))
|
||||||
|
|
||||||
yMin, yMax = prettifyMinMaxY(minRating, maxRating)
|
yMin, yMax = prettifyMinMaxY(minRating, maxRating)
|
||||||
|
|
||||||
|
medalsList = medals.getMedals(medalsRatingList, player.games, player.rating)
|
||||||
|
|
||||||
# change displayed rank to start from 1 :)
|
# change displayed rank to start from 1 :)
|
||||||
player.rank += 1
|
player.rank += 1
|
||||||
@@ -418,10 +205,11 @@ def player():
|
|||||||
return flask.render_template("player.html", player=player, CSV_RATINGS=",".join(csv_ratings),
|
return flask.render_template("player.html", player=player, CSV_RATINGS=",".join(csv_ratings),
|
||||||
CSV_MONTH_YEAR_OF_RATINGS=",".join(csv_month_year),
|
CSV_MONTH_YEAR_OF_RATINGS=",".join(csv_month_year),
|
||||||
CSV_TIMESTAMPS=csv_timestamps,
|
CSV_TIMESTAMPS=csv_timestamps,
|
||||||
Y_MIN=yMin, Y_MAX=yMax)
|
Y_MIN=yMin, Y_MAX=yMax, medals=medalsList)
|
||||||
|
|
||||||
@app.route('/leaderboard')
|
@app.route('/leaderboard')
|
||||||
@cache.cached(timeout=10, query_string=True)
|
@app.route('/')
|
||||||
|
@cache.cached(timeout=600, query_string=True)
|
||||||
def leaderboard():
|
def leaderboard():
|
||||||
'''Show main leaderboard page with range dependant on parameters'''
|
'''Show main leaderboard page with range dependant on parameters'''
|
||||||
|
|
||||||
@@ -476,7 +264,6 @@ def leaderboard():
|
|||||||
if end > maxEntry:
|
if end > maxEntry:
|
||||||
start = maxEntry - ( maxEntry % SEGMENT ) - 1
|
start = maxEntry - ( maxEntry % SEGMENT ) - 1
|
||||||
end = maxEntry - 1
|
end = maxEntry - 1
|
||||||
print(maxEntry)
|
|
||||||
reachedEnd = True
|
reachedEnd = True
|
||||||
|
|
||||||
playerList = db.getRankRange(start, end)
|
playerList = db.getRankRange(start, end)
|
||||||
@@ -490,11 +277,11 @@ def leaderboard():
|
|||||||
if maxEntry <= 100:
|
if maxEntry <= 100:
|
||||||
start = max(start, 0)
|
start = max(start, 0)
|
||||||
|
|
||||||
finalResponse = flask.render_template("base.html", playerList=playerList, \
|
finalResponse = flask.render_template("base.html", playerList=playerList,
|
||||||
doNotComputeRank=doNotComputeRank, \
|
doNotComputeRank=doNotComputeRank,
|
||||||
start=start, \
|
start=start,
|
||||||
endOfBoardIndicator=endOfBoardIndicator, \
|
endOfBoardIndicator=endOfBoardIndicator,
|
||||||
findPlayer=cannotFindPlayer, \
|
findPlayer=cannotFindPlayer,
|
||||||
searchName=searchName,
|
searchName=searchName,
|
||||||
nextPageNumber=int(pageInt)+1,
|
nextPageNumber=int(pageInt)+1,
|
||||||
prevPageNumber=int(pageInt)-1)
|
prevPageNumber=int(pageInt)-1)
|
||||||
@@ -502,28 +289,35 @@ def leaderboard():
|
|||||||
|
|
||||||
@app.route('/static/<path:path>')
|
@app.route('/static/<path:path>')
|
||||||
def send_js(path):
|
def send_js(path):
|
||||||
return send_from_directory('static', path)
|
|
||||||
|
|
||||||
@app.before_first_request
|
response = send_from_directory('static', path)
|
||||||
def init():
|
response.headers['Cache-Control'] = "max-age=2592000"
|
||||||
|
return response
|
||||||
|
|
||||||
global WATCHER
|
|
||||||
with open("key.txt","r") as f:
|
def create_app():
|
||||||
key = f.read().strip()
|
|
||||||
WATCHER = riotwatcher.LolWatcher(key)
|
global SERVERS
|
||||||
|
|
||||||
|
SERVERS_FILE = "servers.json"
|
||||||
|
if os.path.isfile(SERVERS_FILE):
|
||||||
|
with open(SERVERS_FILE) as f:
|
||||||
|
SERVERS = json.load(f)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Start open-leaderboard', \
|
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
||||||
parser.add_argument('--interface', default="localhost", \
|
|
||||||
help='Interface on which flask (this server) will take requests on')
|
|
||||||
parser.add_argument('--port', default="5002", \
|
|
||||||
help='Port on which flask (this server) will take requests on')
|
|
||||||
|
|
||||||
parser.add_argument('--skillbird-db', required=False, help='skillbird database (overrides web connection if set)')
|
parser = argparse.ArgumentParser(description='Start open-leaderboard',
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
parser.add_argument('--interface', default="localhost",
|
||||||
|
help='Interface on which flask (this server) will take requests on')
|
||||||
|
parser.add_argument('--port', default="5002",
|
||||||
|
help='Port on which flask (this server) will take requests on')
|
||||||
|
parser.add_argument('--skillbird-db', required=True,
|
||||||
|
help='skillbird database (overrides web connection if set)')
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
create_app()
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
app.config["DB_PATH"] = args.skillbird_db
|
app.config["DB_PATH"] = args.skillbird_db
|
||||||
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
|
||||||
app.run(host=args.interface, port=args.port)
|
app.run(host=args.interface, port=args.port)
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
CREATE TABLE players(
|
|
||||||
playerName TEXT PRIMARY KEY,
|
|
||||||
rating INTEGER,
|
|
||||||
lastupdated TEXT
|
|
||||||
);
|
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
positions = [ "Top", "Jungle", "Mid", "Bottom", "Support" ]
|
|
||||||
acceptedParser = [ "top", "jungle", "mid", "sup" , "bot", "adc", "support", "bottom", "*" ]
|
|
||||||
sides = [ "left", "right"]
|
|
||||||
|
|
||||||
var checkPlayerFunc = function checkPlayer() {
|
|
||||||
if(this.value == ""){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
url = "/player-api-cache?id=" + this.value
|
|
||||||
fetch(url).then(r => {
|
|
||||||
if(r.status == 200){
|
|
||||||
this.style.background = "#74bb74"
|
|
||||||
}else{
|
|
||||||
this.style.background = "#d25252"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var checkPlayerApiFunc = function checkPlayer() {
|
|
||||||
if(this.value == ""){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
url = "/player-api?id=" + this.value
|
|
||||||
fetch(url).then(r => {
|
|
||||||
if(r.status == 200){
|
|
||||||
this.style.background = "#74bb74"
|
|
||||||
}else{
|
|
||||||
//this.style.background = "#d25252"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var fastPosChangedFunc = function fastPosChanged() {
|
|
||||||
|
|
||||||
accepted = [ "top", "jungle", "mid", "sup" , "bot" ]
|
|
||||||
uniqArr = []
|
|
||||||
prioArray = [5, 5, 5, 5, 5]
|
|
||||||
|
|
||||||
/* commence cleanup */
|
|
||||||
clean = this.value.replaceAll(" ", "").toLocaleLowerCase()
|
|
||||||
clean = clean.replace("support", "sup")
|
|
||||||
clean = clean.replace("adc", "bot")
|
|
||||||
clean = clean.replace("bottom", "bot")
|
|
||||||
|
|
||||||
retVal = true
|
|
||||||
if(clean.includes("<")){
|
|
||||||
console.log("Not accepted (includes <)")
|
|
||||||
retVal = false
|
|
||||||
}
|
|
||||||
|
|
||||||
list = clean.split(">")
|
|
||||||
cur = 1
|
|
||||||
list.forEach(el => {
|
|
||||||
if(el.includes("=")){
|
|
||||||
listEq = el.split("=")
|
|
||||||
listEq.forEach(sub => {
|
|
||||||
if(accepted.includes(sub) && !uniqArr.includes(sub)){
|
|
||||||
prioArray[accepted.indexOf(sub)] = cur
|
|
||||||
uniqArr += [sub]
|
|
||||||
}else{
|
|
||||||
console.log("Not accepted (=): " + sub)
|
|
||||||
retVal = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
cur++
|
|
||||||
}else{
|
|
||||||
if(accepted.includes(el) && !uniqArr.includes(el)){
|
|
||||||
prioArray[accepted.indexOf(el)] = cur
|
|
||||||
uniqArr += [el]
|
|
||||||
cur++
|
|
||||||
}else{
|
|
||||||
console.log("Not accepted (>): " + el)
|
|
||||||
retVal = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for(i = 0; i<5; i++){
|
|
||||||
arr = this.id.split("-")
|
|
||||||
pNr = arr[arr.length-1]
|
|
||||||
side = this.id.includes("left") ? "left" : "right"
|
|
||||||
|
|
||||||
roleSubmission = document.getElementById("fastpos-submission")
|
|
||||||
if(roleSubmission){
|
|
||||||
string = "prio_" + accepted[i]
|
|
||||||
}else {
|
|
||||||
string = "prio-" + side + "-" + accepted[i] + "-" + pNr
|
|
||||||
}
|
|
||||||
|
|
||||||
string = string.replace("top","Top")
|
|
||||||
string = string.replace("jungle","Jungle")
|
|
||||||
string = string.replace("mid","Mid")
|
|
||||||
string = string.replace("sup","Support")
|
|
||||||
string = string.replace("bot","Bottom")
|
|
||||||
|
|
||||||
selector = document.getElementById(string)
|
|
||||||
selector.value = prioArray[i]
|
|
||||||
selector.style.background = "lightblue"
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow some basic shit */
|
|
||||||
if(clean == "*" || clean == ""){
|
|
||||||
retVal = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if(retVal){
|
|
||||||
this.style.background = "#74bb74"
|
|
||||||
}else{
|
|
||||||
this.style.background = "#d25252"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function balance(){
|
|
||||||
|
|
||||||
cont = document.getElementById("response-container")
|
|
||||||
cont.innerHTML = ""
|
|
||||||
cont.style.color = "black";
|
|
||||||
sides = ["left", "right"]
|
|
||||||
|
|
||||||
blue = [ "", "", "", "", ""]
|
|
||||||
red = [ "", "", "", "", ""]
|
|
||||||
|
|
||||||
dictToBeSorted = {
|
|
||||||
0 : [],
|
|
||||||
1 : [],
|
|
||||||
2 : [],
|
|
||||||
3 : [],
|
|
||||||
4 : []
|
|
||||||
}
|
|
||||||
filler = []
|
|
||||||
impossible = []
|
|
||||||
|
|
||||||
dictAll = {}
|
|
||||||
for(sid = 0; sid < 2; sid++){
|
|
||||||
for(id = 0; id < 5; id++){
|
|
||||||
|
|
||||||
var pname = "undef"
|
|
||||||
var prioList = [5, 5, 5, 5, 5]
|
|
||||||
|
|
||||||
stringPid = `playername-${sides[sid]}-${id}`
|
|
||||||
pnameObj = document.getElementById(stringPid)
|
|
||||||
pname = pnameObj.value
|
|
||||||
for(acc = 0; acc < 5; acc++){
|
|
||||||
stringSelectorId = `prio-${sides[sid]}-${positions[acc]}-${id}`
|
|
||||||
selObj = document.getElementById(stringSelectorId)
|
|
||||||
prioList[acc] = selObj.value
|
|
||||||
}
|
|
||||||
|
|
||||||
dictAll[pname] = prioList
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prioBalanceCheckbox = document.getElementById("prio-balance")
|
|
||||||
if(prioBalanceCheckbox.checked){
|
|
||||||
dictAll["acceptable-solution-threshold"] = 0.5
|
|
||||||
}else{
|
|
||||||
dictAll["acceptable-solution-threshold"] = 0.7
|
|
||||||
}
|
|
||||||
jsonData = JSON.stringify(dictAll, null, 4);
|
|
||||||
|
|
||||||
/* transmitt */
|
|
||||||
spinner = document.getElementById("loading")
|
|
||||||
spinner.style.display = "block";
|
|
||||||
fetch(window.location.href, {
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json, text/plain, */*',
|
|
||||||
'Content-Type': 'application/json' },
|
|
||||||
body: jsonData
|
|
||||||
}).then(r => r.json()).then(j => {
|
|
||||||
spinner.style.display = "none";
|
|
||||||
cont.innerHTML = j["content"]
|
|
||||||
}).catch(err => {
|
|
||||||
spinner.style.display = "none";
|
|
||||||
cont.style.color = "red";
|
|
||||||
cont.innerHTML = "Error - request failed."
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseMultiline(){
|
|
||||||
|
|
||||||
var names = []
|
|
||||||
var prioStrings = []
|
|
||||||
|
|
||||||
field = document.getElementById("multi-line-copy")
|
|
||||||
lines = field.value.split("\n")
|
|
||||||
lines.forEach(l => {
|
|
||||||
|
|
||||||
lowestIndex = 100
|
|
||||||
|
|
||||||
acceptedParser.forEach( p => {
|
|
||||||
i = l.indexOf(" " + p)
|
|
||||||
if(i >= 3 && i < lowestIndex){
|
|
||||||
lowestIndex = i
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if(lowestIndex != 100){
|
|
||||||
name = l.substring(0, lowestIndex)
|
|
||||||
prioStr = l.substring(lowestIndex)
|
|
||||||
names.push(name)
|
|
||||||
prioStrings.push(prioStr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
count = 0
|
|
||||||
sides.forEach(s => {
|
|
||||||
for(i = 0; i<5; i++){
|
|
||||||
|
|
||||||
pObjField = document.getElementById("playername-" + s + "-" + i)
|
|
||||||
prObjField = document.getElementById("check-" + s + "-fastpos-" + i)
|
|
||||||
|
|
||||||
if(count >= names.length){
|
|
||||||
pObjField.value = ""
|
|
||||||
prObjField.value = ""
|
|
||||||
}else{
|
|
||||||
pObjField.value = names[count]
|
|
||||||
prObjField.value = prioStrings[count]
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const inputEvent = new Event("input")
|
|
||||||
fastPosFields.forEach(el => el.dispatchEvent(inputEvent))
|
|
||||||
balance()
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryForPlayerData(){
|
|
||||||
ident = document.getElementById("ident-field").innerHTML
|
|
||||||
fetch("/balance-tool-data?id=" + ident).then(r => r.json()).then(j => {
|
|
||||||
if("no-data" in j){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
j["submissions"].forEach(el => {
|
|
||||||
console.log(el)
|
|
||||||
breakToSubmissions = false
|
|
||||||
for(sid = 0; sid < 2; sid++){
|
|
||||||
if(breakToSubmissions){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for(id = 0; id < 5; id++){
|
|
||||||
stringPid = `playername-${sides[sid]}-${id}`
|
|
||||||
pnameObj = document.getElementById(stringPid)
|
|
||||||
if(pnameObj.value == "" || pnameObj.value == el["name"]){
|
|
||||||
pnameObj.value = el["name"]
|
|
||||||
for(acc = 0; acc < 5; acc++){
|
|
||||||
stringSelectorId = `prio-${sides[sid]}-${positions[acc]}-${id}`
|
|
||||||
selObj = document.getElementById(stringSelectorId)
|
|
||||||
selObj.value = el[positions[acc]]
|
|
||||||
}
|
|
||||||
breakToSubmissions = true
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function copy() {
|
|
||||||
|
|
||||||
ident = document.getElementById("ident-field").innerHTML
|
|
||||||
path = "/role-submission?id="
|
|
||||||
copyText = window.location.protocol + "//" + window.location.hostname + path + ident
|
|
||||||
|
|
||||||
navigator.clipboard.writeText(copyText)
|
|
||||||
document.getElementById("copyLink").innerHTML = "Copied!"
|
|
||||||
setTimeout(() => {
|
|
||||||
document.getElementById("copyLink").innerHTML = "Copy Submission Link" }, 500);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fastPosFields = document.getElementsByClassName("fastpos")
|
|
||||||
playerNameFields = document.getElementsByClassName("pname")
|
|
||||||
|
|
||||||
playerNameFields.forEach(el => el.addEventListener('input', checkPlayerFunc));
|
|
||||||
playerNameFields.forEach(el => el.addEventListener('focus', checkPlayerFunc));
|
|
||||||
|
|
||||||
fastPosFields.forEach(el => el.addEventListener('input', fastPosChangedFunc));
|
|
||||||
//fastPosFields.forEach(el => el.addEventListener('focus', fastPosChangedFunc));
|
|
||||||
|
|
||||||
fastposSubmission = document.getElementById("fastpos-submission")
|
|
||||||
if(fastposSubmission){
|
|
||||||
fastposSubmission.addEventListener("input", fastPosChangedFunc)
|
|
||||||
fastposSubmission.addEventListener("focus", fastPosChangedFunc)
|
|
||||||
}
|
|
||||||
setInterval(queryForPlayerData(), 3000)
|
|
||||||
|
|
||||||
formContainer = document.getElementById("form-container")
|
|
||||||
if(formContainer){
|
|
||||||
//formContainer.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetAll(){
|
|
||||||
formContainer = document.getElementById("form-container")
|
|
||||||
formContainer.reset()
|
|
||||||
}
|
|
||||||
@@ -8,12 +8,6 @@ body{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-special{
|
|
||||||
border-style: outset;
|
|
||||||
border-width: 0.2px;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-bar{
|
.top-bar{
|
||||||
background-color: orange;
|
background-color: orange;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
@@ -70,14 +64,14 @@ body{
|
|||||||
font-size: 5vw;
|
font-size: 5vw;
|
||||||
margin-right: 2.5%;
|
margin-right: 2.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field{
|
.input-field{
|
||||||
margin-top: 2vw;
|
margin-top: 2vw;
|
||||||
float: left;
|
float: left;
|
||||||
font-size: 6vw;
|
font-size: 6vw;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field-number{
|
.input-field-number{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -87,7 +81,7 @@ body{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ############# PLAYER INFORMATION IN LINES ############# */
|
/* ############# PLAYER INFORMATION IN LINES ############# */
|
||||||
.playerRank{
|
.playerRank{
|
||||||
margin-left:1%;
|
margin-left:1%;
|
||||||
float: left;
|
float: left;
|
||||||
@@ -149,7 +143,7 @@ body{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.line-odd{
|
.line-odd{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: black;
|
color: black;
|
||||||
background-color: lightgrey !important;
|
background-color: lightgrey !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -173,7 +167,7 @@ body{
|
|||||||
font-size: 4.5vw;
|
font-size: 4.5vw;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colum-names{
|
.colum-names{
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -205,14 +199,14 @@ body{
|
|||||||
width: 15%;
|
width: 15%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playerWinratio{
|
.playerWinratio{
|
||||||
/* 19% is just enought to cut the last letter */
|
/* 19% is just enought to cut the last letter */
|
||||||
width: 19%;
|
width: 19%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ######################## FOOTER ####################### */
|
/* ######################## FOOTER ####################### */
|
||||||
.footer{
|
.footer{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -223,7 +217,6 @@ body{
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLink{
|
.footerLink{
|
||||||
@@ -247,7 +240,6 @@ body{
|
|||||||
.footerLink{
|
.footerLink{
|
||||||
font-size: 4vw;
|
font-size: 4vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mid{
|
.mid{
|
||||||
margin-left: 2.5%;
|
margin-left: 2.5%;
|
||||||
margin-right: 2.5%;
|
margin-right: 2.5%;
|
||||||
@@ -264,3 +256,11 @@ body{
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0.3; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-flicker {
|
||||||
|
animation: fadeIn 2s alternate;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
<div class="my-3">
|
|
||||||
<h3> Suggestion </h3>
|
|
||||||
<p>Postion Wishes: {{ qualityPositions }}% fullfilled /
|
|
||||||
Teambalance: {{ qualityRatings }}% </p>
|
|
||||||
</div>
|
|
||||||
{% for x in range(5) %}
|
|
||||||
<div class="row">
|
|
||||||
{% set leftP = d["left"][positions[x]] %}
|
|
||||||
{% set rightP = d["right"][positions[x]] %}
|
|
||||||
<div class="col-sm">
|
|
||||||
{{ positions[x] }}
|
|
||||||
</div>
|
|
||||||
<div class="col-sm"
|
|
||||||
{% if reqJson.get(leftP) and reqJson.get(leftP)[x] | int >= 4 %}
|
|
||||||
style="background: red;"
|
|
||||||
{% endif %}>
|
|
||||||
{{ leftP }} ({{ ratings[x] }})
|
|
||||||
</div>
|
|
||||||
<div class="col-sm"
|
|
||||||
{% if reqJson.get(rightP) and reqJson.get(rightP)[x] | int >= 4 %}
|
|
||||||
style="background: red;"
|
|
||||||
{% endif %}>
|
|
||||||
{{ rightP }} ({{ ratings[x+5] }})
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<div class="mt-3">
|
|
||||||
<h3>For copying into Lobby:</h3>
|
|
||||||
<div class="mt-2">
|
|
||||||
<div class="row">
|
|
||||||
<textarea style="padding-left: 10px !important; padding-top: 10px !important" rows="16" cols= 100>
|
|
||||||
Left Side Team
|
|
||||||
{% for x in range(5) %}
|
|
||||||
{% set leftP = d["left"][positions[x]] %}{{ leftP }} left team {{ positions[x] }}{% endfor %}
|
|
||||||
|
|
||||||
Right Side Team
|
|
||||||
{% for x in range(5) %}
|
|
||||||
{% set rightP = d["right"][positions[x]] %}{{ rightP }} right team {{ positions[x] }}{% endfor %}
|
|
||||||
</textarea>
|
|
||||||
</div>
|
|
||||||
@@ -10,6 +10,29 @@
|
|||||||
{% include 'navbar_leaderboard.html' %}
|
{% include 'navbar_leaderboard.html' %}
|
||||||
|
|
||||||
<div class="container mt-3 mb-3" role="main">
|
<div class="container mt-3 mb-3" role="main">
|
||||||
|
<div id="playerDisplay" class="playerDisplay mb-3 mt-2">
|
||||||
|
<script>
|
||||||
|
function players(){
|
||||||
|
//document.getElementById("playerDisplay").classList.remove("animate-flicker")
|
||||||
|
fetch("/players-online").then(
|
||||||
|
response => response.json()
|
||||||
|
).then(
|
||||||
|
data => {
|
||||||
|
if(data["error"] == ""){
|
||||||
|
document.getElementById("playerDisplay").innerHTML = "Players Online: " + data["player_total"]
|
||||||
|
if(parseInt(data["player_total"]) == 0){
|
||||||
|
//document.getElementById("playerDisplay").classList.add("animate-flicker")
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
document.getElementById("playerDisplay").innerHTML = "Players Online: (error)" + data["error"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
players()
|
||||||
|
setInterval(players, 10000)
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
<table id="tableMain" class="table table-striped table-bordered table-sm"
|
<table id="tableMain" class="table table-striped table-bordered table-sm"
|
||||||
cellspacing="0">
|
cellspacing="0">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="footer-copyright text-center py-3 bg-dark" role="contentinfo">
|
<div class="footer-copyright text-center py-3 bg-dark" role="contentinfo">
|
||||||
<a style="color: rgba(255,255,255,.5);"
|
<a style="color: rgba(255,255,255,.5);"
|
||||||
class="footerLink" href="https://atlantishq.de/impressum">Impressum/Legal</a>
|
class="footerLink" href="https://blog.atlantishq.de/about">Impressum/Legal</a>
|
||||||
<a style="color: rgba(255,255,255,.5);"
|
<a style="color: rgba(255,255,255,.5);"
|
||||||
class="footerLink mid" href="https://esports-erlangen.de">
|
class="footerLink mid" href="steam://connect/athq.de/:27026">
|
||||||
ESE Website</a>
|
Join the Server!</a>
|
||||||
<a style="color: rgba(255,255,255,.5);"
|
<a style="color: rgba(255,255,255,.5);"
|
||||||
class="footerLink" href="https://github.com/FAUSheppy/skillbird">Star on GitHub</a>
|
class="footerLink" href="https://github.com/FAUSheppy/skillbird">Star on GitHub</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,150 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Balance and Submission Tool</title>
|
|
||||||
<meta name="Description" content="Sheppy is awesome?">
|
|
||||||
<script defer src="/static/balance.js"></script>
|
|
||||||
{% include 'default_head_content.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="bg-special">
|
|
||||||
{% include 'navbar.html' %}
|
|
||||||
<div id="ident-field" style="display: none;">{{ ident }}</div>
|
|
||||||
<div class="container mt-3 mb-3" role="main">
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm">
|
|
||||||
<h1>Balance Tool</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<button type="button" class="mb-3 btn btn-secondary" onclick="balance()">
|
|
||||||
Find Teams
|
|
||||||
</button>
|
|
||||||
</br>
|
|
||||||
<button id="copyLink" type="button"
|
|
||||||
class="mb-3 btn btn-secondary" onclick="copy()">
|
|
||||||
Copy Submission Link
|
|
||||||
</button>
|
|
||||||
<button type="button"
|
|
||||||
class="mb-3 btn btn-secondary" onclick="queryForPlayerData()">
|
|
||||||
Check Submissions
|
|
||||||
</button>
|
|
||||||
</br>
|
|
||||||
{% if True %}
|
|
||||||
<button class="btn btn-primary" type="button" data-toggle="collapse"
|
|
||||||
data-target="#hilfe" aria-expanded="false"
|
|
||||||
aria-controls="hilfe">
|
|
||||||
Hilfe Anzeigen
|
|
||||||
</button>
|
|
||||||
<button type="button"
|
|
||||||
class="mb-3 btn btn-secondary" onclick="resetAll()">
|
|
||||||
Reset all
|
|
||||||
</button></br>
|
|
||||||
|
|
||||||
<div style="display: none;" class="form-check mt-3">
|
|
||||||
<input class="form-check-input" type="checkbox" value=""
|
|
||||||
id="prio-balance">
|
|
||||||
<label class="form-check-label" for="flexCheckChecked">
|
|
||||||
Prioritize balance over positional preferences
|
|
||||||
<p style="color: red;">(experimental, slow af)</p>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="hilfe" class="collapse mt-5 border-special">
|
|
||||||
<h4>Priorität</h4>
|
|
||||||
<p>
|
|
||||||
1 = höchste Priorität
|
|
||||||
5 = niedrigste Priorität
|
|
||||||
</p>
|
|
||||||
<hr class="my-3">
|
|
||||||
<h4>Fast Position</h4>
|
|
||||||
<p>
|
|
||||||
<b>Positionen können in den Kurzschreibweisen: top, mid, bot, jungle, support mit "=" und ">" angegeben werden. Zum Beispiel:</b></br></br>
|
|
||||||
top > mid > top = adc</br>
|
|
||||||
mid = top > bot</br>
|
|
||||||
support > jungle</br>
|
|
||||||
etc..</br>
|
|
||||||
</p>
|
|
||||||
<hr class="my-3">
|
|
||||||
<h4>Submission Link</h4>
|
|
||||||
<p>
|
|
||||||
Mit diesem Link können Spieler eine Positionspräferenz selbst übermitteln, einfach diesen Link in den Chat pasten.
|
|
||||||
</p>
|
|
||||||
<hr class="my-3">
|
|
||||||
<h4>Find Teams</h4>
|
|
||||||
<p>
|
|
||||||
Sobald alle eingetragen sind einmal auf "Find Teams" klicken und auf den Vorschlag warten.
|
|
||||||
</p>
|
|
||||||
<hr class="my-3">
|
|
||||||
<h4>Multiline Input</h4>
|
|
||||||
<p>
|
|
||||||
Jeder Kann seine Rollen im Schnellformat in den Chat schreiben, in das Feld unten kopieren und Button drücken (überschreibt existierende Einträge).
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="spinner-border" id="loading" style="display: none;" role="status">
|
|
||||||
<span class="sr-only">Loading...</span>
|
|
||||||
</div>
|
|
||||||
<div id="response-container" class="mt-3 mb-3">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
|
|
||||||
<form id="form-container" class="row">
|
|
||||||
{% for side in sides %}
|
|
||||||
<div class="col-sm">
|
|
||||||
{% for field in range(5) %}
|
|
||||||
<div id="{{ side }}-{{ field }}" class="row mt-2 mb-2">
|
|
||||||
<div class="col-sm">
|
|
||||||
|
|
||||||
<!-- player name field -->
|
|
||||||
<input class="form-control pname" type="text" placeholder="Player"
|
|
||||||
id="playername-{{ side }}-{{ field }}">
|
|
||||||
|
|
||||||
<!-- fast postition slection field -->
|
|
||||||
<input class="form-control fastpos" type="text"
|
|
||||||
placeholder="top > mid = bot"
|
|
||||||
id="check-{{ side }}-fastpos-{{ field }}">
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-sm">
|
|
||||||
<!-- checkboxes for pos -->
|
|
||||||
{% for pos in positions %}
|
|
||||||
<select id="prio-{{ side }}-{{ pos }}-{{ field }}"
|
|
||||||
class="form-select">
|
|
||||||
<option selected>{{ pos }}</option>
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
</select>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</form>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<textarea type="text" id="multi-line-copy" rows="10"
|
|
||||||
placeholder="Have everybody write their roles in the form of 'top > mid = sup = jungle >adc' in the chat and then copy it in here and hit 'Use Multiline Input' :)"
|
|
||||||
class="form-control md-textarea"></textarea>
|
|
||||||
<button type="button" class="mb-3 btn btn-secondary" onclick="parseMultiline()">
|
|
||||||
Use Multiline Input..
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
</div>
|
|
||||||
{% include 'footer.html' %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -10,13 +10,28 @@
|
|||||||
<!-- left side -->
|
<!-- left side -->
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/">New Balance</a>
|
<a class="nav-link" href="/">Leaderboard</a>
|
||||||
</li>
|
</li>
|
||||||
<!--
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/rounds">Rounds</a>
|
<a class="nav-link" href="/rounds">Rounds</a>
|
||||||
</li>
|
</li>
|
||||||
-->
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/maps">Maps</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav right">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="steam://connect/athq.de/:27026">Server 1</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mr-4">
|
||||||
|
<a class="nav-link" href="steam://connect/athq.de/:27015">Server 2</a>
|
||||||
|
</li>
|
||||||
|
<!--
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="navbar-brand hover-to-75 patreon" style="position: unset !important;" href="https://www.patreon.com/erlangen_sheppy">Support me
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
-->
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -18,8 +18,10 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a id="button-forward" class="nav-link" href="/?page={{ nextPageNumber }}">Forward</a>
|
<a id="button-forward" class="nav-link" href="/?page={{ nextPageNumber }}">Forward</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item" {% if not gameInProgress %} style="opacity: 0.5" {% endif %}>
|
||||||
<a id="button-forward" class="nav-link" href="/balance-tool">Balance Tool</a>
|
<a id="button-forward" class="nav-link" href="/livegames">Livegames
|
||||||
|
<div style="font-size: small; color: red; opacity: 1; float: right; margin-left: 10px;">(experimental)</div>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
@@ -31,12 +33,15 @@
|
|||||||
<li class="nav-item right mr-2">
|
<li class="nav-item right mr-2">
|
||||||
<a class="nav-link" href="/rounds">Rounds</a>
|
<a class="nav-link" href="/rounds">Rounds</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item right mr-2">
|
||||||
|
<a class="nav-link" href="/maps">Maps</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item right">
|
<li class="nav-item right">
|
||||||
<input id="getPlayer" type="text" aria-label="search for player" class="mt-1"
|
<input id="getPlayer" type="text" aria-label="search for player" class="mt-1"
|
||||||
placeholder="search player...">
|
placeholder="search player...">
|
||||||
</li>
|
</li>
|
||||||
{{ findPlayer }}
|
{{ findPlayer }}
|
||||||
<!-- <li class="nav-item right">
|
<!--- <li class="nav-item right">
|
||||||
<input id="gotoRank" type="number" aria-label="goto rank"
|
<input id="gotoRank" type="number" aria-label="goto rank"
|
||||||
placeholder="goto rank...">
|
placeholder="goto rank...">
|
||||||
</li> -->
|
</li> -->
|
||||||
|
|||||||
@@ -14,17 +14,28 @@
|
|||||||
</h1>
|
</h1>
|
||||||
<h3>
|
<h3>
|
||||||
Rating: <i>{{ player.rating }}</i> <br>
|
Rating: <i>{{ player.rating }}</i> <br>
|
||||||
Rank: {{ player.rank }}
|
{% if player.rank == 0 %}
|
||||||
|
<i><small>Missing {{ 10 - player.games }} placement games!</small></i>
|
||||||
|
{% elif not player.lastGame %}
|
||||||
|
<i><small>Must play a game again before being assigned a rank!</small></i>
|
||||||
|
{% else %}
|
||||||
|
Rank: {{ player.rank }}
|
||||||
|
{%endif%}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="plot-container">
|
<div class="plot-container">
|
||||||
<canvas id="lineChart">
|
<canvas id="lineChart">
|
||||||
</canvas>
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-3 medal-container">
|
||||||
|
{% for m in medals %}
|
||||||
|
{{ m }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
<p class="mt-5 mb-3">
|
<p class="mt-5 mb-3">
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% include 'footer.html' %}
|
<!-- {% include 'footer.html' %}-->
|
||||||
<script defer>
|
<script defer>
|
||||||
var canvas = document.getElementById("lineChart")
|
var canvas = document.getElementById("lineChart")
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext('2d');
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Balance and Submission Tool</title>
|
|
||||||
<meta name="Description" content="Sheppy is awesome?">
|
|
||||||
<script defer src="/static/balance.js"></script>
|
|
||||||
{% include 'default_head_content.html' %}
|
|
||||||
</head>
|
|
||||||
<body class="bg-special">
|
|
||||||
{% include 'navbar.html' %}
|
|
||||||
<div class="container mt-3 mb-3" role="main">
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm">
|
|
||||||
<h1>Role Preference Submission Tool</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- player name field -->
|
|
||||||
<form action="/role-submission?id={{ ident }}" method="POST">
|
|
||||||
<p style="color: red; font-weight: bold"> PLEASE USE YOUR _CORRECTLY SPELLED_ LoL-NAME!!</p>
|
|
||||||
<input class="form-control pname m-3" type="text" placeholder="Player"
|
|
||||||
name="playername" id="playername">
|
|
||||||
|
|
||||||
<!-- fast postition slection field -->
|
|
||||||
<input class="form-control fastpos m-3" type="text"
|
|
||||||
placeholder="Fast Position Input"
|
|
||||||
id="fastpos-submission">
|
|
||||||
|
|
||||||
<div class="col-sm m-3" style="min-width: 300px;">
|
|
||||||
<!-- checkboxes for pos -->
|
|
||||||
{% for pos in positions %}
|
|
||||||
<div>
|
|
||||||
<label style="min-width: 100px;"
|
|
||||||
for="prio_{{ pos }}">{{ pos }}</label>
|
|
||||||
<select name="prio_{{ pos }}" id="prio_{{ pos }}"
|
|
||||||
class="form-select ml-3 mr-3">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
<option value="4">4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<input type="submit" value="Submit">
|
|
||||||
|
|
||||||
<div class="mt-5">
|
|
||||||
<h4>Priorität</h4>
|
|
||||||
<p>
|
|
||||||
1 = höchste </br>
|
|
||||||
5 = niedrigste </br>
|
|
||||||
</p>
|
|
||||||
<hr class="my-3">
|
|
||||||
<h4>Fast-Position</h4>
|
|
||||||
<p>
|
|
||||||
<b>Positionen können in den Kurzschreibweisen: top, mid, bot, jungle, support mit "=" und ">" angegeben werden. Zum Beispiel:</b></br></br>
|
|
||||||
top > mid > top = adc</br>
|
|
||||||
mid = top > bot</br>
|
|
||||||
support > jungle</br>
|
|
||||||
etc..</br>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% include 'footer.html' %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -41,6 +41,9 @@
|
|||||||
<div class="col-sm" style="overflow: hidden;">
|
<div class="col-sm" style="overflow: hidden;">
|
||||||
<a href="/player?id={{ p.playerId }}">{{ p.name }}</a>
|
<a href="/player?id={{ p.playerId }}">{{ p.name }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
{{ p.participation }}%
|
||||||
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
{% if not r.invalid %}
|
{% if not r.invalid %}
|
||||||
<small style="color: green;">
|
<small style="color: green;">
|
||||||
@@ -57,6 +60,9 @@
|
|||||||
<div class="col-sm" style="overflow: hidden;">
|
<div class="col-sm" style="overflow: hidden;">
|
||||||
<a href="/player?id={{ p.playerId }}">{{ p.name }}</a>
|
<a href="/player?id={{ p.playerId }}">{{ p.name }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
{{ p.participation }}%
|
||||||
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
{% if not r.invalid %}
|
{% if not r.invalid %}
|
||||||
<small style="color: red;">
|
<small style="color: red;">
|
||||||
|
|||||||
Reference in New Issue
Block a user