|
31 | 31 | : FALLBACK_PLATFORMS; |
32 | 32 | var OTHER = { key: "other", icon: "📦", label: "Inne", kind: "pc", color: "#6b5a3e" }; |
33 | 33 |
|
| 34 | + // Hardware families, for the higher-level "by family" split. Comes from Hugo |
| 35 | + // (window.WACKI_FAMILIES, injected from data/families.yaml) so it shares the |
| 36 | + // site's single source of truth — add a family there and it buckets here for |
| 37 | + // free. Order = display order of the split; `color`/`label`/`icon` mirror the |
| 38 | + // YAML. The inline array is only a fallback for a stale/cached stats.html. |
| 39 | + var FALLBACK_FAMILIES = [ |
| 40 | + { key: "pc", label: "Komputery", icon: "🖥️", color: "#1c3a52" }, |
| 41 | + { key: "mobile", label: "Telefony i tablety", icon: "📱", color: "#14a84a" }, |
| 42 | + { key: "handheld", label: "Handheldy", icon: "🎮", color: "#ff7b08" }, |
| 43 | + { key: "console", label: "Konsole", icon: "📀", color: "#b8330f" } |
| 44 | + ]; |
| 45 | + var FAMILIES = (window.WACKI_FAMILIES && window.WACKI_FAMILIES.length) |
| 46 | + ? window.WACKI_FAMILIES |
| 47 | + : FALLBACK_FAMILIES; |
| 48 | + |
34 | 49 | function platformFor(assetName) { |
35 | 50 | var n = (assetName || "").toLowerCase(); |
36 | 51 | for (var i = 0; i < PLATFORMS.length; i++) { |
|
64 | 79 | var p = platformFor(a.name); |
65 | 80 | perPlatform[p.key] = perPlatform[p.key] || { meta: p, count: 0 }; |
66 | 81 | perPlatform[p.key].count += c; |
67 | | - byKind[p.kind] += c; |
| 82 | + // Guarded so a platform whose kind isn't pre-seeded (a new family) adds |
| 83 | + // up instead of producing NaN. |
| 84 | + byKind[p.kind] = (byKind[p.kind] || 0) + c; |
68 | 85 | relTotal += c; |
69 | 86 | total += c; |
70 | 87 | if (a.created_at && (!firstAssetDate || a.created_at < firstAssetDate)) { |
|
187 | 204 | ); |
188 | 205 | }); |
189 | 206 |
|
190 | | - // desktop vs handheld split (other kinds — consoles like PS2, Android — |
191 | | - // show in the per-platform bars + grand total, but not this binary |
192 | | - // PC↔handheld widget) |
193 | | - var pc = data.byKind.pc, hh = data.byKind.handheld, sum = pc + hh; |
194 | | - var pcPct = sum ? Math.round((pc / sum) * 100) : 0; |
195 | | - var hhPct = sum ? 100 - pcPct : 0; |
196 | | - el("split-pc-num").textContent = fmt(pc); |
197 | | - el("split-hh-num").textContent = fmt(hh); |
198 | | - el("split-pc-pct").textContent = pcPct + "%"; |
199 | | - el("split-hh-pct").textContent = hhPct + "%"; |
200 | | - applySoon(function () { |
201 | | - el("split-pc-fill").style.width = pcPct + "%"; |
202 | | - el("split-hh-fill").style.width = hhPct + "%"; |
| 207 | + // hardware-family split — the same downloads as the per-platform bars, |
| 208 | + // rolled up into the families from data/families.yaml as one 100%-stacked |
| 209 | + // bar. Families with zero downloads are dropped so it shows only what |
| 210 | + // people actually play on. Percentages are a share of this sum (which |
| 211 | + // equals the grand total once every platform maps to a family). |
| 212 | + var famSum = 0; |
| 213 | + FAMILIES.forEach(function (f) { famSum += data.byKind[f.key] || 0; }); |
| 214 | + var splitBar = el("split-bar"); |
| 215 | + var splitLegend = el("split-legend"); |
| 216 | + splitBar.innerHTML = ""; |
| 217 | + splitLegend.innerHTML = ""; |
| 218 | + FAMILIES.forEach(function (f) { |
| 219 | + var count = data.byKind[f.key] || 0; |
| 220 | + if (count <= 0) return; |
| 221 | + // Exact float width (so segments always fill the bar); rounded label. |
| 222 | + var pctExact = famSum ? (count / famSum) * 100 : 0; |
| 223 | + var pctLabel = Math.round(pctExact); |
| 224 | + |
| 225 | + var seg = document.createElement("div"); |
| 226 | + seg.className = "split__seg"; |
| 227 | + seg.style.background = f.color; |
| 228 | + seg.title = f.label + " — " + fmt(count) + " (" + pctLabel + "%)"; |
| 229 | + // Only label segments wide enough to fit the text without clipping; the |
| 230 | + // legend carries the rest so a thin sliver doesn't show garbled digits. |
| 231 | + if (pctExact >= 10) seg.textContent = pctLabel + "%"; |
| 232 | + splitBar.appendChild(seg); |
| 233 | + applySoon(function () { seg.style.width = pctExact + "%"; }); |
| 234 | + |
| 235 | + var item = document.createElement("span"); |
| 236 | + item.className = "split__item"; |
| 237 | + var dot = document.createElement("span"); |
| 238 | + dot.className = "split__dot"; |
| 239 | + dot.style.background = f.color; |
| 240 | + var b = document.createElement("b"); |
| 241 | + b.textContent = fmt(count); |
| 242 | + item.appendChild(dot); |
| 243 | + item.appendChild(document.createTextNode(" " + f.icon + " " + f.label + " — ")); |
| 244 | + item.appendChild(b); |
| 245 | + splitLegend.appendChild(item); |
203 | 246 | }); |
204 | 247 |
|
205 | 248 | // per-release bars (already latest-first from API) — share of grand total |
|
0 commit comments