Compare commits

...

3 Commits

4 changed files with 126 additions and 75 deletions

View File

@@ -3,6 +3,8 @@ import typing
import peewee
import wordlinator.utils
db = peewee.PostgresqlDatabase(
os.getenv("DB_NAME", "wordlegolf"),
user=os.getenv("DB_USER", "wordlegolf"),
@@ -30,6 +32,12 @@ class User(BaseModel):
class Game(BaseModel):
game_id = peewee.AutoField()
game = peewee.IntegerField(null=False)
start_date = peewee.DateField(null=False)
class Player(BaseModel):
user_id = peewee.ForeignKeyField(User, "user_id", null=False)
game_id = peewee.ForeignKeyField(Game, "game_id", null=False)
class Hole(BaseModel):
@@ -65,11 +73,14 @@ class WordleDb:
def add_user(self, username, user_id):
return User.create(username=username, twitter_id=user_id)
def get_or_create_round(self, round_no):
def get_or_create_round(self, round_no, start_date=None):
try:
return Game.get(Game.game == round_no)
except peewee.DoesNotExist:
return Game.create(game=round_no)
start_date = (
start_date or wordlinator.utils.WORDLE_GOLF_ROUND_DATES[round_no - 1]
)
return Game.create(game=round_no, start_date=start_date)
def get_or_create_hole(self, round_no, hole_no):
round = self.get_or_create_round(round_no)
@@ -115,7 +126,13 @@ class WordleDb:
def get_scores(self, round_no):
round = self.get_or_create_round(round_no)
return list(Score.select().filter(Score.game_id == round.game_id))
res = (
Score.select(Score, Player.game_id)
.join(Player, on=(Score.user_id == Player.user_id))
.filter(Player.game_id == round.game_id)
.filter(Score.game_id == round.game_id)
)
return list(res)
def bulk_insert_scores(self, scores: typing.List[typing.Dict]):
with db.atomic():
@@ -131,15 +148,16 @@ class WordleDb:
hole = self.get_or_create_hole(round_no, hole_no)
# Find users who *have* played in this round,
# but have no score on the current hole
query_str = """SELECT username
query_str = """SELECT u.username, player.game_id
FROM user_tbl u
WHERE NOT EXISTS (
JOIN player ON player.user_id = u.user_id
WHERE (
player.game_id = {}
) AND NOT EXISTS (
SELECT FROM score WHERE score.user_id = u.user_id AND score.hole_id = {}
) AND EXISTS (
SELECT FROM score WHERE score.user_id = u.user_id AND score.game_id = {}
)
""".format(
hole.hole_id, hole.game_id
hole.game_id, hole.hole_id
)
if tweetable:

83
wordlinator/utils/web.py Normal file
View File

@@ -0,0 +1,83 @@
import collections
import typing
def golf_score(score_list: typing.List) -> int:
scores = [s.score for s in score_list]
score_count = len(scores)
score = sum(scores) - (score_count * 4)
return score
def get_user_scorelist(
username: str, scores: typing.List
) -> typing.Dict[str, typing.Any]:
scores = list(sorted(scores, key=lambda s: s.hole_id.hole))
return {
"Name": username,
"Score": golf_score(scores),
**{f"Hole {s.hole_id.hole}": s.score for s in scores},
}
def format_string(col, condition):
return "{" + col["id"] + "}" + f" {condition}"
def column_formats(col, pct):
return [
{
"if": {"column_id": col["id"]},
"maxWidth": f"{pct}%",
"width": f"{pct}%",
"minWidth": f"{pct}%",
},
{
"if": {
"column_id": col["id"],
"filter_query": format_string(col, "> 4"),
},
"backgroundColor": "red",
},
{
"if": {
"column_id": col["id"],
"filter_query": format_string(col, "= 4"),
},
"backgroundColor": "orange",
},
{
"if": {
"column_id": col["id"],
"filter_query": format_string(col, "< 4"),
},
"backgroundColor": "green",
},
{
"if": {
"column_id": col["id"],
"filter_query": format_string(col, "is nil"),
},
"backgroundColor": "white",
},
]
def table_rows(score_list):
scores_by_user = collections.defaultdict(list)
for score in score_list:
scores_by_user[score.user_id.username].append(score)
return [
get_user_scorelist(username, scores)
for username, scores in scores_by_user.items()
]
def column_formatting(hole_columns):
pct = round((100 - (10 + 5)) / len(hole_columns), 2)
return [
entry
for format_list in [column_formats(hole, pct) for hole in hole_columns]
for entry in format_list
]

View File

@@ -13,6 +13,7 @@ import plotly.graph_objs
import wordlinator.db.pg as db
import wordlinator.twitter
import wordlinator.utils
import wordlinator.utils.web
###################
# Setup Functions #
@@ -63,69 +64,9 @@ def scores_from_db():
#################
def _golf_score(score_list):
scores = [s.score for s in score_list]
score_count = len(scores)
score = sum(scores) - (score_count * 4)
return score
def _get_user_scorelist(username, scores):
scores = list(sorted(scores, key=lambda s: s.hole_id.hole))
return {
"Name": username,
"Score": _golf_score(scores),
**{f"Hole {s.hole_id.hole}": s.score for s in scores},
}
def _format_string(col, condition):
return "{" + col["id"] + "}" + f" {condition}"
def _column_formats(col):
return [
{
"if": {
"column_id": col["id"],
"filter_query": _format_string(col, "> 4"),
},
"backgroundColor": "red",
},
{
"if": {
"column_id": col["id"],
"filter_query": _format_string(col, "= 4"),
},
"backgroundColor": "orange",
},
{
"if": {
"column_id": col["id"],
"filter_query": _format_string(col, "< 4"),
},
"backgroundColor": "green",
},
{
"if": {
"column_id": col["id"],
"filter_query": _format_string(col, "is nil"),
},
"backgroundColor": "white",
},
]
def get_scores():
score_list = scores_from_db()
scores_by_user = collections.defaultdict(list)
for score in score_list:
scores_by_user[score.user_id.username].append(score)
table_rows = [
_get_user_scorelist(username, scores)
for username, scores in scores_by_user.items()
]
table_rows = wordlinator.utils.web.table_rows(score_list)
hole_columns = [
{"name": f"Hole {i}", "id": f"Hole {i}", "type": "numeric"}
@@ -137,13 +78,22 @@ def get_scores():
*hole_columns,
]
color_formatting = [
format_entry
for column_formats in [_column_formats(col) for col in hole_columns]
for format_entry in column_formats
]
color_formatting = wordlinator.utils.web.column_formatting(hole_columns)
formatting = [
{"if": {"column_id": "Name"}, "textAlign": "center"},
{
"if": {"column_id": "Name"},
"textAlign": "center",
"width": "10%",
"maxWidth": "10%",
"minWidth": "10%",
},
{
"if": {"column_id": "Score"},
"textAlign": "center",
"width": "5%",
"maxWidth": "5%",
"minWidth": "5%",
},
*color_formatting,
]
return dash.dash_table.DataTable(