Compare commits
3 Commits
4b4dfa69fd
...
e94d0a7714
| Author | SHA1 | Date | |
|---|---|---|---|
| e94d0a7714 | |||
| feeaba2c65 | |||
| 48d42c2a4b |
@@ -115,6 +115,9 @@ def _save_db_scores(
|
|||||||
async def main_update(
|
async def main_update(
|
||||||
wordle_day: wordlinator.utils.WordleDay = wordlinator.utils.WORDLE_TODAY,
|
wordle_day: wordlinator.utils.WordleDay = wordlinator.utils.WORDLE_TODAY,
|
||||||
):
|
):
|
||||||
|
if not wordle_day.golf_hole:
|
||||||
|
rich.print(f"[yellow]{wordle_day.date} isn't a #WordleGolf day!")
|
||||||
|
exit()
|
||||||
sheets_client = wordlinator.sheets.SheetsClient(wordle_day=wordle_day)
|
sheets_client = wordlinator.sheets.SheetsClient(wordle_day=wordle_day)
|
||||||
|
|
||||||
today_scores = await get_scores(wordle_day=wordle_day)
|
today_scores = await get_scores(wordle_day=wordle_day)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import datetime
|
||||||
import os
|
import os
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
@@ -25,6 +26,9 @@ class User(BaseModel):
|
|||||||
twitter_id = peewee.CharField(unique=True)
|
twitter_id = peewee.CharField(unique=True)
|
||||||
check_twitter = peewee.BooleanField(default=True)
|
check_twitter = peewee.BooleanField(default=True)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<User {self.username}, Check Twitter: {self.check_twitter}>"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table_name = "user_tbl"
|
table_name = "user_tbl"
|
||||||
|
|
||||||
@@ -34,6 +38,13 @@ class Game(BaseModel):
|
|||||||
game = peewee.IntegerField(null=False)
|
game = peewee.IntegerField(null=False)
|
||||||
start_date = peewee.DateField(null=False)
|
start_date = peewee.DateField(null=False)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Game: Round {self.game}, Start {self.start_date}>"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_date(self):
|
||||||
|
return self.start_date + datetime.timedelta(days=17)
|
||||||
|
|
||||||
|
|
||||||
class Player(BaseModel):
|
class Player(BaseModel):
|
||||||
user_id = peewee.ForeignKeyField(User, "user_id", null=False)
|
user_id = peewee.ForeignKeyField(User, "user_id", null=False)
|
||||||
@@ -45,6 +56,9 @@ class Hole(BaseModel):
|
|||||||
hole = peewee.IntegerField(null=False)
|
hole = peewee.IntegerField(null=False)
|
||||||
game_id = peewee.ForeignKeyField(Game, "game_id", null=False)
|
game_id = peewee.ForeignKeyField(Game, "game_id", null=False)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Hole #{self.hole}>"
|
||||||
|
|
||||||
|
|
||||||
class Score(BaseModel):
|
class Score(BaseModel):
|
||||||
score = peewee.IntegerField(null=False)
|
score = peewee.IntegerField(null=False)
|
||||||
@@ -74,6 +88,9 @@ class WordleDb:
|
|||||||
def add_user(self, username, user_id):
|
def add_user(self, username, user_id):
|
||||||
return User.create(username=username, twitter_id=user_id)
|
return User.create(username=username, twitter_id=user_id)
|
||||||
|
|
||||||
|
def get_rounds(self):
|
||||||
|
return list(sorted(Game.select(), key=lambda d: d.start_date))
|
||||||
|
|
||||||
def get_or_create_round(self, round_no, start_date=None):
|
def get_or_create_round(self, round_no, start_date=None):
|
||||||
try:
|
try:
|
||||||
return Game.get(Game.game == round_no)
|
return Game.get(Game.game == round_no)
|
||||||
@@ -127,8 +144,13 @@ class WordleDb:
|
|||||||
hole_id=hole.hole_id,
|
hole_id=hole.hole_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_scores(self, round_no):
|
def get_scores(self, round_no=None, round_id=None):
|
||||||
round = self.get_or_create_round(round_no)
|
if round_no:
|
||||||
|
round = self.get_or_create_round(round_no)
|
||||||
|
elif round_id:
|
||||||
|
round = Game.get_by_id(round_id)
|
||||||
|
else:
|
||||||
|
raise ValueError("Must provide Round Number or Round ID")
|
||||||
res = (
|
res = (
|
||||||
Score.select(
|
Score.select(
|
||||||
Score,
|
Score,
|
||||||
|
|||||||
@@ -1,3 +1,28 @@
|
|||||||
|
from dash import dcc
|
||||||
|
|
||||||
|
###############
|
||||||
|
# Date Helper #
|
||||||
|
###############
|
||||||
|
|
||||||
|
|
||||||
|
def _date_range(game):
|
||||||
|
return f"{game.start_date} to {game.end_date}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_date_dropdown(dates):
|
||||||
|
options = [
|
||||||
|
{"label": f"Round {d.game} ({_date_range(d)})", "value": d.game_id}
|
||||||
|
for d in dates
|
||||||
|
]
|
||||||
|
|
||||||
|
return dcc.Dropdown(
|
||||||
|
id="round-selector-dropdown",
|
||||||
|
options=options,
|
||||||
|
value=dates[-1].game_id,
|
||||||
|
clearable=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Formatting Helpers #
|
# Formatting Helpers #
|
||||||
######################
|
######################
|
||||||
|
|||||||
@@ -36,17 +36,25 @@ long_callback_manager = dash.long_callback.DiskcacheLongCallbackManager(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache()
|
||||||
|
def _games_from_db(ttl_hash=None):
|
||||||
|
return db.WordleDb().get_rounds()
|
||||||
|
|
||||||
|
|
||||||
|
def games_from_db():
|
||||||
|
return _games_from_db()
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache()
|
||||||
def _wordle_today(ttl_hash=None):
|
def _wordle_today(ttl_hash=None):
|
||||||
today = wordlinator.utils.get_wordle_today()
|
today = wordlinator.utils.get_wordle_today()
|
||||||
if today.golf_hole:
|
if today.golf_hole:
|
||||||
return today
|
return today
|
||||||
last_completed_round = [
|
last_completed_round = [
|
||||||
dt for dt in wordlinator.utils.WORDLE_GOLF_ROUND_DATES[::-1] if dt <= today.date
|
game for game in games_from_db()[::-1] if game.start_date <= today.date
|
||||||
]
|
]
|
||||||
last_round_start = last_completed_round[0]
|
last_round = last_completed_round[0]
|
||||||
last_round_end = last_round_start + datetime.timedelta(days=17)
|
return wordlinator.utils.WordleDay.from_date(last_round.end_date)
|
||||||
return wordlinator.utils.WordleDay.from_date(last_round_end)
|
|
||||||
|
|
||||||
|
|
||||||
def wordle_today():
|
def wordle_today():
|
||||||
@@ -54,13 +62,14 @@ def wordle_today():
|
|||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache()
|
||||||
def _scores_from_db(ttl_hash=None):
|
def _scores_from_db(round_id, ttl_hash=None):
|
||||||
wordle_day = wordle_today()
|
return db.WordleDb().get_scores(round_id=round_id)
|
||||||
return db.WordleDb().get_scores(wordle_day.golf_hole.game_no)
|
|
||||||
|
|
||||||
|
|
||||||
def scores_from_db():
|
def scores_from_db(round_id):
|
||||||
return wordlinator.utils.scores.ScoreMatrix(_scores_from_db(get_ttl_hash()))
|
return wordlinator.utils.scores.ScoreMatrix(
|
||||||
|
_scores_from_db(round_id, get_ttl_hash())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
@@ -68,8 +77,8 @@ def scores_from_db():
|
|||||||
#################
|
#################
|
||||||
|
|
||||||
|
|
||||||
def get_scores():
|
def get_scores(round_id):
|
||||||
score_matrix = scores_from_db()
|
score_matrix = scores_from_db(round_id)
|
||||||
table_rows = score_matrix.user_rows(wordle_today())
|
table_rows = score_matrix.user_rows(wordle_today())
|
||||||
|
|
||||||
hole_columns = [
|
hole_columns = [
|
||||||
@@ -111,6 +120,7 @@ def get_scores():
|
|||||||
},
|
},
|
||||||
fixed_rows={"headers": True, "data": 0},
|
fixed_rows={"headers": True, "data": 0},
|
||||||
filter_action="native",
|
filter_action="native",
|
||||||
|
filter_options={"case": "insensitive"},
|
||||||
style_cell={"textAlign": "center"},
|
style_cell={"textAlign": "center"},
|
||||||
style_data={"width": "10%"},
|
style_data={"width": "10%"},
|
||||||
style_as_list_view=True,
|
style_as_list_view=True,
|
||||||
@@ -140,15 +150,15 @@ def _get_summary_rows(score_matrix):
|
|||||||
return [totals, averages]
|
return [totals, averages]
|
||||||
|
|
||||||
|
|
||||||
def _stats_dict():
|
def _stats_dict(round_id):
|
||||||
score_matrix = scores_from_db()
|
score_matrix = scores_from_db(round_id)
|
||||||
table_rows = [{"Score": k, **v} for k, v in score_matrix.score_breakdown().items()]
|
table_rows = [{"Score": k, **v} for k, v in score_matrix.score_breakdown().items()]
|
||||||
table_rows.extend(_get_summary_rows(score_matrix))
|
table_rows.extend(_get_summary_rows(score_matrix))
|
||||||
return table_rows
|
return table_rows
|
||||||
|
|
||||||
|
|
||||||
def get_daily_stats():
|
def get_daily_stats(round_id):
|
||||||
table_rows = _stats_dict()
|
table_rows = _stats_dict(round_id)
|
||||||
|
|
||||||
columns = [
|
columns = [
|
||||||
{"name": n, "id": n}
|
{"name": n, "id": n}
|
||||||
@@ -185,8 +195,8 @@ SCORE_COLOR_DICT = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_line_graph():
|
def get_line_graph(round_id):
|
||||||
rows = _stats_dict()
|
rows = _stats_dict(round_id)
|
||||||
figure = plotly.graph_objs.Figure()
|
figure = plotly.graph_objs.Figure()
|
||||||
total = [r for r in rows if r["Score"] == "Total"][0]
|
total = [r for r in rows if r["Score"] == "Total"][0]
|
||||||
rows = [r for r in rows if r["Score"] not in ("Total", "Daily Average")]
|
rows = [r for r in rows if r["Score"] not in ("Total", "Daily Average")]
|
||||||
@@ -222,6 +232,11 @@ def get_line_graph():
|
|||||||
app.layout = dash.html.Div(
|
app.layout = dash.html.Div(
|
||||||
children=[
|
children=[
|
||||||
dash.html.H1("#WordleGolf", style={"textAlign": "center"}, id="title"),
|
dash.html.H1("#WordleGolf", style={"textAlign": "center"}, id="title"),
|
||||||
|
dash.html.Div(
|
||||||
|
wordlinator.utils.web.get_date_dropdown(games_from_db()),
|
||||||
|
id="round-selector",
|
||||||
|
style={"maxWidth": "300px"},
|
||||||
|
),
|
||||||
dash.html.Div(
|
dash.html.Div(
|
||||||
[
|
[
|
||||||
dash.html.H2("User Scores", style={"textAlign": "center"}),
|
dash.html.H2("User Scores", style={"textAlign": "center"}),
|
||||||
@@ -246,29 +261,38 @@ app.layout = dash.html.Div(
|
|||||||
|
|
||||||
@app.long_callback(
|
@app.long_callback(
|
||||||
output=dash.dependencies.Output("user-scores", "children"),
|
output=dash.dependencies.Output("user-scores", "children"),
|
||||||
inputs=dash.dependencies.Input("title", "children"),
|
inputs=[
|
||||||
|
dash.dependencies.Input("title", "children"),
|
||||||
|
dash.dependencies.Input("round-selector-dropdown", "value"),
|
||||||
|
],
|
||||||
manager=long_callback_manager,
|
manager=long_callback_manager,
|
||||||
)
|
)
|
||||||
def get_scores_chart(_):
|
def get_scores_chart(_, round_id):
|
||||||
return get_scores()
|
return get_scores(round_id)
|
||||||
|
|
||||||
|
|
||||||
@app.long_callback(
|
@app.long_callback(
|
||||||
output=dash.dependencies.Output("daily-stats", "children"),
|
output=dash.dependencies.Output("daily-stats", "children"),
|
||||||
inputs=dash.dependencies.Input("title", "children"),
|
inputs=[
|
||||||
|
dash.dependencies.Input("title", "children"),
|
||||||
|
dash.dependencies.Input("round-selector-dropdown", "value"),
|
||||||
|
],
|
||||||
manager=long_callback_manager,
|
manager=long_callback_manager,
|
||||||
)
|
)
|
||||||
def get_stats_chart(_):
|
def get_stats_chart(_, round_id):
|
||||||
return get_daily_stats()
|
return get_daily_stats(round_id)
|
||||||
|
|
||||||
|
|
||||||
@app.long_callback(
|
@app.long_callback(
|
||||||
output=dash.dependencies.Output("stats-graph", "children"),
|
output=dash.dependencies.Output("stats-graph", "children"),
|
||||||
inputs=dash.dependencies.Input("title", "children"),
|
inputs=[
|
||||||
|
dash.dependencies.Input("title", "children"),
|
||||||
|
dash.dependencies.Input("round-selector-dropdown", "value"),
|
||||||
|
],
|
||||||
manager=long_callback_manager,
|
manager=long_callback_manager,
|
||||||
)
|
)
|
||||||
def get_stats_graph(_):
|
def get_stats_graph(_, round_id):
|
||||||
return get_line_graph()
|
return get_line_graph(round_id)
|
||||||
|
|
||||||
|
|
||||||
server = app.server
|
server = app.server
|
||||||
|
|||||||
Reference in New Issue
Block a user