Transpose table of results

This commit is contained in:
Bill Thiede 2025-12-03 10:29:52 -08:00
parent 9a76b0496f
commit d1bdecf5e7

View File

@ -968,6 +968,21 @@ class HTMLGenerator:
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 {{
width: 100%;
border-collapse: collapse;
@ -1141,93 +1156,103 @@ class HTMLGenerator:
<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()):
html += f"""
<div class="day-section">
<h3 class="day-header">Day {day}</h3>
"""
# Generate content for each part
for part in sorted(data[year][day].keys()):
part_data = data[year][day][part]
day_part_combos.append((day, part))
if not part_data:
if not day_part_combos:
html += "<p>No data available for this year.</p>"
html += "</div>"
continue
# Find fastest and slowest (using total time)
# 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:
# Backward compatibility with old format
total_time = time_data if time_data > 0 else 0
if total_time > 0:
times.append((user, time_data, total_time))
times.append(total_time)
if times:
fastest_times[(day, part)] = min(times)
if not times:
continue
times.sort(key=lambda x: x[2]) # Sort by total time
fastest_time = times[0][2]
slowest_time = times[-1][2]
# Get git rev and repo_url for historical data link
first_user_data = times[0][1] if isinstance(times[0][1], dict) else {}
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>
# Create table with transposed structure
html += """
<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>
<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>
"""
# 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:
total_time = time_data if time_data > 0 else 0
user_times.append((user, time_data, total_time))
# 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 = []
sorted_users = sorted(user_times, key=lambda x: x[2] if x[2] > 0 else float('inf'))
for user, time_data, total_time_ns in sorted_users:
if total_time_ns == 0:
html += f"""
<tr>
<td>{user}</td>
<td class="no-data">No data</td>
<td class="no-data">-</td>
<td class="no-data">-</td>
<td class="no-data">-</td>
<td class="no-data">-</td>
</tr>
<td><strong>Day {day} Part {part}</strong></td>
"""
# Add timing data for each user
for user in sorted(users):
time_data = part_data.get(user, 0)
if time_data == 0 or (isinstance(time_data, dict) and time_data.get('total', 0) == 0):
html += ' <td class="no-data">-</td>\n'
else:
# Extract times and metadata
# Extract times
if isinstance(time_data, dict):
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:
# Backward compatibility
total_time_ns = time_data
runner_time_ns = total_time_ns
generator_time_ns = 0
git_rev = ''
@ -1243,55 +1268,14 @@ class HTMLGenerator:
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 = '-'
# Determine if fastest
cell_class = ""
if fastest_time > 0 and total_time_ns == fastest_time:
cell_class = "fastest"
# Get historical data for this user/day/part
historical = db.get_historical_results(user, year, day, part)
history_html = ""
history_link = ""
if len(historical) > 1:
history_items = []
for hist in historical[:10]: # Show last 10 runs
@ -1315,36 +1299,23 @@ class HTMLGenerator:
{''.join(history_items)}
</div>
'''
history_link = f'<span class="history-link" onclick="toggleHistory(\'{user}\', {year}, {day}, {part})">📊</span>'
else:
history_link = ""
row_history_htmls.append(history_html)
history_link = f' <span class="history-link" onclick="toggleHistory(\'{user}\', {year}, {day}, {part})">📊</span>'
html += f"""
<tr class="{row_class}">
<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 += f' <td class="time {cell_class}">{total_str}{history_link}</td>\n'
html += """ </tr>
"""
html += """
</tbody>
# Add history HTML after the row
for hist_html in row_history_htmls:
html += hist_html
html += """ </tbody>
</table>
</div>
"""
html += """
</div>
"""
html += """
</div>
"""
# Add summary statistics at the bottom
html += f"""
<div class="summary">