Files
ogame_db/DOCUMENTAZIONE.md
T
2026-09-23 18:59:27 +02:00

18 KiB
Raw Blame History

OGame Galaxy Viewer — Documentazione tecnica

Visualizzatore di galassie per OGame (s170-ar, universo "Rosalind") con archivio personale dei rapporti di spionaggio e classifiche filtrate.

Questa documentazione descrive l'architettura, i sorgenti e, per ciascuno, funzioni e metodi.


1. Panoramica

Il progetto è una web app personale composta da:

Componente Tecnologia Ruolo
Backend Python 3 + Flask API REST, aggiornamento dati, archivio rapporti
Frontend HTML/CSS/JS vanilla Galaxy view, dettagli rapporti, classifiche
Dati File JSON su disco Nessun database: snapshot + rapporti come file
Servizi systemd (utente) App sempre attiva + aggiornamenti schedulati

Flusso dati (dati universo):

Gameforge API pubblica (XML + ?toJson=1)
        │  ogni giorno (03:30)
        ▼
update_data.py ──► data/latest/*.json ──► world.json (indici)
        │                                    ▲
        └── highscore ── ogni ora (:17) ─────┘
                              │
                        app.py (Flask :8899) ──► browser (galassia/classifiche)

Flusso dati (rapporti di spionaggio):

In gioco (pulsante "API" del rapporto) ──► API string "sr-ar-170-<40 hex>"
        │  incollata nella pagina
        ▼
POST /api/reports ──► report_store.py ──► proxy community (ogapi.faw-kes.de)
                                              ▼
                                    data/reports/<sr_id>.json  (+ index.json)
                                              ▼
                    clic sul pianeta in galassia ──► dettagli archiviati

2. Struttura delle directory

/opt/ogame_db/
├── app.py                  # Backend Flask: pagine + API + aggiornamento all'avvio
├── update_data.py          # Download snapshot pubblici + classifiche + world.json
├── report_store.py         # Import/archivio/consultazione rapporti di spionaggio
├── technames.py            # Nomi tecnologici (edifici/ricerche/navi/difese) lato server
├── config.json             # Configurazione (universo, proxy, account personale)
├── requirements.txt        # Dipendenze Python
├── README.md               # Guida rapida d'uso
├── DOCUMENTAZIONE.md       # (questo file)
├── data/
│   ├── latest/             # Snapshot correnti + world.json
│   ├── snapshots/          # Storico giornaliero (ritenzione: keep_snapshots)
│   └── reports/            # Rapporti importati (1 file = 1 rapporto) + index.json
└── static/
    ├── index.html          # Pagina galassia
    ├── rankings.html       # Pagina classifiche
    ├── style.css           # Stili (tema spaziale, responsive)
    ├── common.js           # Utility condivise (fetch, avatar SVG, icone, stelle)
    ├── app.js              # Logica della galassia e dei rapporti
    ├── rankings.js         # Logica della pagina classifiche
    ├── icons.js            # Icone SVG incorporate (game-icons, CC BY 3.0)
    └── icons/              # (riservata a eventuali svg esterni; non usata a runtime)

3. config.json — configurazione

{
  "server_number": 170,          // numero universo
  "community": "ar",             // community (lingua/regione)
  "domain": "s170-ar.ogame.gameforge.com",
  "my_player_id": 100634,        // tuo account: pianeti evidenziati in verde
  "my_player_name": "MaNaki",
  "proxy_base": "https://ogapi.faw-kes.de",   // proxy ufficiale per i rapporti
  "refresh_hours": 24,           // dati "stale" oltre N ore → update all'avvio
  "keep_snapshots": 30           // giorni di storico conservati
}

4. Backend — moduli Python

4.1 app.py — server Flask (porta 8899)

Avviato da systemd come ogame-galaxy.service. All'avvio verifica l'età dei dati (_ensure_fresh_data) e, se più vecchi di refresh_hours, lancia update_data.main().

Middleware

Funzione Descrizione
_no_cache(resp) after_request: imposta Cache-Control: no-store su pagine e file statici (niente cache nel browser)

Helper

Funzione Descrizione
load_config() Legge config.json
load_world() Legge data/latest/world.json e vi fonde i pianeti noti solo dai rapporti (player recenti assenti da universe.xml), marcandoli report_only
fmt_ts(epoch) Converte epoch in stringa YYYY-MM-DD HH:MM UTC
_report_view(rec, full) Trasforma un record d'archivio + payload in una vista sintetica per la UI (date, attività, risorse, conteggi per categoria, flag failed_*)
_ensure_fresh_data() Aggiornamento automatico all'avvio se i dati sono datati

Endpoint HTTP

Rotte Descrizione
GET / Pagina galassia (static/index.html)
GET /rankings Pagina classifiche (static/rankings.html)
GET /api/bootstrap Stato: server (nome, galassie, sistemi, velocità…), myPlayer, fetched (date ultimo aggiornamento per fonte), reportStats (n. rapporti/pianeti)
GET /api/galaxy?g=&s= Celle del sistema (15 posizioni): per ogni cella pianeta, luna, giocatore (+stato, alleanza, rank totale/armamenti), rapporti disponibili
GET /api/planet?g=&s=&p= Dettaglio pianeta: info, giocatore con rank, altri pianeti dello stesso giocatore, rapporti del pianeta e della luna
GET /api/player?id= Dettaglio giocatore: tutti i suoi pianeti e tutti i rapporti (su qualunque pianeta o luna), ordinati per data
POST /api/reports Importa un rapporto: body {"token": "sr-ar-170-<id>"} (o solo l'id a 40 hex). Idempotente: se già presente ritorna created:false
GET /api/reports/<sr_id> JSON completo di un rapporto archiviato ({meta, report})
DELETE /api/reports/<sr_id> Elimina un rapporto archiviato (file su disco + voce in index.json)
GET /api/rankings?type=&status=&start=&end=&q= Classifiche filtrate (vedi 4.4)
POST /api/refresh Forza update_data.main() in background

4.2 update_data.py — aggiornamento dati

Scarica l'API pubblica ufficiale di Gameforge (endpoint XML con ?toJson=1).

Costanti

Costante Valore
ENDPOINTS serverData, universe, players, alliances, localization
HIGHSCORES highscore_total (cat.1, type 0), highscore_military (cat.1, type 3)
UA User-Agent dichiarato nelle richieste

Funzioni

Funzione Descrizione
load_config() Legge config.json
http_get(url, timeout) GET con User-Agent
fetch_xml_json(cfg, name, query) Scarica https://s<num>-<comm>.ogame.gameforge.com/api/<name>.xml?toJson=1<query> e aggiunge _fetched_at
fetch_endpoint(cfg, name) Wrapper per gli endpoint semplici
fetch_highscore(...) (helper storico) scarica un highscore
save_latest(name, data) Salva in data/latest/<name>.json
save_snapshot(name, data) Copia giornaliera in data/snapshots/<name>_<AAAA-MM-GG>.json (una per giorno; prune oltre keep_snapshots)
_as_dict(payload, key, attr_key) Normalizza {"player":[{"@attributes":{...}}]} → {id: {...}}
build_world(cfg) Costruisce world.json (vedi §6)
_file_time(name) Epoch dell'ultimo fetch di un file latest
update_highscores(cfg, with_snapshot) Scarica i 2 highscore
main() Esegue l'aggiornamento; con argomento --highscore-only aggiorna solo le classifiche (usato dal timer orario)

4.3 report_store.py — archivio rapporti di spionaggio

Gestisce il ciclo di vita dei rapporti: parsing API string → recupero dal proxy → salvataggio JSON → indicizzazione per coordinate.

Funzioni

Funzione Descrizione
load_config() Legge config.json
_load_index() / _save_index(idx) Legge/scrive data/reports/index.json
parse_token(token, cfg) Valida l'API string (cr|sr|rr|mr)-<comm>-<num>-<40hex>; verifica che community/server combacino con la config; accetta anche il solo id esadecimale (assunto sr)
fetch_from_proxy(api_string, cfg) GET {proxy}/v1/report/{api_string}/1; gestisce 429 (limite proxy ~10 req/min) e RESULT_CODE != 1000
_defender_info(report) Estrae dal payload generic i dati del bersaglio (coordinate, tipo pianeta/luna, nomi, data evento, attività, % bottino)
import_report(api_string, cfg) Parsa → scarica → salva data/reports/<sr_id>.json → aggiorna index.json. Ritorna (record, creato?). Idempotente
get_report(rid) Legge il file completo {meta, report}
delete_report(rid) Elimina un rapporto (file + indice, ripulisce by_coords). Ritorna True se rimosso
list_by_coords(coords, scope) Elenca i rapporti di un pianeta. scope: planet | moon | all, ordinati per event_timestamp desc
summary(rec) (utilità) alias del record sintetico
stats(cfg) Conta rapporti totali e pianeti coperti

4.4 Filtri /api/rankings

Parametri: type (total|military|fleet), status, start/end (range posizione), q (testo su nome giocatore, tag o nome alleanza).

Con type=fleet (Top Flotte) la classifica non usa gli highscore: elenca solo i giocatori che hanno almeno un rapporto importato, ordinati per numero di navi. Le navi sono sommate prendendo, per ogni pianeta/luna spiato, il rapporto più recente (campo total_ship_count, memorizzato nell'indice all'import); la posizione rank è quella della classifica flotte e il valore è in score.

Valori di status e relativa condizione sullo stato API:

status stato API ammesso
all qualsiasi
active (vuoto)
inactive i, I
vacation v
vacation_inactive vi, vI
admin a

Nota UI: la pagina /rankings espone solo le voci Tutti (all), Attivi (active) e Inattivi (inactive). Gli altri valori restano accettati dall'API per compatibilità, ma non sono più selezionabili dall'interfaccia.

Le righe restituite includono: id, nome, stato, alleanza (tag+nome), posizione, punteggio, coordinate del primo pianeta (per l'avatar), numero pianeti, flag mine, numero di rapporti di spionaggio sul giocatore (reports) e coordinate del rapporto più recente (report_coords, usata per il salto dal badge "Spie").

4.5 technames.py — dizionario nomi tech (server)

Mappe id → nome per la numerazione client attuale (diversa da quella storica): edifici 1–44, ricerca 106–199, navi 202–219, difese 401–503, edifici lifeform 11101+. Nota: il frontend ha una copia aggiornata nei propri sorgenti (vedi §5.4, NAMES); technames.py resta come riferimento/utilità lato server.

Funzione Descrizione
_localized_names() Carica i nomi localizzati da data/latest/localization.json (fallback)
item_name(category, tid) Nome di un elemento (IT → localizzato → "Categoria #id")
category_name(cat) Etichetta della categoria

5. Frontend — static/

5.1 common.js — utility condivise

Funzione Descrizione
esc(s) Escape HTML
num(v) Formatta numeri in stile italiano (1.234.567), — se nullo
hashStr(s) Hash deterministico (per i colori degli avatar)
api(path, opts) fetch JSON con gestione errori ({ok:false, error})
icon(name, size) Ritorna l'SVG inline dell'icona da window.ICONS (icons.js) con currentColor
artSVG(seedKey, size, moon) Avatar pianeta/luna in SVG: colore scelto da palette in base all'hash, con ombra e (per la luna) crateri
initStars() Sfondo stellare su canvas (twinkle); non bloccante se canvas non disponibile

5.2 app.js — galassia e rapporti

Funzione Descrizione
loadBootstrap() Popola header: nome universo, range galassie/sistemi, date dati, conteggio spie
loadGalaxy() GET /api/galaxy e render della tabella
renderGalaxy(data) Costruisce le 15 righe: posizione, pianeta (avatar SVG + nome), luna, giocatore (colore per stato + 🏆/⚔ rank), alleanza, badge "spie"
openPlanet(pos, focusMoon) Apre il popup del pianeta (GET /api/planet)
openPlanetAt(coords, focusMoon) Apre il popup di un pianeta date le coordinate g:s:p, anche di un altro sistema
openPlayer(pid) / renderPlayerPopup(d) Apre la finestra giocatore (GET /api/player): elenco di tutti i pianeti + tutti i rapporti di spionaggio sul giocatore, in un'unica vista
renderPlanetPopup(data, focusMoon) Header con avatar; chip giocatore/stato/classifica/luna; altri pianeti del giocatore (cliccabili); griglia di card per gli spionaggi del pianeta e della luna
rptCard(rec) Card riepilogo di un rapporto (data, attività colorata, bersaglio con coordinate [g:s:p], attaccante, conteggi con icone categoria)
openReport(srId) / renderReportDetail(meta, rep) Vista dettaglio: risorse in tile colorate, meta (difensore/attaccante/attività/bottino/detriti), avvisi failed_*, sezioni in griglia di card con icona per ogni edificio/ricerca/nave/difesa
techSection(...) Griglia card per categoria
itemName(cat, id) / itemIconName(cat, id) Nome e chiave-icona di un elemento (fallback sulla categoria)
actClass/actLabel(activity) Colore/etichetta dell'attività rilevata (0/15/30/60 min)
fmtEv(evt) Data evento in formato locale italiano
setSystem/setGalaxy/closePopup/goToCoords Navigazione (con clamp sui limiti universo)
setMsg(kind, text) Messaggi di stato nella barra di import
importReport() Legge l'API string, POST /api/reports, aggiorna la vista

Stato globale: state = {galaxy, system, maxGalaxy, maxSystem, boot}. All'avvio legge ?g= e ?s= dalla URL (usato dai click dalle classifiche).

Colori stato giocatore (come in galaxy OGame): attivo = giallo · inattivo (i/I) = grigio · vacanza+inattivo = grigio · in vacanza = celeste · admin = rosso.

5.3 rankings.js — classifiche

Funzione Descrizione
initHead() Header con nome universo e data aggiornamento classifiche
load() GET /api/rankings con i filtri correnti
render(d) Tabella: posizione (top3 colorati oro/argento/bronzo), avatar pianeta, giocatore (colore stato, ● = tu), alleanza, stato, pianeti, Spie (badge col numero di rapporti sul giocatore, cliccabile verso il pianeta del rapporto più recente), punti
goGalaxy(coords) Salta alla galassia /?g=..&s=.. al pianeta del giocatore
readFilters() Legge i controlli (stato, range, testo)

Tabs: Generale (total), Armamenti (military) e Top Flotte (fleet — solo giocatori con rapporti, ordinati per navi), con icone SVG.

5.4 Mappe dati nel frontend (NAMES, ITEM_ICON)

NAMES[buildings|research|ships|defense|lfbuildings] → {id: nome} e ITEM_ICON[...] → {id: chiave icona}. Nomi allineati al client attuale (es. 213 → "Corazzata", 215 → "Incrociatore da battaglia", 210 → "Sonda di spionaggio").

5.5 icons.js / icone

window.ICONS = { chiave: {vb, body} } con 87 icone: 79 da game-icons.net (CC BY 3.0, attribuzione nei footer) + icone UI custom (refresh, chevron, chiusura, logo, avviso). Tutte usano fill="currentColor": il colore segue il CSS di categoria (--tc), quindi nessuna dipendenza dai font emoji del sistema.


6. Dati su disco — data/

6.1 data/latest/*.json

Snapshot grezzi dell'API (serverData, universe, players, alliances, localization, highscore_total, highscore_military), ciascuno con _fetched_at.

6.2 data/latest/world.json (indici precompilati)

Chiave Contenuto
server numero, community, dominio, nome universo, galassie, sistemi, velocità, versione, lingua, timezone, ACS
fetched epoch dell'ultimo fetch per ogni fonte
players {id: {name, status, alliance, alliance_tag, alliance_name}}
alliances {id: {name, tag, founder}}
planets {"g:s:p": {id, player, name, coords, moon:{...}}}. Le voci con report_only: true non vengono dall'API pubblica ma da un rapporto di spionaggio (pianeti di player recenti assenti da universe.xml)
avatar {playerId: prime-coordinate} (per gli avatar in classifica)
ranks {playerId: {total, military, total_score, military_score}}

6.3 data/snapshots/

Copie giornaliere *_AAAA-MM-GG.json per fonte (ritenzione configurabile).

6.4 data/reports/

  • index.json: {by_coords: {"g:s:p": [sr_id,…], "g:s:p#moon": [… ]}, reports: {sr_id: {meta…}}} → ricerca immediata per pianeta/luna.
  • <sr_id>.json: {"meta": {…}, "report": {generic, details}} (payload completo del proxy).

7. Servizi systemd (utente)

Unità Quando Cosa fa
ogame-galaxy.service sempre attivo web app su 0.0.0.0:8899 (restart on failure)
ogame-data-update.timer giornaliero 03:30 update_data.py (pianeti/giocatori/alleanze + highscore)
ogame-highscore.timer ogni ora (:17) update_data.py --highscore-only (classifiche)

Comandi utili: systemctl --user status/restart <unità>, journalctl --user -u ogame-galaxy.service -f, loginctl show-user principale | grep Linger (linger=yes ⇒ i servizi partono al boot senza login).


8. API esterne utilizzate

Sorgente Uso Note
https://s170-ar.ogame.gameforge.com/api/*.xml?toJson=1 API pubblica ufficiale: universe, players, alliances, serverData, localization, highscore highscore.xml?category=1&type=0|3; cadenze server: universe ~settimanale, players ~giornaliero, highscore ~orario
https://ogapi.faw-kes.de/v1/report/{api_string}/1 Proxy community ufficiale per il recupero dei rapporti (CR/SR/RR/MR) Nessuna API key necessaria; limite ~10 richieste/min
https://forum.origin.ogame.gameforge.com Documentazione ufficiale (thread "OGame API", procedure accesso) Riferimento del protocollo

9. Note operative e di sicurezza

  1. Accesso: app su 0.0.0.0:8899 senza autenticazione: se la rete non è privata, mettere un reverse proxy con login.
  2. Backup: copiare data/ (report inclusi) e config.json.
  3. Cache: i file statici sono serviti con no-store: un refresh basta dopo ogni modifica (nessun Ctrl+F5 necessario, ma non guasta).
  4. Privacy: i rapporti restano su questo server; il proxy viene contattato solo al momento dell'import di un nuovo token (che il giocatore controlla e condivide volontariamente).
  5. Licenza icone: game-icons.net, CC BY 3.0 (attribuzione nei footer di pagina).