elmadany commited on
Commit
107ece8
·
verified ·
1 Parent(s): 6226dc5

Create public/index.html

Browse files
Files changed (1) hide show
  1. public/index.html +168 -0
public/index.html ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Simba Benchmark</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Rubik:wght@400;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root {
10
+ --primary-navy: #282351;
11
+ --primary-orange: #D97706;
12
+ --secondary-navy: #2f3b7d;
13
+ --bg-cream: #FFFBF5;
14
+ --border-gold: #dca02a;
15
+ }
16
+ body { background: var(--bg-cream); font-family: 'Inter', sans-serif; color: #333; margin: 0; padding: 20px; }
17
+ .container { max-width: 1400px; margin: 0 auto; }
18
+ .header { text-align: center; margin-bottom: 30px; }
19
+ .header img { max-width: 60%; height: auto; }
20
+ .card { background: white; border-radius: 12px; padding: 30px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); margin-bottom: 30px; }
21
+
22
+ /* Tabs */
23
+ .tabs { display: flex; border-bottom: 2px solid var(--primary-navy); margin-bottom: 20px; }
24
+ .tab-btn { background: none; border: none; padding: 12px 20px; font-size: 16px; font-weight: 600; color: var(--secondary-navy); cursor: pointer; border-radius: 8px 8px 0 0; }
25
+ .tab-btn.active { background: var(--primary-navy); color: white; }
26
+ .view { display: none; }
27
+ .view.active { display: block; }
28
+
29
+ /* Controls */
30
+ .controls { display: flex; gap: 10px; margin-bottom: 15px; align-items: center; }
31
+ .btn { padding: 8px 16px; border-radius: 6px; cursor: pointer; border: none; font-weight: bold; }
32
+ .btn-primary { background: var(--primary-navy); color: white; }
33
+ .btn-secondary { background: #eee; color: var(--primary-navy); }
34
+ select { padding: 8px; border-radius: 6px; min-width: 200px; }
35
+
36
+ /* Tables */
37
+ .table-wrap { overflow-x: auto; }
38
+ table { width: 100%; border-collapse: collapse; border-top: 2px solid var(--border-gold); border-bottom: 2px solid var(--border-gold); font-size: 14px; }
39
+ th, td { padding: 10px; text-align: center; border-bottom: 1px solid #eee; white-space: nowrap; }
40
+ th { color: #7d3561; vertical-align: bottom; }
41
+ th:first-child, td:first-child { text-align: left; font-weight: bold; color: var(--primary-navy); }
42
+ .v-head { writing-mode: vertical-rl; transform: rotate(180deg); height: 130px; text-align: left; }
43
+
44
+ #loader { text-align: center; padding: 50px; font-size: 18px; color: var(--secondary-navy); }
45
+ </style>
46
+ </head>
47
+ <body>
48
+
49
+ <div class="container">
50
+ <div class="header"><img src="https://africa.dlnlp.ai/simba/images/simbabench_header.png" alt="Simba"></div>
51
+
52
+ <div class="card">
53
+ <div id="loader">🦁 Loading Data...</div>
54
+ <div id="content" style="display:none;">
55
+ <div class="tabs">
56
+ <button class="tab-btn active" onclick="setTab('asr', this)">ASR Leaderboard</button>
57
+ <button class="tab-btn" onclick="setTab('tts', this)">TTS Leaderboard</button>
58
+ <button class="tab-btn" onclick="setTab('slid', this)">SLID Leaderboard</button>
59
+ </div>
60
+
61
+ <div id="asr" class="view active">
62
+ <div class="controls">
63
+ <button id="btn-fam" class="btn btn-primary" onclick="setASRMode('family')">By Family</button>
64
+ <button id="btn-mod" class="btn btn-secondary" onclick="setASRMode('model')">By Model</button>
65
+ <div style="flex-grow:1; text-align:right;"><select id="asr-select" onchange="renderASR()"></select></div>
66
+ </div>
67
+ <div id="asr-table" class="table-wrap"></div>
68
+ </div>
69
+
70
+ <div id="tts" class="view">
71
+ <div class="controls"><label>Model: </label><select id="tts-select" onchange="renderTTS()"></select></div>
72
+ <div id="tts-table" class="table-wrap"></div>
73
+ </div>
74
+
75
+ <div id="slid" class="view"><div id="slid-table" class="table-wrap"></div></div>
76
+ </div>
77
+ </div>
78
+ <div class="card">
79
+ <h3>Citation</h3>
80
+ <p>If you use Simba, please cite our <a href='https://africa.dlnlp.ai/sahara/' style="color:#D97706">ACL2025 paper</a>.</p>
81
+ </div>
82
+ </div>
83
+
84
+ <script>
85
+ let DATA = null;
86
+ let asrMode = 'family';
87
+
88
+ fetch('/api/data').then(r=>r.json()).then(d=>{
89
+ DATA = d;
90
+ document.getElementById('loader').style.display='none';
91
+ document.getElementById('content').style.display='block';
92
+ init();
93
+ });
94
+
95
+ function init() {
96
+ populate('asr-select', DATA.metadata.families);
97
+ populate('tts-select', DATA.metadata.tts_models);
98
+ renderASR(); renderTTS(); renderSLID();
99
+ }
100
+ function populate(id, list) {
101
+ const s = document.getElementById(id); s.innerHTML='';
102
+ list.forEach(i=>{ let o=document.createElement('option'); o.value=i; o.text=i; s.add(o); });
103
+ }
104
+ function fmt(n) { return (n==null)?'N/A':n.toFixed(2); }
105
+
106
+ function renderASR() {
107
+ const val = document.getElementById('asr-select').value;
108
+ const div = document.getElementById('asr-table');
109
+ let html='';
110
+ if(asrMode==='family'){
111
+ const d=DATA.asr.by_family[val];
112
+ if(!d) return;
113
+ html=`<table><thead><tr><th>Model</th><th>Avg WER/CER</th>`;
114
+ d.languages.forEach(l=>html+=`<th><div class="v-head">${l}</div></th>`);
115
+ html+=`</tr></thead><tbody>`;
116
+ d.data.forEach(r=>{
117
+ html+=`<tr><td>${r.Model}</td><td><b>${fmt(r.Avg_WER)} / ${fmt(r.Avg_CER)}</b></td>`;
118
+ d.languages.forEach(l=>{
119
+ let w=r[`WER_${l}`], c=r[`CER_${l}`];
120
+ html+=`<td>${(w!=null)?fmt(w)+'/'+fmt(c):'-'}</td>`;
121
+ });
122
+ html+=`</tr>`;
123
+ });
124
+ } else {
125
+ const rows=DATA.asr.by_model[val];
126
+ html=`<table><thead><tr><th>Language</th><th>Family</th><th>WER</th><th>CER</th></tr></thead><tbody>`;
127
+ rows.forEach(r=>html+=`<tr><td>${r.Language}</td><td>${r.Family}</td><td>${fmt(r.WER)}</td><td>${fmt(r.CER)}</td></tr>`);
128
+ }
129
+ html+=`</tbody></table>`;
130
+ div.innerHTML=html;
131
+ }
132
+
133
+ function renderTTS() {
134
+ const rows=DATA.tts[document.getElementById('tts-select').value];
135
+ if(!rows) return;
136
+ let w=0,m=0,c=0;
137
+ rows.forEach(r=>{w+=r.wer;m+=r.mcd;c++;});
138
+ let html=`<p><b>Avg:</b> WER: ${fmt(w/c)} | MCD: ${fmt(m/c)}</p><table><thead><tr><th>Lang</th><th>WER</th><th>MCD</th><th>PESQ</th></tr></thead><tbody>`;
139
+ rows.forEach(r=>html+=`<tr><td>${r.language}</td><td>${fmt(r.wer)}</td><td>${fmt(r.mcd)}</td><td>${fmt(r.pesq)}</td></tr>`);
140
+ html+=`</tbody></table>`;
141
+ document.getElementById('tts-table').innerHTML=html;
142
+ }
143
+
144
+ function renderSLID() {
145
+ let html=`<table><thead><tr><th>Lang</th><th>MMS</th><th>Simba</th></tr></thead><tbody>`;
146
+ DATA.slid.forEach(r=>{
147
+ let m=r['MMS-LID-1024'], s=r['Simba-SLID'];
148
+ html+=`<tr><td>${r.Language}</td><td>${m>s?'<b>'+fmt(m)+'</b>':fmt(m)}</td><td>${s>m?'<b>'+fmt(s)+'</b>':fmt(s)}</td></tr>`;
149
+ });
150
+ html+=`</tbody></table>`;
151
+ document.getElementById('slid-table').innerHTML=html;
152
+ }
153
+
154
+ window.setTab=(id,btn)=>{
155
+ document.querySelectorAll('.view').forEach(e=>e.classList.remove('active'));
156
+ document.querySelectorAll('.tab-btn').forEach(e=>e.classList.remove('active'));
157
+ document.getElementById(id).classList.add('active'); btn.classList.add('active');
158
+ };
159
+ window.setASRMode=(m)=>{
160
+ asrMode=m;
161
+ document.getElementById('btn-fam').className=m==='family'?'btn btn-primary':'btn btn-secondary';
162
+ document.getElementById('btn-mod').className=m==='model'?'btn btn-primary':'btn btn-secondary';
163
+ populate('asr-select', m==='family'?DATA.metadata.families:DATA.metadata.models);
164
+ renderASR();
165
+ }
166
+ </script>
167
+ </body>
168
+ </html>