BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
이탈리아 최초의 공동 스케디나 게임, 상대와 겨뤄서 상품을 받으세요
Fanta Schedina - Il primo gioco di schedine collettivo in Italia. Sfida i tuoi avversari nella schedina per ottenere premi!
게임TypeScript · JavaScriptGitHub @giuseppemignanocr7-create온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Gioco di pronostici Serie A multi-utente: schedine settimanali, classifica condivisa, premi, minigiochi che fanno guadagnare gettoni e power-up spendibili sulla schedina. Stack: React 18 + Vite + TypeScript + Tailwind + Zustand (client), Firebase Auth + Firestore + Cloud Functions (backend sicuro), dati partite ESPN public API. Tutta la logica che tocca punti e gettoni gira server-side su Cloud Functions: [README 설치·사용 부분 발췌] Setup 2. Progetto Firebase (piano Blaze richiesto per le Functions) 1. https://console.firebase.google.com → Add project 2. **README 전문 보기 ↗
Gioco di pronostici Serie A multi-utente: schedine settimanali, classifica condivisa, premi, minigiochi che fanno guadagnare gettoni e power-up spendibili sulla schedina.
Stack: React 18 + Vite + TypeScript + Tailwind + Zustand (client), Firebase Auth + Firestore + Cloud Functions (backend sicuro), dati partite ESPN public API.
Tutta la logica che tocca punti e gettoni gira server-side su Cloud Functions:
| Azione | Dove gira | Perché |
|---|---|---|
| Invio schedina | callable submitSchedina | valida deadline, sostituisce le quote con quelle ufficiali, addebita i power-up, e verifica l'appartenenza alla lega per le schedine di lega |
| Settlement giornata | scheduled settleMatchdays (ogni ora) | valuta le schedine, aggiorna punti/profili in transaction, assegna premi |
| Sync giornata + quote | scheduled syncMatchday (ogni 6h) | le quote sono generate SOLO server-side |
| Minigiochi | callable playMinigame | esiti estratti dal server, cooldown 1/giorno su Firestore |
| Missioni | callable claimMission | verifica progressi dal profilo, accredita gettoni |
| Premi settimanali | callable adminManageWeeklyPrizes | l'admin decide cosa si vince in una giornata; il settlement li assegna al podio |
| Classifica | callable getRankings | calcolata una volta sola dal server, anche per lega: il client non scarica più tutti i profili |
| Pulizia duelli | scheduled cleanupPenaltyDuels (ogni ora) | chiude le sfide ferme e cancella quelle mai iniziate |
| Cambio Last-Minute | callable changePrediction | addebita 100 gettoni, consuma il power-up e cambia 1 pronostico dopo la deadline, solo su partite non iniziate |
Le Firestore Rules (firestore.rules) bloccano ogni scrittura client su punti, gettoni, schedine e giornate. Le schedine altrui sono leggibili solo dopo la deadline (anti-copia).
I punti di una schedina sono la somma delle quote indovinate, moltiplicata per 10: una giocata a 2.00 vale 20 punti, dieci giocate a 2.00 ne valgono 200. Ogni quota è cappata a 5.00 (quindi max 50 punti a giocata) e le quote sotto 1.30 non sono valide. Chi indovina 9 pronostici su 10 prende +5 punti, chi li indovina tutti e 10 +10 punti. I punti si sommano giornata dopo giornata in classifica generale.
I punti sono una cosa, i gettoni un'altra: i primi fanno la classifica, i secondi si spendono in power-up e si guadagnano coi minigiochi.
Ogni giornata un utente compila una schedina per la classifica generale e una per ogni lega di cui fa parte: stesse partite, stessa deadline, punti separati.
| Circuito generale | Leghe | |
|---|---|---|
| Documento | schedine/{uid}_{giornata} | schedine/{uid}_{giornata}_{lega} |
| Dove finiscono i punti | profilo (totalPoints) | leagues/{lega}/standings/{uid} |
| Gettoni dai pronostici | sì | no |
| Statistiche e missioni | sì | no |
| Power-up | sì, a pagamento | sì, si pagano su ogni schedina |
| Premio di giornata | 100 gettoni al migliore | solo la vittoria in classifica di lega |
I gettoni si guadagnano quindi solo dal circuito generale e dai minigiochi, mentre le leghe li consumano: è una scelta di bilanciamento, non un effetto collaterale. In schedina un pulsante copia dalla schedina generale evita di ricompilare dieci pronostici per ogni lega.
Guadagni gettoni con:
| Fonte | Premio | Limite |
|---|---|---|
| Quiz Calcio | +3 a risposta esatta (max 10 domande) | 1 partita al giorno |
| Ruota giornaliera | 5–100 a caso su 8 spicchi | 1 giro al giorno |
| Rigori | +2 a gol (5 tiri) | 50 gettoni al giorno |
| Memoria Calcio | +5 a livello, +1 ogni 5 secondi risparmiati | 40 gettoni al giorno |
| Duelli rigori 1v1 | 50 a vittoria, 25 a pareggio | 150 gettoni al giorno |
| Sfide 1vs1 | 5–30 secondo la prestazione | una per avversario a settimana |
| Missioni | 50–500 una tantum | una volta per missione |
| Schedina | +2 gettoni a pronostico esatto, +50 con 9/10, +150 con 10/10, +100 al vincitore di giornata | per giornata |
I valori vivono in functions/src/config.ts e sono verificati dai test: se
cambi quelli, questa tabella va aggiornata a mano.
Li spendi in power-up sulla schedina:
Config centralizzata in functions/src/config.ts (server, fonte di verità) e src/lib/economy.ts (client, mirror).
npm install
npm --prefix functions install
eur3)firebaseConfigcp .env.example .env # compila con i valori del firebaseConfig
npm i -g firebase-tools
firebase login
# Sostituisci il project id in .firebaserc, poi:
firebase deploy --only firestore:rules,firestore:indexes
firebase deploy --only functions
Le quote sono generate algoritmicamente di default. Per usare quote reali da bookmaker europei via The Odds API (500 crediti/mese gratis, nessuna carta):
# 1. Registrati su the-odds-api.com → ottieni una API key gratuita
# 2. Imposta la secret su Firebase
firebase functions:secrets:set ODDS_API_KEY
# 3. Ridistribuisci le functions (obbligatorio a ogni cambio di secret)
firebase deploy --only functions
Il secret è dichiarato con
defineSecrete collegato asyncMatchdayeadminSyncMatchday. Le function v2 ricevono i secret solo se elencati nelle loro opzioni: senza,process.envresta vuoto e il sistema ricade silenziosamente sulle quote algoritmiche.
Se la key non è impostata o l'API non risponde, il sistema usa automaticamente l'engine algoritmico come fallback. Mercati coperti da quote reali: esito, over_under, goal_nogoal, doppia_chance (derivata). Mercati algoritmici: multigoal, esito_1t, over_under_1t, goal_nogoal_1t.
# Scarica il service account JSON: Console → Project settings → Service accounts
set GOOGLE_APPLICATION_CREDENTIALS=C:\path\serviceAccount.json
npm run seed:quiz
npm run dev # sviluppo
npm run check # tsc + eslint + vitest
npm run build # produzione
| Collection | Doc ID | Scrittura | Contenuto |
|---|---|---|---|
profiles | {uid} | Functions (client: solo username/avatar) | punti, gettoni, statistiche, missioni riscosse |
matchdays | {number}, _meta | Solo Functions | partite, risultati (anche HT), quote ufficiali, deadline |
schedine | {uid}_{matchday} o {uid}_{matchday}_{lega} | Solo Functions | pronostici, power-up, risultati valutati |
leagues | auto | Client (rules vincolate) | leghe private, codici invito, membri |
leagues/{id}/standings | {uid} | Solo Functions | classifica di lega, alimentata dalle schedine di lega |
wallet_transactions | auto | Solo Functions | audit trail gettoni |
prizes | weekly_{n}, … | Solo Functions | albo d'oro: podio di giornata e premio assegnato |
weekly_prizes | {matchday} | Solo Functions (admin) | premi in palio per una giornata |
quiz_questions | q001… | Seed script | pool domande quiz |
quiz_sessions | {uid} | Solo Functions | sessione quiz anti-cheat |
syncMatchday (ogni 6h) crea la prossima giornata con quote server-sidesubmitSchedina (deadline enforced)settleMatchdays (ogni ora, post-deadline) legge i risultati ESPNweeklyPoints dei non-giocantinpm test # test unitari (logica pura)
npm run test:coverage # con soglie di copertura
npm run check # typecheck + lint (0 warning) + test + coverage
npm run check:bundle # budget di dimensione (richiede build)
npm run audit:prod # CVE sulle sole dipendenze di produzione
npm run test:integration # callable contro l'emulatore Firestore (richiede Java)
npm run test:e2e # Playwright contro gli emulatori Firebase
Coperti dai test unitari: scoring client e server, motore quote, economia, classifiche, sorgente casuale, motore rigori, client HTTP resiliente, contabilità dei power-up.
Coperti dai test di integrazione (functions/src/__tests__/*.itest.ts):
invio e reinvio della schedina con addebito/rimborso dei power-up,
annullamento, Cambio Last-Minute, settlement di giornata, duelli con tetto
giornaliero e pulizia, minigiochi, classifica generale e di lega. Girano
contro un Firestore vero perché transazioni e idempotenza non si verificano
con dei mock.
Non ancora coperto: leghe (manageLeague), missioni (claimMission),
quiz e cancellazione account.
Se l'emulatore Firestore non parte con Unable to establish loopback connection, il JVM non riesce a creare il socket AF_UNIX nella cartella
temporanea di default (tipico dei path con nome corto tipo GIUSEP~1).
Si risolve indicandogliene un'altra:
setx JAVA_TOOL_OPTIONS "-Djdk.net.unixdomain.tmpdir=C:\jtmp"
Il deploy in produzione avviene solo dalla CI, con approvazione manuale.
Non usare vercel --prod da locale: pubblicherebbe codice che non ha superato
i gate.
GitHub → Actions → Deploy in produzione → Run workflow.
Procedura completa, configurazione dei secret e criteri di abort:
docs/runbook/deploy.md.
| Documento | Quando serve |
|---|---|
docs/runbook/deploy.md | Rilasciare |
docs/runbook/rollback.md | Tornare indietro |
docs/runbook/backup-restore.md | Backup e ripristino |
docs/runbook/incidenti.md | Qualcosa è rotto |
docs/runbook/osservabilita.md | Sentry, uptime, alert |
docs/runbook/app-check.md | Attivare App Check |
SECURITY.md | Postura di sicurezza e limiti noti |
docs/privacy/registro-trattamenti.md | Adempimenti GDPR |
Prima di aprire al pubblico vanno chiusi:
docs/runbook/app-check.md)