Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Metis ♟️

Metis è un assistente per l'analisi delle partite di scacchi giocate a tavolino. Tu (l'unico amministratore) incolli una partita a un bot Telegram; Metis la fa analizzare a Stockfish, commenta ogni mossa in italiano, riconosce l'apertura, tiene un profilo statistico di ogni giocatore, genera un video animato della partita e una scheda giocatore, e invia tutto in privato a ciascun giocatore su Telegram.


Parte 1 — Guida per l'utente

Questa parte spiega come si usa, senza tecnicismi. La parte tecnica è più sotto.

Cos'è, in due parole

C'è un bot Telegram (il tuo: @metis_chess_bot). Solo tu, l'amministratore, puoi mandargli le partite. Ogni giocatore registrato riceve poi in chat privata la propria analisi.

Per ogni partita analizzata, ciascun giocatore riceve quattro cose:

  1. 📊 Un messaggio di riassunto, scritto dal suo punto di vista (esito: hai vinto / hai perso / patta) — apertura riconosciuta, la sua precisione e quella dell'avversario, numero di errori gravi (blunder) e i 2–3 momenti chiave della sua partita, ciascuno con un'icona sulla qualità della mossa e una spiegazione discorsiva (cosa è cambiato e cosa si poteva fare meglio).
  2. 🖼️ La sua scheda giocatore (immagine) — record vittorie/patte/sconfitte, precisione media, livello stimato, rendimento per fase (apertura/mediogioco/finale), e lo storico delle aperture con le percentuali di successo.
  3. 🎬 Un video animato della partita — la scacchiera che si muove mossa per mossa, con la mossa evidenziata, un'etichetta colorata sulla qualità (verde = ottima … rosso = blunder) e il commento. Gli errori restano più a lungo a schermo per capirli bene.
  4. 📄 Un documento di testo col commento completo, mossa per mossa.

I tre passi per usarlo

Passo 1 — Registra i giocatori (una volta sola per persona). Scrivi al bot:

/giocatore mario Mario Rossi

Il bot ti risponde con un link d'invito. Mandalo a Mario: lui lo apre, il bot gli dice «sei collegato», e da quel momento riceverà le sue analisi. (Telegram permette al bot di scrivere a una persona solo se quella ha aperto il bot: per questo serve l'invito.)

Passo 2 — Manda una partita. Scrivi il comando con i due giocatori e il risultato, e a capo incolli le mosse (oppure un PGN completo copiato da un sito/app):

/analizza mario luigi 1-0
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 ...

Il risultato è uno tra 1-0 (vince il Bianco), 0-1 (vince il Nero), 1/2-1/2 (patta). Il bot risponde subito «⏳ Ricevuto! Sto analizzando…» e dopo qualche minuto invia le analisi.

Passo 3 — Ricevi i risultati. Ogni giocatore collegato riceve in privato le sue 4 cose. Se un giocatore non si è ancora collegato, la sua copia arriva a te, così non si perde niente.

I comandi

Comando Chi Cosa fa
/giocatore <id> <nome> tu crea un giocatore e genera il link d'invito. Es: /giocatore mario Mario Rossi
/start <token> i giocatori apre il link d'invito e collega la loro chat
/analizza <idBianco> <idNero> <risultato> + mosse tu analizza una partita e la invia
/profilo <id> tu mostra la scheda di un giocatore
/help tu elenca i comandi

Note utili:

  • L'id del giocatore è un'etichetta corta a tua scelta (es. mario), serve a ritrovarlo.
  • Puoi incollare anche un PGN completo con i tag [White ...] [Black ...] [Result ...]: Metis legge nomi e data dai tag (il risultato però è quello che scrivi nel comando). Eventuali commenti e varianti nel PGN vengono ignorati: si analizza la linea principale.

Accendere e spegnere il bot

Tu non tieni il bot sempre acceso: lo avvii quando devi mandare le partite e lo spegni quando hai finito. Dal terminale, nella cartella del progetto:

bash deploy/start.sh

Questo accende tutto il necessario (il motore di commento AI, e il bot) e resta in ascolto. Manda pure le tue partite; quando vedi «Analisi completata» puoi chiudere con Ctrl-C.


Parte 2 — Guida tecnica

Panoramica

  • Linguaggio/build: Java 17, Maven. Fat-jar: target/metis.jar (main com.metis.app.Main).
  • Motore: binario Stockfish esterno, pilotato via protocollo UCI.
  • Database: Supabase (PostgreSQL); lo schema viene creato da zero da Flyway all'avvio.
  • Commenti: commentatore a regole deterministico (sempre corretto), discorsivo e didattico (spiega l'errore e l'alternativa, non solo le percentuali) + opzionale riformulatore Ollama (LLM locale).
  • Media: video MP4 (frame Java2D montati con ffmpeg) e scheda PNG (Java2D).

Architettura (a strati: il dominio non dipende dall'infrastruttura)

com.metis
├─ app/      bootstrap: Config (variabili d'ambiente), Main (wiring + shutdown hook)
├─ engine/   UciEngine (UCI/Stockfish), Eval, EngineConfig
├─ analysis/ GameAnalyzer, MoveScoring, MoveJudge, BoardFacts, Notation, Analysis (modello)
├─ opening/  OpeningBook (tabelle aperture Lichess)
├─ comment/  Commentator, RuleCommentator, OllamaCommentator
├─ render/   BoardRenderer + GameVideoRenderer (video), ProfileCardRenderer (scheda PNG)
├─ store/    Db (Hikari + Flyway), *Repository (interfaccia + JDBC), StatsCalculator
└─ bot/      MetisBot, AnalysisService, GameInputParser, MessageFormatter, InviteService, Notifier

Le dipendenze puntano verso il dominio; l'accesso ai dati passa per interfacce (repository); motore, connessioni DB e processi esterni sono sempre chiusi (try-with-resources / shutdown hook).

Tecnologie e versioni (verificate su Maven Central / JitPack)

Libreria Versione Note
com.github.bhlangonijr:chesslib 1.3.6 modello scacchi (SAN/FEN/PGN). Su JitPack, non su Maven Central.
org.postgresql:postgresql 42.7.11 driver JDBC
com.zaxxer:HikariCP 7.0.2 pool di connessioni (Java 17+)
org.flywaydb:flyway-core + flyway-database-postgresql 12.8.1 migrazioni. Il modulo PostgreSQL è separato e obbligatorio dalla v10.
com.github.pengrad:java-telegram-bot-api 10.0.0 bot Telegram (API pulita per long-polling)
org.slf4j:slf4j-api + slf4j-simple 2.0.18 logging
org.junit.jupiter:junit-jupiter 6.1.0 test (baseline Java 17)

Il fat-jar (maven-shade-plugin) usa il ServicesResourceTransformer così che i file META-INF/services del driver JDBC e dei plugin Flyway vengano uniti correttamente.

Configurazione

Tutto da variabili d'ambiente, lette nella classe Config. Le variabili obbligatorie sono validate all'avvio: se ne manca una, Metis si ferma con un messaggio chiaro. Vedi .env.example.

Variabile Obbligatoria Default Significato
METIS_BOT_TOKEN token del bot (@BotFather)
METIS_ADMIN_ID il tuo id numerico Telegram (unico autorizzato)
METIS_DB_URL URL JDBC del Session Pooler Supabase (con ?sslmode=require)
METIS_DB_USER utente Session Pooler, es. postgres.<project-ref>
METIS_DB_PASSWORD password del database
METIS_STOCKFISH_PATH no stockfish percorso/comando del binario Stockfish
METIS_FFMPEG_PATH no ffmpeg percorso/comando di ffmpeg (per il video)
METIS_ANALYSIS_DEPTH no 16 profondità di ricerca di Stockfish
METIS_ANALYSIS_MOVETIME_MS no 0 tempo fisso per mossa in ms (0 = usa la profondità)
METIS_ENGINE_THREADS no 1 opzione UCI Threads
METIS_ENGINE_HASH_MB no 128 opzione UCI Hash (MB)
METIS_LLM_ENABLED no false attiva il riformulatore Ollama
METIS_OLLAMA_MODEL no llama3.1 modello Ollama quando l'LLM è attivo

I segreti non vanno mai committati: i valori reali stanno in un file .env (git-ignored); .env.example contiene solo i segnaposto.

Database Supabase (Session Pooler)

Usa la stringa del Session Pooler dalla dashboard (Connect → Session pooler): è compatibile IPv4 e supporta i prepared statement (a differenza del Transaction Pooler sulla 6543, e della connessione diretta solo-IPv6). Nel .env la URL JDBC va senza utente/password (passati a parte):

METIS_DB_URL=jdbc:postgresql://aws-0-<regione>.pooler.supabase.com:5432/postgres?sslmode=require
METIS_DB_USER=postgres.<project-ref>
METIS_DB_PASSWORD=<password>

Nessun SQL manuale: all'avvio Metis applica la migrazione V1__init.sql e crea lo schema. Se lo schema public contiene già altri oggetti, Metis fa il baseline a versione 0 e applica comunque V1 (le create ... if not exists la rendono idempotente; i riavvii non duplicano nulla).

Build e test

mvn -q -DskipTests package   # crea target/metis.jar
mvn -q test                  # esegue gli unit test (nessuna rete/Stockfish/DB necessari)

Esiste anche un test d'integrazione manuale (LiveSmokeIT) che esercita tutta la pipeline contro Stockfish, Supabase e Ollama reali; è escluso da mvn test e si auto-salta senza .env:

set -a; . ./.env; set +a
mvn test -Dtest=LiveSmokeIT -DfailIfNoTests=false -Dsurefire.useFile=false

Per sviluppare sul progetto, vedi CLAUDE.md: comandi rapidi, convenzioni e i "fatti critici" da non far regredire (chesslib su JitPack, en passant, modulo Flyway Postgres, video via image2pipe, API pengrad, riformulazione selettiva).

Avvio on-demand e prerequisiti

deploy/start.sh è pensato per l'uso a richiesta su un Mac: avvia Ollama (se l'LLM è attivo), ne riscalda il modello, ricostruisce il jar se manca o se i sorgenti (src/main/pom.xml) sono più recenti del jar (così a ogni avvio parte l'ultima versione del codice), poi esegue il bot in foreground. Prerequisiti (Homebrew):

brew install stockfish
brew install ffmpeg
brew install --cask ollama        # app ufficiale; la *formula* Homebrew 0.30.x è incompleta
ollama pull llama3.1:8b           # solo se vuoi l'LLM

In alternativa, esegui il jar dopo aver caricato il .env:

set -a; . ./.env; set +a
java -jar target/metis.jar

Se ffmpeg manca, l'analisi funziona lo stesso: viene saltato solo il video.

Commenti: regole + riformulazione selettiva (Ollama)

Il RuleCommentator produce commenti deterministici e sempre corretti dai fatti dell'analisi. Lo stile è discorsivo e didattico: per imprecisioni, errori e blunder non si limita alle percentuali ma le traduce in stati di posizione a parole (vincente / di vantaggio / equilibrata / di svantaggio / compromessa) e spiega cosa era meglio e perché — la mossa del motore e lo stato che avrebbe preservato. Esempio:

Errore. Le tue probabilità di vittoria scendono dal 80% al 55%: da una posizione di vantaggio a una posizione equilibrata. Era meglio Nf3 (d5 e3), che avrebbe mantenuto una posizione di vantaggio.

Tutto è derivato solo dai fatti già presenti nell'analisi: nessun fatto scacchistico viene inventato. Le mosse ottime/buone e quelle di teoria restano concise (compaiono su ogni riga del documento mossa per mossa).

Se METIS_LLM_ENABLED=true, l'OllamaCommentator riformula quel commento in 2-3 frasi più scorrevoli, con tono da allenatore (POST a http://localhost:11434/api/generate, temperature 0 per restare fedele), con fallback automatico al commento a regole su qualsiasi errore.

Riformulazione selettiva: l'LLM viene usato solo sui commenti sostanziosi (imprecisioni, errori, blunder); quelli brevi e netti («Ottima, la scelta migliore.», «Mossa di teoria (…)») restano testuali. Il prompt vincola il modello a non inventare nulla (mosse, pezzi, minacce, numeri): riformula soltanto il commento a regole. Questo, insieme alla selettività, evita che il modello «ricami» fatti inventati e riduce molto il numero di chiamate (quindi i tempi). Per la massima sicurezza factuale puoi comunque tenere l'LLM spento.

Il video animato (render + ffmpeg)

BoardRenderer disegna ogni posizione con Java2D (scacchiera verde, coordinate, pezzi in stile Staunton dal set cburnett, mossa evidenziata, re sotto scacco cerchiato, didascalia con mossa, badge colorato per classe, variazione di probabilità e commento). I pezzi sono 12 PNG bundlati in src/main/resources/pieces/cburnett/, decodificati e scalati una volta in cache (con fallback a lettere se mancano); il frame è reso a risoluzione doppia (supersampling 2×) e poi ridotto a 720×900, per contorni dei pezzi e testo più nitidi. GameVideoRenderer invia i frame a ffmpeg via image2pipe a FPS fisso, ripetendo ogni frame per la sua durata (i blunder durano di più). Così la durata del video è esattamente numero_frame / fps (niente trucchi del concat-demuxer, che su ffmpeg 8.x raddoppiavano l'ultima durata). Output: H.264 720×900 yuv420p (libx264 -preset slow -tune stillimage -crf 18), compatibile con Telegram.

Crediti pezzi. Il set cburnett è opera di Colin M.L. Burnett, usato sotto licenza 3-clause BSD (vedi src/main/resources/pieces/cburnett/LICENSE.txt).

La scheda giocatore (ProfileCardRenderer)

PNG largo 820 px con tema scuro: intestazione, barra impilata vittorie/patte/sconfitte, barra di precisione, barre per fase (con la fase più debole evidenziata), punti per colore e storico aperture. Nessun testo viene troncato: i nomi delle aperture vanno a capo su più righe, il nome del giocatore si auto-riduce per restare nei margini e l'altezza della scheda è dinamica (cresce col contenuto, con un minimo). Inviata come foto; se la generazione fallisce, si ripiega sul profilo testuale.

Statistiche e storico aperture (StatsCalculator)

Tutte le statistiche sono ricalcolate dai dati (game + moves) a ogni richiesta, quindi si affinano con le partite. Il profilo include: record V/P/S, precisione media, ACPL medio, livello stimato (clamp(600, 2700, 2500 − 13·ACPL) arrotondato a 50), rendimento per fase con la fase più debole, ripartizione punti per colore, scontri diretti, e lo storico aperture (le più giocate e le meno giocate, con record V/P/S per ciascuna).

Deploy alternativo (sempre acceso, Linux/Oracle ARM)

Se invece volessi tenerlo sempre acceso su una VM Linux (es. Oracle Cloud Always Free, ARM), usa deploy/metis.service (systemd, Restart=always): metti il jar in /opt/metis, i segreti in /etc/metis.env (permessi 600), installa Stockfish/ffmpeg via apt, poi systemctl enable --now metis. chesslib, PostgreSQL, HikariCP e la libreria Telegram sono Java puro; l'unico binario dipendente dall'architettura è Stockfish (build ARM disponibile via apt).

Note importanti

  • Fedeltà LLM: anche a temperature 0 un modello piccolo può «arricchire» i commenti; per questo la riformulazione è selettiva ed esiste sempre il fallback a regole. Il commento a regole è la fonte di verità.
  • Segreti: se token o password vengono esposti, ruotali (@BotFather e Supabase) e aggiorna il .env.

Stato e roadmap

Implementato: analisi UCI, commenti (regole + LLM selettivo), riconoscimento aperture, profilo con storico aperture, scheda PNG, video animato. Possibili sviluppi futuri: temi/orientamento scacchiera configurabili, riconoscimento aperture ancora più ricco.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages