File size: 5,160 Bytes
cb0e846 0847ae1 e9919d6 a46d377 0847ae1 f6875cc c656e64 741a990 4c4c6d0 741a990 4c4c6d0 2026e50 f1afdb8 c656e64 1283fd6 c656e64 a46d377 4c4c6d0 a46d377 4c4c6d0 a46d377 4c4c6d0 a46d377 9266b25 a46d377 7e3ce91 a46d377 595f614 1f8c60c a46d377 d45cd69 2026e50 e4a7c66 c656e64 d45cd69 1283fd6 c656e64 cb1c711 595f614 267c93c a46d377 ab24a94 c656e64 1283fd6 a46d377 f8c689d a46d377 f8c689d b321754 a46d377 f6875cc a46d377 f6875cc a46d377 f6875cc a46d377 f6875cc a46d377 ab24a94 e7262f2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | from fasthtml.common import *
# using https://www.fastht.ml/docs/tutorials/by_example.html
app,rt = fast_app(pico=True)
## From HF
## Initial set of scores information
scores = {
# Team A
'A_goals': 0, # goals
'A_points': 0, # points
# Team B
'B_goals': 0, # goals
'B_points': 0, # points
}
# Track scores time series in memory
scores_ts = {}
scores_id = len(scores_ts)+1
scores_ts[scores_id] = {"scores": scores.copy()}
# Default team names
team_A = "Bishopstown"
team_B = "Other Team"
def create_score_button(team_code, score_type):
# Determine the unique ID for the button's target span
span_id = f"{team_code}_{score_type}"
# Determine the key to pass to the increment function
counter_name = f"{team_code}_{score_type}"
return Button(
Span(f"{scores[counter_name]}", id=span_id),
hx_post="/increment",
hx_target=f"#{span_id}",
hx_vals=f'{{"counter": "{counter_name}"}}',
hx_swap="innerHTML"
)
def create_score_section(team_code):
return (
H1(create_score_button(f"{team_code}", "goals"),
Span(" "),
create_score_button(f"{team_code}", "points"),
cls="card-title"),
)
verbose = False
@app.post("/increment")
def increment(counter: str):
if verbose: print("incrementing")
global scores
if counter in scores:
scores[counter] += 1
## Add new score to time series
global scores_ts
scores_id = len(scores_ts)
scores_ts[scores_id+1] = {"scores": scores.copy()}
## Return the text that is expected for the button update
return f"{scores[counter]}"
@app.post("/reset")
def reset_scores_and_page():
if verbose: print("reseting")
global scores
scores = {
# Team A
'A_goals': 0, # goals
'A_points': 0, # points
# Team B
'B_goals': 0, # goals
'B_points': 0, # points
}
global scores_ts
scores_ts = {}
scores_id = len(scores_ts)+1
scores_ts[scores_id] = {"scores": scores.copy()}
# Return a response to reload the table
return set_table(team_A, team_B)
@app.post("/reset_recent")
def reset_to_last_score_and_page():
if verbose: print("reseting to recent")
global scores
global scores_ts
## previous index
scores_id = len(scores_ts)
if scores_id > 1:
scores = scores_ts[scores_id-1]["scores"]
## Drop the latest entry in the score time series
#scores_ts[scores_id+1] = {"scores": scores.copy()}
scores_ts.pop(scores_id)
# Return a response to reload the score table
return set_table(team_A, team_B)
@rt
def index():
return Titled('GAA Score Keeper',
Div(
P('Enter the team names'),
Form(Input(name='team_name_A', value=team_A),
Input(name='team_name_B', value=team_B),
Button('Click'),
hx_post='/set_table', hx_target='#main'),
id='main'))
@rt
def set_table(team_name_A:str, team_name_B:str):
global team_A
global team_B
team_A = team_name_A ## Update global
team_B = team_name_B ## Update global
print("set_table called"+team_A+team_B)
return Main(
Div(
Table(
Tr(
Th(H2(team_A)),
Th(H2(team_B))
),
Tr(
Td(create_score_section(team_code = "A"),style="text-align: center;"),
Td(create_score_section(team_code = "B"),style="text-align: center;")
)
),
Br(),
Br(),
Div(
id="timer_display", hx_get="/timer",
hx_trigger="every 1s",
style="text-align: center; margin-top: 20px; cursor: pointer;"
),
style="flex-grow: 1;"
),
Div(
Button( Span("Undo"), hx_post="/reset_recent", hx_target='#main' ),
Button( Span("Toggle Clock"), hx_post="/timer_toggle", hx_target='#timer_display' ),
Button( Span("Full Reset"), hx_post="/reset", hx_target='#main' ),
style = "display: flex; justify-content: space-between;"
),
style="display: flex; flex-direction: column; min-height: 80vh;"
)
# Timer state
timer_state = {
'start_time': None,
'is_running': False
}
@app.get("/timer")
def get_timer():
import time
if timer_state['is_running'] and timer_state['start_time']:
elapsed = time.time() - timer_state['start_time']
minutes = int(elapsed // 60)
seconds = int(elapsed % 60)
color = "red" if minutes >= 30 else "green"
return Span(f"{minutes:02d}:{seconds:02d}", style=f"color: {color}; font-size: 2em;")
return Span("00:00", style="color: green; font-size: 2em;")
@app.post("/timer_toggle")
def toggle_timer():
import time
if timer_state['is_running']:
timer_state['is_running'] = False
else:
timer_state['start_time'] = time.time()
timer_state['is_running'] = True
return get_timer()
serve(port=7860) |