Howieeeee commited on
Commit
c1f740b
·
verified ·
1 Parent(s): 77cc2fa

Create script.js

Browse files
Files changed (1) hide show
  1. script.js +214 -0
script.js ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const COL_ORDER = [
2
+ "Model Name",
3
+ "WorldScore-Static",
4
+ "WorldScore-Dynamic",
5
+ "Camera Control",
6
+ "Object Control",
7
+ "Content Alignment",
8
+ "3D Consistency",
9
+ "Photometric Consistency",
10
+ "Style Consistency",
11
+ "Subjective Quality",
12
+ "Motion Accuracy",
13
+ "Motion Magnitude",
14
+ "Motion Smoothness",
15
+ "Model Type",
16
+ "Ability",
17
+ "Sampled by",
18
+ "Evaluated by",
19
+ "Accessibility",
20
+ "Date",
21
+ ];
22
+
23
+ // 简单 CSV 解析(你的数据没有带逗号的字段,这样已经够用)
24
+ function parseCsv(text) {
25
+ const lines = text.trim().split(/\r?\n/);
26
+ const header = lines[0].split(",");
27
+ const rows = lines.slice(1).map((line) => {
28
+ if (!line.trim()) return null;
29
+ const parts = line.split(",");
30
+ const obj = {};
31
+ header.forEach((h, i) => {
32
+ obj[h.trim()] = (parts[i] || "").trim();
33
+ });
34
+ return obj;
35
+ }).filter(Boolean);
36
+ return { header, rows };
37
+ }
38
+
39
+ function parseMarkdownLink(s) {
40
+ const m = s.match(/^\[(.*?)\]\((.*?)\)$/);
41
+ if (m) {
42
+ return { text: m[1], url: m[2] };
43
+ }
44
+ return { text: s, url: null };
45
+ }
46
+
47
+ function isNumericColumn(colName) {
48
+ const numericCols = new Set([
49
+ "WorldScore-Static",
50
+ "WorldScore-Dynamic",
51
+ "Camera Control",
52
+ "Object Control",
53
+ "Content Alignment",
54
+ "3D Consistency",
55
+ "Photometric Consistency",
56
+ "Style Consistency",
57
+ "Subjective Quality",
58
+ "Motion Accuracy",
59
+ "Motion Magnitude",
60
+ "Motion Smoothness",
61
+ ]);
62
+ return numericCols.has(colName);
63
+ }
64
+
65
+ function buildTable(rows) {
66
+ const container = document.getElementById("table-container");
67
+ container.innerHTML = "";
68
+
69
+ const table = document.createElement("table");
70
+ table.className = "ws-table";
71
+
72
+ const thead = document.createElement("thead");
73
+ const headRow = document.createElement("tr");
74
+
75
+ const firstRow = rows[0] || {};
76
+ const cols = COL_ORDER.filter((c) => c in firstRow);
77
+
78
+ // 表头:全部 sortable
79
+ cols.forEach((col) => {
80
+ const th = document.createElement("th");
81
+ th.textContent = col;
82
+ th.classList.add("sortable");
83
+ th.dataset.col = col;
84
+
85
+ // 默认排序列:WorldScore-Static,标记为 desc
86
+ if (col === "WorldScore-Static") {
87
+ th.classList.add("desc");
88
+ }
89
+ headRow.appendChild(th);
90
+ });
91
+
92
+ thead.appendChild(headRow);
93
+ table.appendChild(thead);
94
+
95
+ const tbody = document.createElement("tbody");
96
+ table.appendChild(tbody);
97
+ container.appendChild(table);
98
+
99
+ // 内部函数:根据当前 rows 渲染 body
100
+ function renderBody(data) {
101
+ tbody.innerHTML = "";
102
+ data.forEach((row) => {
103
+ const tr = document.createElement("tr");
104
+ cols.forEach((col) => {
105
+ const td = document.createElement("td");
106
+ const val = row[col] ?? "";
107
+
108
+ if (col === "Model Name") {
109
+ const { text, url } = parseMarkdownLink(val);
110
+ if (url) {
111
+ const a = document.createElement("a");
112
+ a.href = url;
113
+ a.target = "_blank";
114
+ a.rel = "noopener noreferrer";
115
+ a.textContent = text;
116
+ td.appendChild(a);
117
+ } else {
118
+ td.textContent = text;
119
+ }
120
+ } else {
121
+ td.textContent = val;
122
+ }
123
+
124
+ tr.appendChild(td);
125
+ });
126
+ tbody.appendChild(tr);
127
+ });
128
+ }
129
+
130
+ // 当前排序状态
131
+ let currentSortCol = "WorldScore-Static";
132
+ let currentAsc = false; // 默认降序
133
+
134
+ // 根据列名和升降序排序,然后渲染
135
+ function sortAndRender(col, asc) {
136
+ const sorted = [...rows].sort((a, b) => {
137
+ const va = a[col] ?? "";
138
+ const vb = b[col] ?? "";
139
+
140
+ if (isNumericColumn(col)) {
141
+ const na = parseFloat(va);
142
+ const nb = parseFloat(vb);
143
+ if (isNaN(na) && isNaN(nb)) return 0;
144
+ if (isNaN(na)) return asc ? -1 : 1;
145
+ if (isNaN(nb)) return asc ? 1 : -1;
146
+ return asc ? na - nb : nb - na;
147
+ } else {
148
+ return asc
149
+ ? String(va).localeCompare(String(vb))
150
+ : String(vb).localeCompare(String(va));
151
+ }
152
+ });
153
+
154
+ renderBody(sorted);
155
+
156
+ // 更新箭头 class
157
+ const headers = Array.from(thead.querySelectorAll("th.sortable"));
158
+ headers.forEach((h) => {
159
+ h.classList.remove("asc", "desc");
160
+ });
161
+ const target = headers.find((h) => h.dataset.col === col);
162
+ if (target) {
163
+ target.classList.add(asc ? "asc" : "desc");
164
+ }
165
+ }
166
+
167
+ // 初始渲染:WorldScore-Static 降序
168
+ sortAndRender(currentSortCol, currentAsc);
169
+
170
+ // 给所有表头绑定 click 排序
171
+ const headers = Array.from(thead.querySelectorAll("th.sortable"));
172
+ headers.forEach((th) => {
173
+ th.addEventListener("click", () => {
174
+ const col = th.dataset.col;
175
+ if (col === currentSortCol) {
176
+ currentAsc = !currentAsc; // 同一列就翻转方向
177
+ } else {
178
+ currentSortCol = col;
179
+ currentAsc = true; // 新列默认升序
180
+ }
181
+ sortAndRender(currentSortCol, currentAsc);
182
+ });
183
+ });
184
+ }
185
+
186
+ // 入口:加载 CSV,默认在 JS 里先按 WorldScore-Static 降序排一次,然后 buildTable
187
+ fetch("leaderboard.csv")
188
+ .then((res) => {
189
+ if (!res.ok) {
190
+ throw new Error("HTTP " + res.status);
191
+ }
192
+ return res.text();
193
+ })
194
+ .then((text) => {
195
+ const parsed = parseCsv(text);
196
+ if (!parsed.rows || parsed.rows.length === 0) {
197
+ document.getElementById("table-container").innerHTML =
198
+ "<p>No data rows in leaderboard.csv</p>";
199
+ return;
200
+ }
201
+
202
+ // 这里的 rows 保留原始字符串形式(包括 [Name](url))
203
+ const rows = parsed.rows.slice();
204
+
205
+ // 默认排序逻辑放在 buildTable 内部 sortAndRender 已经做了,
206
+ // 这里不需要再排序一次,直接丢过去
207
+ buildTable(rows);
208
+ })
209
+ .catch((err) => {
210
+ console.error("Failed to load CSV:", err);
211
+ document.getElementById("table-container").innerHTML =
212
+ "<p style='color:#f97316'>Failed to load leaderboard.csv: " + String(err) + "</p>";
213
+ });
214
+