primo commit

This commit is contained in:
2026-09-23 18:59:27 +02:00
parent 029e9f67fb
commit bd900099a0
451 changed files with 143273 additions and 2 deletions
+107
View File
@@ -0,0 +1,107 @@
/* Utility condivise tra le pagine (galassia e classifiche) */
"use strict";
/* ---------------- utility base ---------------- */
function esc(s) {
return String(s ?? "").replace(/[&<>"']/g, (c) =>
({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
}
function num(v) { return (v === null || v === undefined) ? "—" : Number(v).toLocaleString("it"); }
function hashStr(s) { let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0; return Math.abs(h); }
async function api(path, opts) {
const r = await fetch(path, opts);
let data = null;
try { data = await r.json(); } catch (_) { /* noop */ }
if (!r.ok) throw new Error((data && data.error) || ("Errore HTTP " + r.status));
return data;
}
/* ---------------- icone SVG (window.ICONS da icons.js) ---------------- */
function icon(name, size = 16) {
const it = (window.ICONS || {})[name];
if (!it) return "";
return `<svg class="ic" width="${size}" height="${size}" viewBox="${it.vb}" ` +
`xmlns="http://www.w3.org/2000/svg" aria-hidden="true">${it.body}</svg>`;
}
/* ---------------- avatar pianeti/lune (SVG) ---------------- */
let _svgSeq = 0;
const PLANET_PAL = [
["#ffd9a0", "#e0762c"], ["#f2b3a0", "#b3422f"], ["#ffb1c0", "#a0275a"],
["#9fd8ff", "#2a6fc4"], ["#8fe8c0", "#1e7a5f"], ["#d3b8ff", "#6d3fc4"],
["#f5e3a0", "#c2a22e"], ["#c3d0e2", "#5c6f8c"],
];
const LUNA_PAL = [["#e6e6e6", "#9a9a9a"]];
function artSVG(seedKey, size, moon = false) {
const seed = hashStr(seedKey) || 1;
const r = 15; // viewBox 32
const pal = (moon ? LUNA_PAL : PLANET_PAL)[seed % (moon ? 1 : PLANET_PAL.length)];
const id = "g" + (++_svgSeq);
let extras = "";
if (moon) {
for (let i = 0; i < 4; i++) {
const cx = 7 + ((seed >> (i * 3)) % 18);
const cy = 7 + ((seed >> (i * 5 + 2)) % 18);
const cr = 2 + ((seed >> (i * 2 + 1)) % 3);
extras += `<circle cx="${cx}" cy="${cy}" r="${cr}" fill="rgba(0,0,0,.18)"/>` +
`<circle cx="${cx}" cy="${cy}" r="${cr}" fill="none" stroke="rgba(255,255,255,.28)" stroke-width=".7"/>`;
}
} else {
for (let i = 0; i < 3; i++) {
const cx = 8 + ((seed >> (i * 4)) % 14);
const cy = 6 + ((seed >> (i * 3 + 1)) % 14);
extras += `<circle cx="${cx}" cy="${cy}" r="${5 + ((seed >> i) % 5)}" fill="rgba(255,255,255,.10)"/>`;
}
}
return `<svg width="${size}" height="${size}" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">` +
`<defs><radialGradient id="${id}" cx=".35" cy=".3" r=".95">` +
`<stop offset="0" stop-color="${pal[0]}"/><stop offset="1" stop-color="${pal[1]}"/>` +
`</radialGradient></defs>` +
`<circle cx="16" cy="16" r="${r}" fill="url(#${id})"/>` +
extras +
`<path d="M2 17a14 14 0 0 0 28 0 12 9 0 0 1 -28 0z" fill="rgba(0,0,0,.30)"/>` +
`<circle cx="16" cy="16" r="${r}" fill="none" stroke="rgba(0,0,0,.35)" stroke-width="1"/>` +
`</svg>`;
}
/* ---------------- sfondo stellare ---------------- */
function initStars() {
const cv = document.getElementById("space");
if (!cv) return;
let ctx = null;
try { ctx = cv.getContext("2d"); } catch (_) { /* noop */ }
if (!ctx) return; // mai bloccare il resto dell'app
let stars = [], tw = [];
function resize() {
cv.width = innerWidth; cv.height = innerHeight;
stars = []; tw = [];
const n = Math.floor((cv.width * cv.height) / 6500);
for (let i = 0; i < n; i++) {
stars.push({ x: Math.random() * cv.width, y: Math.random() * cv.height,
r: Math.random() * 1.1 + .25, a: Math.random() * .5 + .2 });
}
for (let i = 0; i < 26; i++) {
tw.push({ x: Math.random() * cv.width, y: Math.random() * cv.height,
r: Math.random() * 1.2 + .4, p: Math.random() * Math.PI * 2, s: .8 + Math.random() });
}
}
resize();
addEventListener("resize", resize);
(function draw(t) {
ctx.clearRect(0, 0, cv.width, cv.height);
for (const s of stars) {
ctx.globalAlpha = s.a; ctx.fillStyle = "#cfe0ff";
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 7); ctx.fill();
}
const k = t / 1000;
for (const s of tw) {
ctx.globalAlpha = .25 + .6 * Math.abs(Math.sin(k * s.s + s.p));
ctx.fillStyle = "#fff";
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 7); ctx.fill();
}
ctx.globalAlpha = 1;
requestAnimationFrame(draw);
})(performance.now());
}