mirror of
https://github.com/FAUSheppy/open-web-leaderboard.git
synced 2025-12-09 16:38:32 +01:00
Compare commits
32 Commits
6491afc272
...
ese-custom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d98016040 | ||
|
|
6a2ff6a72f | ||
|
|
ee61d1bb63 | ||
|
|
5c8191f4cf | ||
|
|
5dc1d16447 | ||
|
|
eb967900d0 | ||
|
|
bcb460bc24 | ||
|
|
02be6031a2 | ||
| a8da2b71bc | |||
| 7f8af681dd | |||
| 25ea0e03b5 | |||
| 7f845cc17c | |||
| 6a5b150cb8 | |||
| 82680cc0db | |||
| bdd24d68fa | |||
| cab9dceab7 | |||
| ead1a05c2e | |||
| 77e58305da | |||
| 9cdee90a7f | |||
| 0a1675c637 | |||
| f6ce5a9533 | |||
| 8f8eba81fa | |||
| 3a028607b4 | |||
| ca8dfb5208 | |||
|
|
3df3ade848 | ||
| 2ce48a7147 | |||
| 590763c613 | |||
| 5b8ab6fa78 | |||
| 1641332661 | |||
| bf31cb59e8 | |||
| a52bd66aed | |||
| 54f02c978a |
10
Round.py
10
Round.py
@@ -36,12 +36,12 @@ class Round:
|
|||||||
self.blacklist = True
|
self.blacklist = True
|
||||||
|
|
||||||
|
|
||||||
if winnerSide == 2:
|
if winnerSide == 1:
|
||||||
self.winnerSideString = "Security"
|
self.winnerSideString = "Red"
|
||||||
self.loserSideString = "Insurgent"
|
self.loserSideString = "Blue"
|
||||||
else:
|
else:
|
||||||
self.winnerSideString = "Insurgent"
|
self.winnerSideString = "Blue"
|
||||||
self.loserSideString = "Security"
|
self.loserSideString = "Red"
|
||||||
if mapName:
|
if mapName:
|
||||||
self.mapName = mapName
|
self.mapName = mapName
|
||||||
else:
|
else:
|
||||||
|
|||||||
113
api.py
Normal file
113
api.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/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
|
||||||
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 where games >= 10 and not lastgame is null")
|
cursor.execute("SELECT Count(*) FROM players")
|
||||||
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
|
||||||
sqlQuery = '''Select * FROM players where games >= 10
|
print(limit, start)
|
||||||
and not lastgame is null
|
sqlQuery = '''Select * FROM players where games >= 1
|
||||||
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,11 +121,8 @@ 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()
|
||||||
if(player.games < 10):
|
cursor.execute('''SELECT COUNT(*) from players
|
||||||
return -1
|
where (mu-2*sigma) > (?-2*?);''',
|
||||||
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
|
||||||
@@ -181,9 +178,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 ''',
|
||||||
|
|||||||
BIN
rounds.sqlite
BIN
rounds.sqlite
Binary file not shown.
50
rounds/2021-04-26-round-01.json
Normal file
50
rounds/2021-04-26-round-01.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-04-26-round-02.json
Normal file
50
rounds/2021-04-26-round-02.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-04-26-round-03.json
Normal file
50
rounds/2021-04-26-round-03.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
71
rounds/2021-05-24-round-01.json
Normal file
71
rounds/2021-05-24-round-01.json
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
72
rounds/2021-05-31-round-01.json
Normal file
72
rounds/2021-05-31-round-01.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
72
rounds/2021-05-31-round-02.json
Normal file
72
rounds/2021-05-31-round-02.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
71
rounds/2021-05-31-round-03.json
Normal file
71
rounds/2021-05-31-round-03.json
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-06-07-round-01.json
Normal file
50
rounds/2021-06-07-round-01.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-07-05-round-01.json
Normal file
50
rounds/2021-07-05-round-01.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-07-05-round-02.json
Normal file
50
rounds/2021-07-05-round-02.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
50
rounds/2021-07-05-round-03.json
Normal file
50
rounds/2021-07-05-round-03.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
7
rounds/all.sh
Normal file
7
rounds/all.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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
Normal file
13
rounds/data
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
1
|
||||||
|
24:16
|
||||||
|
TryhardYordle
|
||||||
|
ChessGM lbfxd
|
||||||
|
TheSlapstick
|
||||||
|
Vyne
|
||||||
|
ESE Felix
|
||||||
|
Phirop
|
||||||
|
xXxMarethyuxXx
|
||||||
|
iTrash
|
||||||
|
JuckF Bierhuhn
|
||||||
|
ENTAC
|
||||||
|
2021-04-25T22:00+02:00
|
||||||
44
rounds/gen.py
Executable file
44
rounds/gen.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/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))
|
||||||
252
server.py
252
server.py
@@ -4,15 +4,26 @@ 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
|
||||||
|
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
@@ -115,7 +126,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=7)
|
start = datetime.datetime.now() - datetime.timedelta(days=365)
|
||||||
end = datetime.datetime.now()
|
end = datetime.datetime.now()
|
||||||
else:
|
else:
|
||||||
start = datetime.datetime.fromtimestamp(start)
|
start = datetime.datetime.fromtimestamp(start)
|
||||||
@@ -133,6 +144,227 @@ 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'''
|
||||||
@@ -189,8 +421,7 @@ def player():
|
|||||||
Y_MIN=yMin, Y_MAX=yMax)
|
Y_MIN=yMin, Y_MAX=yMax)
|
||||||
|
|
||||||
@app.route('/leaderboard')
|
@app.route('/leaderboard')
|
||||||
@app.route('/')
|
@cache.cached(timeout=10, query_string=True)
|
||||||
@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'''
|
||||||
|
|
||||||
@@ -245,6 +476,7 @@ 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)
|
||||||
@@ -274,12 +506,11 @@ def send_js(path):
|
|||||||
|
|
||||||
@app.before_first_request
|
@app.before_first_request
|
||||||
def init():
|
def init():
|
||||||
SERVERS_FILE = "servers.json"
|
|
||||||
if os.path.isfile(SERVERS_FILE):
|
global WATCHER
|
||||||
import valve.source.a2s
|
with open("key.txt","r") as f:
|
||||||
from valve.source import NoResponseError
|
key = f.read().strip()
|
||||||
with open(SERVERS_FILE) as f:
|
WATCHER = riotwatcher.LolWatcher(key)
|
||||||
SERVERS = json.load(f)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Start open-leaderboard', \
|
parser = argparse.ArgumentParser(description='Start open-leaderboard', \
|
||||||
@@ -289,9 +520,10 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('--port', default="5002", \
|
parser.add_argument('--port', default="5002", \
|
||||||
help='Port on which flask (this server) will take requests on')
|
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)')
|
parser.add_argument('--skillbird-db', required=False, help='skillbird database (overrides web connection if set)')
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
5
sqlite.init
Normal file
5
sqlite.init
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE players(
|
||||||
|
playerName TEXT PRIMARY KEY,
|
||||||
|
rating INTEGER,
|
||||||
|
lastupdated TEXT
|
||||||
|
);
|
||||||
300
static/balance.js
Normal file
300
static/balance.js
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
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,6 +8,12 @@ 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;
|
||||||
|
|||||||
41
templates/balance_response_partial.html
Normal file
41
templates/balance_response_partial.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<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,25 +10,6 @@
|
|||||||
{% 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(){
|
|
||||||
fetch("/players-online").then(
|
|
||||||
response => response.json()
|
|
||||||
).then(
|
|
||||||
data => {
|
|
||||||
if(data["error"] == ""){
|
|
||||||
document.getElementById("playerDisplay").innerHTML = "Players Online: " + data["player_total"]
|
|
||||||
}else{
|
|
||||||
document.getElementById("playerDisplay").innerHTML = "Players Online: (error)" + data["error"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
players()
|
|
||||||
setInterval(players, 2000)
|
|
||||||
</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://blog.atlantishq.de/about">Impressum/Legal</a>
|
class="footerLink" href="https://atlantishq.de/impressum">Impressum/Legal</a>
|
||||||
<a style="color: rgba(255,255,255,.5);"
|
<a style="color: rgba(255,255,255,.5);"
|
||||||
class="footerLink mid" href="steam://connect/athq.de/:27026">
|
class="footerLink mid" href="https://esports-erlangen.de">
|
||||||
Join the Server!</a>
|
ESE Website</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>
|
||||||
|
|||||||
150
templates/json_builder.html
Normal file
150
templates/json_builder.html
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<!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,28 +10,13 @@
|
|||||||
<!-- 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="/">Leaderboard</a>
|
<a class="nav-link" href="/">New Balance</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,10 +18,8 @@
|
|||||||
<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" {% if not gameInProgress %} style="opacity: 0.5" {% endif %}>
|
<li class="nav-item">
|
||||||
<a id="button-forward" class="nav-link" href="/livegames">Livegames
|
<a id="button-forward" class="nav-link" href="/balance-tool">Balance Tool</a>
|
||||||
<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">
|
||||||
@@ -33,15 +31,12 @@
|
|||||||
<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,13 +14,7 @@
|
|||||||
</h1>
|
</h1>
|
||||||
<h3>
|
<h3>
|
||||||
Rating: <i>{{ player.rating }}</i> <br>
|
Rating: <i>{{ player.rating }}</i> <br>
|
||||||
{% if player.rank == 0 %}
|
Rank: {{ player.rank }}
|
||||||
<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">
|
||||||
|
|||||||
70
templates/role_submission.html
Normal file
70
templates/role_submission.html
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<!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,9 +41,6 @@
|
|||||||
<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;">
|
||||||
@@ -60,9 +57,6 @@
|
|||||||
<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