Transpose table of results
This commit is contained in:
parent
9a76b0496f
commit
d1bdecf5e7
339
aocsync.py
339
aocsync.py
@ -968,6 +968,21 @@ class HTMLGenerator:
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
th small {{
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 0.7em;
|
||||||
|
}}
|
||||||
|
|
||||||
|
th small a {{
|
||||||
|
color: #fff;
|
||||||
|
opacity: 0.8;
|
||||||
|
}}
|
||||||
|
|
||||||
|
th small a:hover {{
|
||||||
|
opacity: 1;
|
||||||
|
text-decoration: underline;
|
||||||
|
}}
|
||||||
|
|
||||||
table {{
|
table {{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
@ -1141,207 +1156,163 @@ class HTMLGenerator:
|
|||||||
<h2 class="year-header">Year {year}</h2>
|
<h2 class="year-header">Year {year}</h2>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Generate content for each day
|
# Collect all day/part combinations for this year
|
||||||
|
day_part_combos = []
|
||||||
for day in sorted(data[year].keys()):
|
for day in sorted(data[year].keys()):
|
||||||
|
for part in sorted(data[year][day].keys()):
|
||||||
|
day_part_combos.append((day, part))
|
||||||
|
|
||||||
|
if not day_part_combos:
|
||||||
|
html += "<p>No data available for this year.</p>"
|
||||||
|
html += "</div>"
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Collect user info (git rev, repo_url) for header
|
||||||
|
user_info = {}
|
||||||
|
for day, part in day_part_combos:
|
||||||
|
part_data = data[year][day][part]
|
||||||
|
for user in users:
|
||||||
|
if user not in user_info:
|
||||||
|
user_info[user] = {'git_rev': '', 'repo_url': ''}
|
||||||
|
if user in part_data:
|
||||||
|
time_data = part_data[user]
|
||||||
|
if isinstance(time_data, dict):
|
||||||
|
if not user_info[user]['git_rev']:
|
||||||
|
user_info[user]['git_rev'] = time_data.get('git_rev', '')
|
||||||
|
if not user_info[user]['repo_url']:
|
||||||
|
user_info[user]['repo_url'] = time_data.get('repo_url', '')
|
||||||
|
|
||||||
|
# Find fastest times per day/part for highlighting
|
||||||
|
fastest_times = {}
|
||||||
|
for day, part in day_part_combos:
|
||||||
|
part_data = data[year][day][part]
|
||||||
|
times = []
|
||||||
|
for user, time_data in part_data.items():
|
||||||
|
if isinstance(time_data, dict):
|
||||||
|
total_time = time_data.get('total', 0)
|
||||||
|
else:
|
||||||
|
total_time = time_data if time_data > 0 else 0
|
||||||
|
if total_time > 0:
|
||||||
|
times.append(total_time)
|
||||||
|
if times:
|
||||||
|
fastest_times[(day, part)] = min(times)
|
||||||
|
|
||||||
|
# Create table with transposed structure
|
||||||
|
html += """
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Day/Part</th>
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Add user columns with git rev in header
|
||||||
|
for user in sorted(users):
|
||||||
|
git_rev = user_info[user]['git_rev']
|
||||||
|
repo_url = user_info[user]['repo_url']
|
||||||
|
|
||||||
|
if git_rev and repo_url:
|
||||||
|
commit_url = repo_url.rstrip('/') + '/commit/' + git_rev
|
||||||
|
git_rev_html = f'<br><small><a href="{commit_url}" target="_blank" title="View commit">{git_rev[:7]}</a></small>'
|
||||||
|
elif git_rev:
|
||||||
|
git_rev_html = f'<br><small>{git_rev[:7]}</small>'
|
||||||
|
else:
|
||||||
|
git_rev_html = ''
|
||||||
|
|
||||||
|
html += f' <th>{user}{git_rev_html}</th>\n'
|
||||||
|
|
||||||
|
html += """ </tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Add rows for each day/part combination
|
||||||
|
for day, part in day_part_combos:
|
||||||
|
part_data = data[year][day][part]
|
||||||
|
fastest_time = fastest_times.get((day, part), 0)
|
||||||
|
row_history_htmls = []
|
||||||
|
|
||||||
html += f"""
|
html += f"""
|
||||||
<div class="day-section">
|
<tr>
|
||||||
<h3 class="day-header">Day {day}</h3>
|
<td><strong>Day {day} Part {part}</strong></td>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Generate content for each part
|
# Add timing data for each user
|
||||||
for part in sorted(data[year][day].keys()):
|
for user in sorted(users):
|
||||||
part_data = data[year][day][part]
|
time_data = part_data.get(user, 0)
|
||||||
|
|
||||||
if not part_data:
|
if time_data == 0 or (isinstance(time_data, dict) and time_data.get('total', 0) == 0):
|
||||||
continue
|
html += ' <td class="no-data">-</td>\n'
|
||||||
|
else:
|
||||||
# Find fastest and slowest (using total time)
|
# Extract times
|
||||||
times = []
|
|
||||||
for user, time_data in part_data.items():
|
|
||||||
if isinstance(time_data, dict):
|
if isinstance(time_data, dict):
|
||||||
total_time = time_data.get('total', 0)
|
total_time_ns = time_data.get('total', 0)
|
||||||
|
runner_time_ns = time_data.get('runner', 0)
|
||||||
|
generator_time_ns = time_data.get('generator', 0)
|
||||||
|
git_rev = time_data.get('git_rev', '')
|
||||||
|
repo_url = time_data.get('repo_url', '')
|
||||||
else:
|
else:
|
||||||
# Backward compatibility with old format
|
# Backward compatibility
|
||||||
total_time = time_data if time_data > 0 else 0
|
total_time_ns = time_data
|
||||||
if total_time > 0:
|
runner_time_ns = total_time_ns
|
||||||
times.append((user, time_data, total_time))
|
generator_time_ns = 0
|
||||||
|
git_rev = ''
|
||||||
if not times:
|
repo_url = ''
|
||||||
continue
|
|
||||||
|
# Format total time
|
||||||
times.sort(key=lambda x: x[2]) # Sort by total time
|
total_ms = total_time_ns / 1_000_000
|
||||||
fastest_time = times[0][2]
|
total_us = total_time_ns / 1_000
|
||||||
slowest_time = times[-1][2]
|
if total_ms >= 1:
|
||||||
|
total_str = f"{total_ms:.2f} ms"
|
||||||
# Get git rev and repo_url for historical data link
|
elif total_us >= 1:
|
||||||
first_user_data = times[0][1] if isinstance(times[0][1], dict) else {}
|
total_str = f"{total_us:.2f} μs"
|
||||||
sample_git_rev = first_user_data.get('git_rev', '')
|
|
||||||
sample_repo_url = first_user_data.get('repo_url', '')
|
|
||||||
|
|
||||||
html += f"""
|
|
||||||
<div class="part-section">
|
|
||||||
<h4 class="part-header">Part {part}</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>User</th>
|
|
||||||
<th>Total Time</th>
|
|
||||||
<th>Generator</th>
|
|
||||||
<th>Runner</th>
|
|
||||||
<th>Git Rev</th>
|
|
||||||
<th>Relative Speed</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Sort users by total time (include all users, even if no data)
|
|
||||||
user_times = []
|
|
||||||
for user in users:
|
|
||||||
time_data = part_data.get(user, 0)
|
|
||||||
if isinstance(time_data, dict):
|
|
||||||
total_time = time_data.get('total', 0)
|
|
||||||
else:
|
else:
|
||||||
total_time = time_data if time_data > 0 else 0
|
total_str = f"{total_time_ns} ns"
|
||||||
user_times.append((user, time_data, total_time))
|
|
||||||
|
# Determine if fastest
|
||||||
sorted_users = sorted(user_times, key=lambda x: x[2] if x[2] > 0 else float('inf'))
|
cell_class = ""
|
||||||
|
if fastest_time > 0 and total_time_ns == fastest_time:
|
||||||
for user, time_data, total_time_ns in sorted_users:
|
cell_class = "fastest"
|
||||||
if total_time_ns == 0:
|
|
||||||
html += f"""
|
# Get historical data for this user/day/part
|
||||||
<tr>
|
historical = db.get_historical_results(user, year, day, part)
|
||||||
<td>{user}</td>
|
history_link = ""
|
||||||
<td class="no-data">No data</td>
|
if len(historical) > 1:
|
||||||
<td class="no-data">-</td>
|
history_items = []
|
||||||
<td class="no-data">-</td>
|
for hist in historical[:10]: # Show last 10 runs
|
||||||
<td class="no-data">-</td>
|
hist_total = hist['time_ns'] + hist.get('generator_time_ns', 0)
|
||||||
<td class="no-data">-</td>
|
hist_ms = hist_total / 1_000_000
|
||||||
</tr>
|
hist_us = hist_total / 1_000
|
||||||
"""
|
if hist_ms >= 1:
|
||||||
else:
|
hist_time_str = f"{hist_ms:.2f} ms"
|
||||||
# Extract times and metadata
|
elif hist_us >= 1:
|
||||||
if isinstance(time_data, dict):
|
hist_time_str = f"{hist_us:.2f} μs"
|
||||||
runner_time_ns = time_data.get('runner', 0)
|
else:
|
||||||
generator_time_ns = time_data.get('generator', 0)
|
hist_time_str = f"{hist_total} ns"
|
||||||
git_rev = time_data.get('git_rev', '')
|
|
||||||
repo_url = time_data.get('repo_url', '')
|
|
||||||
else:
|
|
||||||
# Backward compatibility
|
|
||||||
runner_time_ns = total_time_ns
|
|
||||||
generator_time_ns = 0
|
|
||||||
git_rev = ''
|
|
||||||
repo_url = ''
|
|
||||||
|
|
||||||
# Format total time
|
|
||||||
total_ms = total_time_ns / 1_000_000
|
|
||||||
total_us = total_time_ns / 1_000
|
|
||||||
if total_ms >= 1:
|
|
||||||
total_str = f"{total_ms:.2f} ms"
|
|
||||||
elif total_us >= 1:
|
|
||||||
total_str = f"{total_us:.2f} μs"
|
|
||||||
else:
|
|
||||||
total_str = f"{total_time_ns} ns"
|
|
||||||
|
|
||||||
# Format generator time
|
|
||||||
gen_ms = generator_time_ns / 1_000_000
|
|
||||||
gen_us = generator_time_ns / 1_000
|
|
||||||
if gen_ms >= 1:
|
|
||||||
gen_str = f"{gen_ms:.2f} ms"
|
|
||||||
elif gen_us >= 1:
|
|
||||||
gen_str = f"{gen_us:.2f} μs"
|
|
||||||
elif generator_time_ns > 0:
|
|
||||||
gen_str = f"{generator_time_ns} ns"
|
|
||||||
else:
|
|
||||||
gen_str = "-"
|
|
||||||
|
|
||||||
# Format runner time
|
|
||||||
run_ms = runner_time_ns / 1_000_000
|
|
||||||
run_us = runner_time_ns / 1_000
|
|
||||||
if run_ms >= 1:
|
|
||||||
run_str = f"{run_ms:.2f} ms"
|
|
||||||
elif run_us >= 1:
|
|
||||||
run_str = f"{run_us:.2f} μs"
|
|
||||||
else:
|
|
||||||
run_str = f"{runner_time_ns} ns"
|
|
||||||
|
|
||||||
# Calculate relative speed (based on total time)
|
|
||||||
if fastest_time > 0:
|
|
||||||
relative = total_time_ns / fastest_time
|
|
||||||
relative_str = f"{relative:.2f}x"
|
|
||||||
else:
|
|
||||||
relative_str = "-"
|
|
||||||
|
|
||||||
# Determine if fastest or slowest
|
|
||||||
row_class = ""
|
|
||||||
if total_time_ns == fastest_time:
|
|
||||||
row_class = "fastest"
|
|
||||||
elif total_time_ns == slowest_time and len(times) > 1:
|
|
||||||
row_class = "slowest"
|
|
||||||
|
|
||||||
# Format git rev with link if available
|
|
||||||
if git_rev and repo_url:
|
|
||||||
# Create link to commit
|
|
||||||
commit_url = repo_url.rstrip('/') + '/commit/' + git_rev
|
|
||||||
git_rev_html = f'<a href="{commit_url}" target="_blank" title="View commit">{git_rev[:7]}</a>'
|
|
||||||
elif git_rev:
|
|
||||||
git_rev_html = git_rev[:7]
|
|
||||||
else:
|
|
||||||
git_rev_html = '-'
|
|
||||||
|
|
||||||
# Get historical data for this user/day/part
|
|
||||||
historical = db.get_historical_results(user, year, day, part)
|
|
||||||
history_html = ""
|
|
||||||
if len(historical) > 1:
|
|
||||||
history_items = []
|
|
||||||
for hist in historical[:10]: # Show last 10 runs
|
|
||||||
hist_total = hist['time_ns'] + hist.get('generator_time_ns', 0)
|
|
||||||
hist_ms = hist_total / 1_000_000
|
|
||||||
hist_us = hist_total / 1_000
|
|
||||||
if hist_ms >= 1:
|
|
||||||
hist_time_str = f"{hist_ms:.2f} ms"
|
|
||||||
elif hist_us >= 1:
|
|
||||||
hist_time_str = f"{hist_us:.2f} μs"
|
|
||||||
else:
|
|
||||||
hist_time_str = f"{hist_total} ns"
|
|
||||||
|
|
||||||
hist_git = hist.get('git_rev', '')[:7] if hist.get('git_rev') else '-'
|
|
||||||
hist_date = hist.get('timestamp', '')[:16] if hist.get('timestamp') else ''
|
|
||||||
history_items.append(f'<div class="history-item">{hist_date}: {hist_time_str} ({hist_git})</div>')
|
|
||||||
|
|
||||||
history_html = f'''
|
hist_git = hist.get('git_rev', '')[:7] if hist.get('git_rev') else '-'
|
||||||
|
hist_date = hist.get('timestamp', '')[:16] if hist.get('timestamp') else ''
|
||||||
|
history_items.append(f'<div class="history-item">{hist_date}: {hist_time_str} ({hist_git})</div>')
|
||||||
|
|
||||||
|
history_html = f'''
|
||||||
<div class="history-data" id="history-{user}-{year}-{day}-{part}">
|
<div class="history-data" id="history-{user}-{year}-{day}-{part}">
|
||||||
<strong>History:</strong>
|
<strong>History:</strong>
|
||||||
{''.join(history_items)}
|
{''.join(history_items)}
|
||||||
</div>
|
</div>
|
||||||
'''
|
'''
|
||||||
history_link = f'<span class="history-link" onclick="toggleHistory(\'{user}\', {year}, {day}, {part})">📊</span>'
|
row_history_htmls.append(history_html)
|
||||||
else:
|
history_link = f' <span class="history-link" onclick="toggleHistory(\'{user}\', {year}, {day}, {part})">📊</span>'
|
||||||
history_link = ""
|
|
||||||
|
html += f' <td class="time {cell_class}">{total_str}{history_link}</td>\n'
|
||||||
html += f"""
|
|
||||||
<tr class="{row_class}">
|
html += """ </tr>
|
||||||
<td>{user}{history_link}</td>
|
|
||||||
<td class="time">{total_str}</td>
|
|
||||||
<td class="time">{gen_str}</td>
|
|
||||||
<td class="time">{run_str}</td>
|
|
||||||
<td>{git_rev_html}</td>
|
|
||||||
<td>{relative_str}</td>
|
|
||||||
</tr>
|
|
||||||
{history_html}
|
|
||||||
"""
|
|
||||||
|
|
||||||
html += """
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
html += """
|
# Add history HTML after the row
|
||||||
</div>
|
for hist_html in row_history_htmls:
|
||||||
"""
|
html += hist_html
|
||||||
|
|
||||||
html += """
|
html += """ </tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user