AZIONE: A seconda del tuo uso di internet inserisci il numero di ore/giorno nelle diverse opzioni.
💎HACKER TIP: Clicca sui diamanti criptati per svelare i retroscena dei server e guadagnare +20 XP ciascuno!
⚠️ FIREWALL: DATA CLASH
DOMANDA 1 / 4
✔️ FIREWALL BYPASSATO. IDENTITÀ CONFERMATA.
⚠️ DATA ANALYSIS: L’ICEBERG PERSONALE
1. IL TUO ICEBERG (ANNUALE)
🏠 ENERGIA UTILE (HARDWARE IN USO)
0 kWh/ANNO
⚡ VAMPIRE DRAIN (SPRECO HARDWARE)
0 kWh/ANNO
👻 CLOUD BACKGROUND (NOTIFICHE E PATCH)
0 GB -> 0 kWh/ANNO
☁ CLOUD ATTIVO (LE TUE AZIONI)
0 GB -> 0 kWh/ANNO
2. L’IMPRONTA DELLA TUA GENERAZIONE
EMISSIONI CO2 ANNUALI PER SINGOLO STUDENTE (USO SOCIAL E WEB)
MEDIA STUDENTI99 kg CO₂
IL TUO PROFILO ATTUALE (STIMA)0 kg CO₂
🌍 TRADUTTORE DI REALTÀ
quante volte potresti caricare da 0 a 100% il tuo cellulare ogni singolo giorno usando solo l’energia che i server bruciano per il tuo traffico dati?
UNA, DIECI, CENTO BATTERIE!
TOTALE: 0 RICARICHE AL GIORNO
MALUS: STAI PAGANDO INUTILMENTE SULLA BOLLETTA PER IL VAMPIRE DRAIN LOCALE.
🌍 L’ICEBERG GLOBALE (SETTORE ICT)
Il peso reale del mondo digitale sull’intero pianeta.
1. LA NAZIONE INVISIBILE
CLASSIFICA DEI CONSUMI ELETTRICI (TERAWATT-ORA ALL’ANNO)
🇨🇳 CINA~ 10.000 TWh
🇺🇸 STATI UNITI~ 4.500 TWh
🌐 INTERNET E SETTORE DIGITALE (ICT)~ 2.500 TWh
🇮🇹 ITALIA~ 300 TWh
2. IL 10% DEL PIANETA TERRA
TUTTA L’ELETTRICITÀ PRODOTTA NEL MONDO25.000 TWh
QUOTA ASSORBITA DAL DIGITALE (ICT)10%
3. IL PESO DEL VIRTUALE SUL REALE
CONFRONTO DI ASSORBIMENTO (SOLO ELETTRICITÀ)
TUTTE LE CASE DEL MONDO (Residenziale)~ 6.750 TWh
TUTTI GLI UFFICI/NEGOZI (Commerciale e Servizi)~ 5.250 TWh
L’INTERO MONDO DIGITALE (Settore ICT)~ 2.500 TWh
TRASPORTI ELETTRICI (Treni, Metro, Auto EV)~ 500 TWh
ZONA DI OVERRIDE
SCONFIGGI LE IMPOSTAZIONI DI FABBRICA (DEFAULT)
IL CODICE DELL’ECO-HACKER
CODICE 01: BYPASS DI RETE
ENERGIA PER TRASPORTARE 1 GB DI DATI
FIBRA + WI-FI DI CASA~50 Wh
WI-FI PUBBLICO / SCUOLA~80 Wh
RETE MOBILE (4G/5G)~250 Wh
CODICE 02: DOWNGRADE VIDEO
IMPATTO PER 1 ORA DI CONTENUTO
TESTO E IMMAGINI WEB~0.1 GB
VIDEO STANDARD / HD~1.0 GB
VIDEO 4K ULTRA HD~7.0 GB
CODICE 03: CONTENIMENTO I.A.
ENERGIA PER UNA SINGOLA OPERAZIONE
RICERCA WEB CLASSICA~0.3 Wh
TESTO I.A. (ES. CHATGPT)~3.0 Wh
GENERARE 1 IMMAGINE I.A.~15.0 Wh
GENERARE 1 VIDEO I.A.~50.0 Wh
CODICE 04: BLOCCO PRE-LOAD
IMPATTO PER 1 ORA DI UTILIZZO
CHAT E TESTO< 0.1 GB
SCROLL FOTO (PINTEREST, X)~ 0.5 GB
VIDEO E REELS (INSTAGRAM)~ 1.5 GB
PRE-LOAD AGGRESSIVO (TIKTOK)~ 2.5 GB
CODICE 05: STOP VAMPIRE DRAIN
PARADOSSO CONSOLE (2H GIOCO VS 22H STANDBY)
ATTIVA (GIOCANDO PER 2 ORE)~300 Wh
STANDBY DI RETE (RESTANTI 22 ORE)~330 Wh
CODICE 06: LONGEVITÀ DEL LITIO
IMPATTO REALE (CO2)
ELETTRICITÀ RICARICHE (10 ANNI DI FILA)~20 kg
PRODUZIONE DI UN SOLO TELEFONO NUOVO~80 kg
ORA APPLICA IL CODICE: SELEZIONA UN NODO E SEGUI LE ISTRUZIONI PER HACKERARE GLI SPRECHI NELLE TUE APP.
📊 RIEPILOGO DEBRIEFING
🤖
ANALISI COMPORTAMENTALE: TITOLO ASSEGNATO
…
…
LA TUA IMPRONTA VS MEDIA STUDENTI
MEDIA ANNUALE DI UN COETANEO99 kg CO₂
LA TUA IMPRONTA DOPO GLI HACK… kg CO₂
Più la barra è corta, meglio è per il pianeta.
LOOT / VANTAGGIO REALE PER LA FAMIGLIA
💵BOLLETTA:≈ –0 €/y
📶GIGA SALVATI:≈ 0 GB/y
☁CO2 EVITATA:≈ 0 kg/y
🔋BATTERIA:≈ +0 h/g
🏆
PATTO DI FAMIGLIA
DIVENTA ENERGY MANAGER E SCATTA IL SELFIE SQUADRA
🛡️
PATTO ENERGIADI
FIRMA E RADDOPPIA I wattORO
📡 INCOMING TRANSMISSION…
⚡ TARGET ACQUISITO ⚡
TERMINALE OVERRIDE
DEFAULT: ANALISI IN CORSO…
📱
SYS_OP: OVERRIDE_MODE
STATUS: SEARCHING…
SEC_LVL: ENCRYPTED
> Scanning device settings… > Bypassing factory default… > Looking for data saver flag… > Awaiting agent verification…
PERCORSO GUIDATO: Seleziona il tuo sistema operativo per sbloccare la missione.
🔍 CACCIA AL TESORO: Trova la voce sul tuo schermo e inserisci la parola chiave qui sotto.
🏆 PATTO DI FAMIGLIA & ENERGY MANAGER
Congratulazioni! Sei stato investito ufficialmente del ruolo di Energy Manager / Energy Hacker di casa. Coinvolgi genitori, fratelli e sorelle per eliminare gli sprechi in standby e lo streaming non necessario.
📷 SELFIE DI SQUADRA (FOTO-PROVA LIVE)
SELFIE ACQUISITO CORRETTAMENTE ✔️
Scatta un selfie in famiglia direttamente con la fotocamera del tuo dispositivo vicino alla ciabatta spenta o al logbook.
STATO: PATTO NON ANCORA FIRMATO CON IL SELFIE
🛡️ PATTO UFFICIALE ENERGIADI
Eco hacker … hai raggiunto nuove conoscenze, è ora di agire! Firma il patto con le Energiadi, mantieni le app hackerate per almeno 8 settimane e compila il CRONACHE ECO-HACKER (Diario di Bordo). In cambio le Energiadi raddoppiano i tuoi punti xp e li trasformano in wattORO, utile per vincere la gara delle Energiadi.
FIRMA DIGITALE A PRESSIONE
TIENI PREMUTO PER 2 SECONDI PER FIRMARE IL PATTO
✔️ PATTO FIRMATO CON SUCCESSO! WattORO Raddoppiati (x2).
📓 CRONACHE ECO-HACKER (DIARIO DI BORDO)
REGISTRA IL TUO CONTROLLO PERIODICO (MAX 1 VOLTA AL GIORNO):
`; throw new Error("Security Override: Domain Mismatch."); } const audioFX = { ctx: null, bgGain: null, isMuted: false, initialized: false, init: function() { if (this.initialized) return; window.AudioContext = window.AudioContext || window.webkitAudioContext; if(!window.AudioContext) return; this.ctx = new AudioContext(); this.initialized = true; this.startCyberDrone(); document.getElementById('btn-audio').innerText = "🔊"; }, toggleMute: function() { if (!this.initialized) { this.init(); return; } this.isMuted = !this.isMuted; if (this.bgGain) this.bgGain.gain.setTargetAtTime(this.isMuted ? 0 : 0.20, this.ctx.currentTime, 0.1); document.getElementById('btn-audio').innerText = this.isMuted ? "🔇" : "🔊"; }, startCyberDrone: function() { if (!this.ctx) return; this.bgGain = this.ctx.createGain(); this.bgGain.gain.value = this.isMuted ? 0 : 0.20; this.bgGain.connect(this.ctx.destination); const arpPattern = [130.81, 155.56, 130.81, 196.00, 130.81, 233.08, 130.81, 196.00]; let step = 0; setInterval(() => { if (this.isMuted) return; const now = this.ctx.currentTime; const currentStep = step % 8; if (currentStep % 4 === 0) { const kickOsc = this.ctx.createOscillator(); const kickGain = this.ctx.createGain(); kickOsc.frequency.setValueAtTime(100, now); kickOsc.frequency.exponentialRampToValueAtTime(10, now + 0.15); kickGain.gain.setValueAtTime(0.8, now); kickGain.gain.exponentialRampToValueAtTime(0.01, now + 0.15); kickOsc.connect(kickGain); kickGain.connect(this.bgGain); kickOsc.start(now); kickOsc.stop(now + 0.2); } const freq = arpPattern[currentStep]; if (freq) { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sawtooth'; osc.frequency.value = freq; gain.gain.setValueAtTime(0.1, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.1); osc.connect(gain); gain.connect(this.bgGain); osc.start(now); osc.stop(now + 0.15); } step++; }, 140); }, playClick: function() { if (!this.ctx || this.isMuted) return; const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'square'; osc.frequency.setValueAtTime(800, this.ctx.currentTime); osc.frequency.exponentialRampToValueAtTime(300, this.ctx.currentTime + 0.05); gain.gain.setValueAtTime(0.05, this.ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.05); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(); osc.stop(this.ctx.currentTime + 0.05); }, playTransition: function() { if (!this.ctx || this.isMuted) return; const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(400, this.ctx.currentTime); osc.frequency.exponentialRampToValueAtTime(100, this.ctx.currentTime + 0.2); gain.gain.setValueAtTime(0.1, this.ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.2); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(); osc.stop(this.ctx.currentTime + 0.2); }, playError: function() { if (!this.ctx || this.isMuted) return; const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(150, this.ctx.currentTime); osc.frequency.exponentialRampToValueAtTime(80, this.ctx.currentTime + 0.3); gain.gain.setValueAtTime(0.2, this.ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.3); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(); osc.stop(this.ctx.currentTime + 0.3); }, playSuccess: function() { if (!this.ctx || this.isMuted) return; const now = this.ctx.currentTime; const playNote = (freq, time) => { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.frequency.value = freq; gain.gain.setValueAtTime(0.15, time); gain.gain.exponentialRampToValueAtTime(0.001, time + 0.4); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(time); osc.stop(time + 0.4); }; playNote(523.25, now); playNote(659.25, now + 0.1); playNote(783.99, now + 0.2); playNote(1046.50, now + 0.3); } }; const app = { player: { avatar: '🤖', gametag: '', missionCode: '', xp: 0, profileName: '' }, currentStage: 0, currentTarget: 'pc', currentSelectedOS: null, capturedNodesCount: 0, localUsefulKwh: 0, localWasteKwh: 0, hwCloudBgGB: 0, cloudActiveGB: 0, cloudBackgroundGB: 0, cloudActiveKwh: 0, cloudBackgroundKwh: 0, dailyCharges: 0, tatticheCompletate: 0, ninjaCompletate: 0, typeWriterInterval: null, introShown: false, dossierArchive: [], viewedDiamonds: new Set(), clashCurrentIndex: 0, currentOverrideTarget: null, scannedTargets: new Set(), wattOro: 0, isPattoSigned: false, isFamilyPattoSigned: false, familyPhotoBase64: '', bioTimer: null, currentDiaryGametag: '', actionKeys: 0, unlockedActions: new Set(), strategyData: { 'strat-rete': { tech: "DATI DECRITTATI: L'EFFETTO PONTE RADIO\n\nTrasmettere dati via etere (4G/5G) richiede enormi antenne sempre attive. Il Wi-Fi usa i cavi fisici e richiede fino a 5 volte meno energia.", action: "Scarica film, giochi o aggiornamenti pesanti SOLO quando sei connesso al Wi-Fi. Oltre a non esaurire i Giga del tuo piano tariffario, abbatterai drasticamente l'energia bruciata dalla rete mobile!" }, 'strat-res': { tech: "DATI DECRITTATI: LA TRAPPOLA DEI PIXEL\n\nPer trasmettere un video in 4K il datacenter deve calcolare e inviare fino a 7 volte più dati rispetto al normale HD.", action: "Imposta YouTube o Netflix a 1080p o 720p quando sei su cellulare. Il tuo occhio non noterà alcuna differenza sullo schermo piccolo, ma risparmierai una quantità immensa di dati e batteria!" }, 'strat-ai': { tech: "DATI DECRITTATI: IL CERVELLO DI SILICIO\n\nLe I.A. per generare risposte usano potentissime schede video nei server, consumando tantissima elettricità e acqua per il raffreddamento.", action: "Usa le I.A. generative (come ChatGPT) solo per compiti scolastici complessi, riassunti o creatività. Se ti serve solo trovare un sito, una definizione o il meteo, usa il motore di ricerca classico: risparmierai 10 volte l'energia per lo stesso identico risultato!" }, 'strat-social': { tech: "DATI DECRITTATI: IL PARADOSSO SOCIAL\n\nPer garantirti zero attese mentre fai scroll, i Social scaricano di nascosto decine di video che forse non guarderai mai.", action: "Entra nelle impostazioni (TikTok, Instagram) e attiva il 'Risparmio Dati'. Toglierai il pilota automatico all'app, costringendo i server a inviare i dati solo per i video che decidi tu di riprodurre." }, 'strat-vampire': { tech: "DATI DECRITTATI: L'ILLUSIONE DELLO SPEGNIMENTO\n\. Le console moderne in 'Avvio Rapido' non si spengono mai davvero, succhiando energia dalla presa H24 per restare connesse.", action: "Vai nelle impostazioni e scegli lo 'Spegnimento Completo'. Aspettare 10 secondi in più per l'accensione eliminerà il Vampire Drain, facendo risparmiare alla tua famiglia decine di euro all'anno sulla bolletta!" }, 'strat-litio': { tech: "DATI DECRITTATI: IL PARADOSSO DELLA SPINA\n\nCostruire un telefono nuovo genera circa 80 kg di CO2. Ricaricarlo tutti i giorni per un anno intero genera meno di 2 kg.", action: "Evita di far spegnere il telefono allo 0% e attiva la 'Ricarica Ottimizzata' nelle impostazioni. Ridurrai lo stress chimico della batteria: il tuo device durerà 4 o 5 anni invece di 2. Far vivere a lungo l'hardware è la mossa ecologica ed economica più potente in assoluto!" } }, clashQuestions: [ { q: "I SOCIAL NETWORK CONSUMANO ENERGIA, MA CERTAMENTE MENO DI TANTE ALTRE ATTIVITÀ ONLINE, COME INVIARE MAIL, LEGGERE NOTIZIE O NAVIGARE SUI SITI WEB.", ans: false, msg: "Sembrano app leggere, ma a causa di miliardi di utenti connessi simultaneamente, i Social Network (uniti a video streaming e gaming) generano oltre il 70% di tutto il traffico globale dei datacenter.", chart: `
SITI WEB E EMAIL (TESTO)
SOCIAL, VIDEO E GAMING> 70%
` }, { q: "GUARDARE VIDEO PER 30 MINUTI SU YOUTUBE HD CONSUMA MOLTA PIÙ ENERGIA RISPETTO A SCORRERE VELOCEMENTE TIKTOK PER 30 MINUTI.", ans: false, msg: "YouTube scarica solo il video scelto. L'algoritmo di TikTok pre-carica costantemente in background decine di video HD per garantirti zero attese.\nSe fai 'swipe' rapido, forzi i server a consumare energia per contenuti che non hai mai guardato.", chart: `
YOUTUBE HD (SOLO VIDEO SCELTO)~0.4 GB
TIKTOK (PRE-LOAD CONTINUO)~1.2 GB
` }, { q: "FORZARE UN VIDEO YOUTUBE IN 4K DAL CELLULARE FA FATICARE DI PIÙ I SERVER, MA ALMENO VEDI UN'IMMAGINE MOLTO PIÙ DETTAGLIATA.", ans: false, msg: "Richiedere un flusso 4K costringe il datacenter a inviare fino a 8 volte la mole di dati di un normale video HD.\nMa su uno schermo da 6 pollici, il tuo occhio non può notare la differenza con un 1080p. Risultato? Sprecate gigabyte e batteria inutilmente.", chart: `
STREAMING HD (1080p)0.9 GB/h
STREAMING 4K (SPRECO INVISIBILE)7.0 GB/h
` }, { q: "FARE UNA RICERCA TRAMITE INTELLIGENZA ARTIFICIALE (ES. CHATGPT) CONSUMA ESATTAMENTE COME UNA NORMALE RICERCA SU GOOGLE.", ans: false, msg: "Una ricerca web classica estrae solo un link da un indice.\nL'Intelligenza Artificiale, invece, deve \"ragionare\" e generare la risposta parola per parola usando potentissime schede video.\nRisultato? Una ricerca IA consuma circa 10 volte l'energia di una ricerca standard.", chart: `
1 RICERCA WEB CLASSICA (GOOGLE)0.3 Wh
1 RICERCA CON I.A. (ES. CHATGPT)3.0 Wh
` } ], overrideTargets: [ { id: 't-battery', name: 'SMARTPHONE', icon: '🔋', trigger: 'USURA CHIMICA DA RICARICA', action: 'IMPOSTAZIONI > BATTERIA > RICARICA OTTIMIZZATA (O LIMITE 80%)', xp: 50, appLink: 'hardware_battery', reason: "Mantenere la batteria tra il 20% e l'80% non fa risparmiare sulla bolletta, ma dimezza l'usura chimica del litio. Il tuo telefono durerà anni in più prima di doverlo cambiare, salvando all'istante circa 80 kg di CO2!" }, { id: 't-tiktok', name: 'TIKTOK', icon: '', trigger: 'PRE-CARICAMENTO INVISIBILE', action: 'IMPOSTAZIONI > RISPARMIO DATI > ON', xp: 50, appLink: 'https://www.tiktok.com/', reason: "L'algoritmo scarica i 5 video successivi prima ancora che tu li veda. Se scorri via, i server hanno faticato per nulla. Il Risparmio Dati costringe l'app a scaricare solo ciò che guardi." }, { id: 't-ig', name: 'INSTAGRAM', icon: '', trigger: 'AUTOPLAY REELS', action: 'IMPOSTAZIONI E PRIVACY > USO DEI DATI > USA MENO DATI', xp: 50, appLink: 'instagram://app', reason: "Ogni volta che apri l'app, i video partono da soli scaricando decine di Megabyte in pochi secondi. Fermare l'autoplay toglie il pilota automatico: i server si attivano solo quando decidi tu." }, { id: 't-wa', name: 'WHATSAPP', icon: '', trigger: 'DOWNLOAD AUTO IN 4G', action: 'IMPOSTAZIONI > SPAZIO E DATI > SU RETE MOBILE > DESELEZIONA TUTTO', xp: 50, appLink: 'whatsapp://app', reason: "Trasportare dati in 4G costa fino a 5 volte più energia rispetto al Wi-Fi. Bloccando il download per strada, scaricherai i meme la sera usando la fibra ottica, molto più ecologica." }, { id: 't-yt', name: 'YOUTUBE', icon: '', trigger: 'RISOLUZIONE 4K SPRECATA', action: 'IMPOSTAZIONI > PREFERENZE QUALITÀ > RETE MOBILE: RISPARMIO DATI', xp: 50, appLink: 'https://www.youtube.com/', reason: "Su uno schermo da 6 pollici l'occhio non vede la differenza tra HD e 4K. Ma per inviarti il 4K, i server sudano 4 volte di più e i ripetitori bruciano giga inutili." }, { id: 't-twitch', name: 'TWITCH', icon: '', trigger: 'STREAMING PASSIVO', action: 'IMPOSTAZIONI > QUALITÀ > SOLO AUDIO (SE ASCOLTI SOLO)', xp: 50, appLink: 'https://twitch.tv/', reason: "Se metti una live in sottofondo mentre fai altro, stai scaricando gigabyte di video che non guardi. La modalità 'Solo Audio' taglia il consumo del 90%." }, { id: 't-netflix', name: 'NETFLIX', icon: '', trigger: 'ALTA QUALITÀ IN 4G', action: 'IMPOSTAZIONI APP > USO DATI CELLULARE > RISPARMIO DATI', xp: 50, appLink: 'https://netflix.com/', reason: "Scaricare un film in 4G brucia molta più energia che in Wi-Fi. Impostando il limite, i server comprimeranno il video riducendo drasticamente l'impatto sulla rete mobile." }, { id: 't-telegram', name: 'TELEGRAM', icon: '', trigger: 'AUTODOWNLOAD FILE PESANTI', action: 'IMPOSTAZIONI > DATI E ARCHIVIO > AUTODOWNLOAD > DISATTIVA IN 4G', xp: 50, appLink: 'tg://', reason: "Telegram permette l'invio di file enormi fino a 2GB! Se sei in una chat di gruppo, potresti scaricare decine di video pesantissimi in 4G senza neanche accorgertene, esaurendo Giga e batteria." }, { id: 't-roblox', name: 'ROBLOX', icon: '', trigger: 'BATTERY DRAIN DA GRAFICA 3D', action: 'IN GIOCO > SETTINGS > GRAPHICS MODE > MANUAL (ABBASSA IL LIVELLO)', xp: 50, appLink: 'https://roblox.com/', reason: "I mondi 3D ibridi come Roblox spingono la scheda grafica del telefono (GPU) al massimo. Abbassare la grafica salva la batteria, riduce il calore e allunga la vita del dispositivo." }, { id: 't-console', name: 'CONSOLE', icon: '', trigger: 'STANDBY DI RETE H24', action: 'IMPOSTAZIONI > RISPARMIO ENERGIA > SPEGNIMENTO COMPLETO', xp: 80, appLink: 'hardware_joypad', reason: "In 'Avvio Rapido' la console resta accesa di nascosto H24. Alla fine dell'anno, avrà consumato più corrente mentre era 'spenta' rispetto alle ore in cui hai giocato!" }, { id: 't-tv', name: 'SMART TV', icon: '', trigger: 'FAST START E TELEMETRIA', action: 'IMPOSTAZIONI TV > SISTEMA / RETE > DISATTIVA AVVIO RAPIDO', xp: 80, appLink: 'hardware_remote', reason: "Spegnere col telecomando disattiva solo lo schermo. La TV resta connessa per accendersi in 1 secondo o per inviare dati sulle tue abitudini (Telemetria). Stacca la spina virtuale!" } ], init: function() { this.bindEvents(); this.initDiaryEvents(); }, bindEvents: function() { const self = this; document.body.addEventListener('click', () => { if (!audioFX.initialized) audioFX.init(); }, { once: true }); document.getElementById('btn-audio')?.addEventListener('click', (e) => { e.stopPropagation(); audioFX.toggleMute(); audioFX.playClick(); }); const savedGametag = localStorage.getItem('ecoquest_gametag'); const savedMission = localStorage.getItem('ecoquest_mission'); if (savedGametag && document.getElementById('gametag')) { document.getElementById('gametag').value = savedGametag; self.player.gametag = savedGametag; } if (savedMission && document.getElementById('mission-code')) { document.getElementById('mission-code').value = savedMission; self.player.missionCode = savedMission; } if (savedGametag && savedGametag.length >= 3 && savedMission && savedMission.length >= 4) { const btn = document.getElementById('btn-start-game'); if (btn) btn.removeAttribute('disabled'); } const avatars = document.querySelectorAll('.avatar-option'); avatars.forEach(opt => { opt.addEventListener('click', function() { audioFX.playClick(); avatars.forEach(el => el.classList.remove('opt-active')); this.classList.add('opt-active'); self.player.avatar = this.dataset.avatar; checkInput(); }); }); const checkInput = () => { const gametagInput = document.getElementById('gametag'); const missionCodeInput = document.getElementById('mission-code'); const btn = document.getElementById('btn-start-game'); if (!gametagInput || !missionCodeInput || !btn) return; if (gametagInput.value.trim().length >= 3 && missionCodeInput.value.trim().length >= 4) { btn.removeAttribute('disabled'); self.player.gametag = gametagInput.value.trim().toUpperCase(); self.player.missionCode = missionCodeInput.value.trim().toUpperCase(); } else { btn.setAttribute('disabled', 'true'); } }; ['input', 'change', 'keyup'].forEach(evt => { document.getElementById('gametag')?.addEventListener(evt, () => { checkInput(); const val = document.getElementById('gametag').value.trim().toUpperCase(); if(val) localStorage.setItem('ecoquest_gametag', val); }); document.getElementById('mission-code')?.addEventListener(evt, () => { checkInput(); const val = document.getElementById('mission-code').value.trim().toUpperCase(); if(val) localStorage.setItem('ecoquest_mission', val); }); }); const bioBtn = document.getElementById('btn-biometric-scan'); const bioStatus = document.getElementById('biometric-status'); const startBioScan = (e) => { e.preventDefault(); if (self.isPattoSigned) return; audioFX.playClick(); bioStatus.innerText = "VERIFICA IMPRONTA IN CORSO..."; bioStatus.style.color = "var(--yellow-gold)"; bioBtn.style.transform = "scale(0.95)"; self.bioTimer = setTimeout(() => { self.isPattoSigned = true; audioFX.playSuccess(); bioBtn.classList.add('signed'); bioBtn.innerHTML = ''; bioBtn.style.transform = "scale(1)"; bioStatus.innerText = "SIGILLO BIOMETRICO VALIDATO ✔️"; bioStatus.style.color = "var(--lime-green)"; try { localStorage.setItem('ecoquest_signed_' + self.player.gametag, 'true'); } catch(e) {} setTimeout(() => { document.getElementById('patto-signature-box').style.display = 'none'; document.getElementById('patto-actions-view').style.display = 'flex'; }, 3000); self.calculateWattOro(); }, 2000); }; const cancelBioScan = () => { if (self.isPattoSigned) return; if (self.bioTimer) clearTimeout(self.bioTimer); bioBtn.style.transform = "scale(1)"; bioStatus.innerText = "SCANSIONE INTERROTTA. TENERE PREMUTO PER 2 SECONDI."; bioStatus.style.color = "var(--red-neon)"; }; if (bioBtn) { bioBtn.addEventListener('mousedown', startBioScan); bioBtn.addEventListener('mouseup', cancelBioScan); bioBtn.addEventListener('mouseleave', cancelBioScan); bioBtn.addEventListener('touchstart', startBioScan); bioBtn.addEventListener('touchend', cancelBioScan); } document.getElementById('gametag')?.addEventListener('blur', function() { const gt = this.value.trim().toUpperCase(); if (gt.length >= 3) { self.player.gametag = gt; localStorage.setItem('ecoquest_gametag', gt); const getUserUrl = window.location.origin + '/wp-json/ecoquest/v1/user/' + encodeURIComponent(gt); fetch(getUserUrl) .then(res => { if (!res.ok) throw new Error("Utente non trovato"); return res.json(); }) .then(serverData => { self.player.missionCode = serverData.student_profile.mission_code; self.player.avatar = serverData.student_profile.avatar; self.player.xp = serverData.game_metrics.xp_totali; self.isPattoSigned = serverData.game_metrics.patto_signed; self.isFamilyPattoSigned = serverData.game_metrics.family_patto_signed || false; self.player.profileName = serverData.student_profile.agent_title; const missionInput = document.getElementById('mission-code'); if (missionInput && serverData.student_profile.mission_code) { missionInput.value = serverData.student_profile.mission_code; localStorage.setItem('ecoquest_mission', serverData.student_profile.mission_code); } let remoteDiary = serverData.diary_bordo; if (typeof remoteDiary === 'string') { try { remoteDiary = JSON.parse(remoteDiary); } catch(e) {} } if (remoteDiary && remoteDiary.logs) { localStorage.setItem('ecoquest_diary_' + gt, JSON.stringify(remoteDiary)); } if (serverData.student_profile.avatar) { document.querySelectorAll('.avatar-option').forEach(el => { if (el.dataset.avatar === serverData.student_profile.avatar) { document.querySelectorAll('.avatar-option').forEach(o => o.classList.remove('opt-active')); el.classList.add('opt-active'); } }); } const btn = document.getElementById('btn-start-game'); if (btn) btn.removeAttribute('disabled'); self.showCyberPopup(`PROFILO ESISTENTE RICONOSCIUTO DAL CLOUD!\n\nAGENTE: ${gt}\nMISSIONE: ${self.player.missionCode}\nXP RECUPERATI: ${self.player.xp}\n\nClicca sul tasto sottostante per aprire direttamente il tuo Diario di Bordo.`, () => { const diarioModal = document.getElementById('diario-modal'); const loginView = document.getElementById('diario-login-view'); const checkinView = document.getElementById('diario-checkin-view'); const inputGt = document.getElementById('diario-input-gametag'); const welcomeTxt = document.getElementById('diario-welcome-txt'); if(inputGt) inputGt.value = gt; self.currentDiaryGametag = gt; if(loginView) loginView.style.display = 'none'; if(checkinView) checkinView.style.display = 'block'; if(welcomeTxt) welcomeTxt.innerText = `DIARIO DI BORDO AGENTE: ${gt}`; self.renderDiaryLogs(gt); if(diarioModal) diarioModal.style.display = 'flex'; }, null, "[ 📓 VAI AL DIARIO ]"); }) .catch(() => { if(!self.introShown) { self.introShown = true; self.showCyberPopup(`BENVENUTO, ECO-HACKER.\n\nI TUOI DEVICE E LE TUE APP HANNO IMPOSTAZIONI DI FABBRICA ("DEFAULT"), CHE SPESSO SERVONO SOLO A BRUCIARE ENERGIA E DATI.\n\nINSERISCI I TUOI DATI PER INIZIARE L'INDAGINE, TAGLIARE GLI SPRECHI E SBLOCCARE VANTAGGI REALI.`); } }); } }); document.getElementById('btn-start-game')?.addEventListener('click', function(e) { e.preventDefault(); const gt = self.player.gametag; if (!gt) return; const getUserUrl = window.location.origin + '/wp-json/ecoquest/v1/user/' + encodeURIComponent(gt); fetch(getUserUrl) .then(res => { if (!res.ok) throw new Error("Utente non trovato"); return res.json(); }) .then(serverData => { self.player.missionCode = serverData.student_profile.mission_code; self.player.avatar = serverData.student_profile.avatar; self.player.xp = serverData.game_metrics.xp_totali; self.isPattoSigned = serverData.game_metrics.patto_signed; self.isFamilyPattoSigned = serverData.game_metrics.family_patto_signed || false; self.player.profileName = serverData.student_profile.agent_title; localStorage.setItem('ecoquest_gametag', gt); if (serverData.student_profile.mission_code) { localStorage.setItem('ecoquest_mission', serverData.student_profile.mission_code); } if (self.isPattoSigned) { localStorage.setItem('ecoquest_signed_' + gt, 'true'); } if (self.isFamilyPattoSigned) { localStorage.setItem('ecoquest_family_signed_' + gt, 'true'); } let remoteDiary = serverData.diary_bordo; if (typeof remoteDiary === 'string') { try { remoteDiary = JSON.parse(remoteDiary); } catch(e) {} } if (remoteDiary && remoteDiary.logs) { localStorage.setItem('ecoquest_diary_' + gt, JSON.stringify(remoteDiary)); } document.getElementById('main-hud').style.display = 'flex'; document.getElementById('hud-gametag').innerText = gt; document.getElementById('hud-avatar-icon').innerText = self.player.avatar; self.updateXpHud(0); self.showCyberPopup(`BENTORNATO, AGENTE ${gt}!\n\nPROFILO E PROGRESSI RECUPERATI DAL CLOUD.\n\nACCESSO DIRETTO AL DIARIO DI BORDO (CRONACHE ECO-HACKER).`, () => { const diarioModal = document.getElementById('diario-modal'); const loginView = document.getElementById('diario-login-view'); const checkinView = document.getElementById('diario-checkin-view'); const inputGt = document.getElementById('diario-input-gametag'); const welcomeTxt = document.getElementById('diario-welcome-txt'); if(inputGt) inputGt.value = gt; self.currentDiaryGametag = gt; if(loginView) loginView.style.display = 'none'; if(checkinView) checkinView.style.display = 'block'; if(welcomeTxt) welcomeTxt.innerText = `DIARIO DI BORDO AGENTE: ${gt}`; self.renderDiaryLogs(gt); if(diarioModal) diarioModal.style.display = 'flex'; }, null, "[ 📓 VAI AL DIARIO ]"); }) .catch(err => { localStorage.setItem('ecoquest_gametag', gt); localStorage.setItem('ecoquest_mission', self.player.missionCode); self.showCyberPopup(`INIZIO FASE 1: SCANNER LOCALE.\n\nL'OBIETTIVO È REGISTRARE I CONSUMI HARDWARE E STANARE IL 'VAMPIRE DRAIN': L'ENERGIA CHE I TUOI DEVICE SPRECANO IN CASA ANCHE QUANDO CREDI SIANO SPENTI.\n\nSELEZIONA I BERSAGLI E CONFIGURA I PARAMETRI.`, () => { document.getElementById('main-hud').style.display = 'flex'; document.getElementById('hud-gametag').innerText = self.player.gametag; document.getElementById('hud-avatar-icon').innerText = self.player.avatar; self.showStage(1); self.setTarget('pc'); }); }); }); document.getElementById('btnTargetPC')?.addEventListener('click', function() { self.setTarget('pc'); }); document.getElementById('btnTargetTV')?.addEventListener('click', function() { self.setTarget('tv'); }); document.getElementById('btnTargetConsole')?.addEventListener('click', function() { self.setTarget('console'); }); document.getElementById('btnTargetPhone')?.addEventListener('click', function() { self.setTarget('phone'); }); document.getElementById('btnTargetCharger')?.addEventListener('click', function() { self.setTarget('charger'); }); document.getElementById('btnTargetRouter')?.addEventListener('click', function() { self.setTarget('router'); }); document.getElementById('btnCaptureSketch')?.addEventListener('click', function() { self.openProfilerModal(); }); // 1. Dichiara il contatore globale all'inizio (o assicurati che non venga sovrascritto) self.scanCount = self.scanCount || 0; const MAX_SCANS = 6; document.getElementById('btn-confirm-hw')?.addEventListener('click', function() { // 2. Esegue il salvataggio dei dati e l'animazione del tuo script originale self.processHwProfile(); // 3. Incrementa il contatore delle scansioni effettuate self.scanCount++; // 4. Verifica se abbiamo raggiunto il limite di 6 scansioni if (self.scanCount >= MAX_SCANS) { // FASE COMPLETATA: Disattiviamo il sistema const btnCapture = document.getElementById('btnCaptureSketch'); if (btnCapture) { btnCapture.disabled = true; btnCapture.style.pointerEvents = 'none'; btnCapture.style.opacity = '0.4'; btnCapture.style.filter = 'grayscale(100%)'; btnCapture.innerHTML = '✔️ TUTTI I NODI SCANSIONATI'; } // Opzionale: scurisce l'area del mirino per far capire che è inattiva const viewfinderArea = document.querySelector('.viewfinder'); if (viewfinderArea) { viewfinderArea.style.opacity = '0.5'; viewfinderArea.style.pointerEvents = 'none'; } // Mostra il pulsante per procedere al Cloud (Diagnosi) const btnGoCloud = document.getElementById('btn-go-to-diagnosi'); if (btnGoCloud) { btnGoCloud.style.display = 'block'; } } else { // NON ABBIAMO ANCORA FINITO (Meno di 6 scansioni) // Aspettiamo un attimo che l'interfaccia si aggiorni con il box verde, // poi selezioniamo automaticamente il primo target grigio (non ancora fatto) disponibile. setTimeout(() => { // Cerchiamo i bottoni originali usando una classe che sappiamo scomparire quando diventano verdi // Se i bottoni grigi perdono '.btn-target' o '.target-active' quando diventano verdi, usiamo quello const remainingTargets = document.querySelectorAll('.target-selector .btn-target:not(.target-active)'); // Sostituisci ':not(.target-active)' con la logica corretta se necessario // Un approccio più sicuro se i bottoni verdi non sono più pulsanti cliccabili: const clickableTargets = Array.from(document.querySelectorAll('.target-selector button.btn-target')); // Troviamo il primo bottone che non contiene il segno di spunta '✓' (o altra classe che usi per i verdi) const nextTarget = clickableTargets.find(btn => !btn.innerText.includes('✓')); if (nextTarget) { nextTarget.click(); } }, 500); } }); document.getElementById('btn-go-to-diagnosi')?.addEventListener('click', function(e) { e.preventDefault(); self.showCyberPopup("INIZIO FASE 2: PROFILAZIONE CLOUD.\n\nIL CONSUMO FISICO DEI TUOI DISPOSITIVI È SOLO L'INIZIO.\n\nOGNI AZIONE CHE FAI E OGNI VIDEO CHE GUARDI SVEGLIANO ENORMI SERVER LONTANI DA TE, CHE BRUCIANO CORRENTE H24.\n\nDICHIARA LE TUE ABITUDINI SOFTWARE.\n\n⚠️ TIP: CLICCA SUI DIAMANTI PER DECRITTARE DATI SEGRETI E GUADAGNARE +20 XP.", () => { self.showStage(2); }); }); document.getElementById('btn-go-to-minigame')?.addEventListener('click', function(e) { e.preventDefault(); self.calculateCloudGB(); self.showCyberPopup("ATTENZIONE: BLOCCO DI SICUREZZA (DATA CLASH).\n\nPRIMA DI VEDERE I RISULTATI DELLA TUA RICERCA, DEVI DIMOSTRARE DI NON ESSERE UN BOT INFILTRATO.\n\nSMASCHERA LE ILLUSIONI DIGITALI SUI CONSUMI PER BYPASSARE IL FIREWALL.", () => { self.clashCurrentIndex = 0; self.renderClashQuestion(); self.showStage('2bis'); }); }); document.getElementById('btn-generate-diagnosis')?.addEventListener('click', function(e) { e.preventDefault(); self.showCyberPopup("ACCESSO CONSENTITO.\nFASE 3: L'ICEBERG PERSONALE.\n\nLA PUNTA VISIBILE È L'HARDWARE CHE HAI IN CASA E I SUOI CONSUMI NASCOSTI.\nLA MASSA SOMMERSA È L'ENORME ENERGIA RICHIESTA DALLE ANTENNE E DALLE DATACENTER PER INVIARE I DATI.\n\nANALIZZA I TUOI GRAFICI E SCOPRI IL TUO IMPATTO.", () => { self.generateIceberg(); }); }); document.getElementById('btn-play-reality')?.addEventListener('click', function(e) { e.preventDefault(); audioFX.playClick(); document.getElementById('reality-trigger-box').style.display = 'none'; const optionsContainer = document.getElementById('reality-options-container'); optionsContainer.style.display = 'flex'; optionsContainer.scrollIntoView({ behavior: 'smooth', block: 'center' }); self.animateBatteries(self.dailyCharges); }); document.getElementById('btn-go-to-macro')?.addEventListener('click', function(e) { e.preventDefault(); self.showCyberPopup("CREDI CHE I GRANDI MOSTRI SUCCHIA-ENERGIA SIANO SOLO LE FABBRICHE CON LE CIMINIERE O LE METROPOLI ILLUMINATE? SBAGLIATO.\n\nOGGI, IL MONDO 'INVISIBILE' DI INTERNET, DELLE APP E DEI SERVER CONSUMA DA SOLO L'ENERGIA DI 1/3 DI TUTTE LE CASE DEL PIANETA.\n\nI TUOI GIGA PESANO. SCOPRI QUANTO.", () => { self.showStage('3-macro'); setTimeout(() => { document.querySelectorAll('#stage-3-macro .macro-bar').forEach(bar => { const w = bar.getAttribute('data-width'); if(w) bar.style.width = w; }); }, 200); }); }); document.getElementById('btn-go-to-tactics')?.addEventListener('click', function(e) { e.preventDefault(); self.showCyberPopup("FASE 4: ZONA DI OVERRIDE.\n\nORA CHE CONOSCI L'ENORMITÀ DEI CONSUMI GLOBALI DELLA RETE, È IL MOMENTO DI AGIRE.\n\nSTUDIA IL CODICE DELL'ECO-HACKER E RICERCA LE OPPORTUNITÀ DI AZIONE REALI.\n\nPOI SCONFIGGI LE IMPOSTAZIONI DI FABBRICA DELLE TUE APP E CARICA LE PROVE DEGLI HACK.", () => { self.showStage(4); self.renderTacticsGrid(); setTimeout(() => { document.querySelectorAll('#stage-4 .strat-bar').forEach(bar => { const w = bar.getAttribute('data-width'); if(w) bar.style.width = w; }); }, 300); }); }); document.getElementById('modal-file-upload')?.addEventListener('change', function(e) { if(e.target.files && e.target.files[0]) { self.processScreenshotModal(e.target.files[0], this.getAttribute('data-action')); this.value = ''; } }); document.getElementById('btn-go-to-debriefing')?.addEventListener('click', function(e) { e.preventDefault(); self.generateDebriefing(); }); }, openFamilyDealModal: function() { audioFX.playClick(); const modal = document.getElementById('family-deal-modal'); if(this.isFamilyPattoSigned) { document.getElementById('family-patto-status-msg').innerText = "PATTO DI FAMIGLIA GIÀ FIRMATO E BONUS +200 XP ACQUISITO ✔️"; document.getElementById('btn-confirm-family-patto').style.display = 'none'; } modal.style.display = 'flex'; }, closeFamilyDealModal: function() { this.stopFamilyCamera(); document.getElementById('family-deal-modal').style.display = 'none'; }, startFamilyCamera: async function() { audioFX.playClick(); const video = document.getElementById('familyCameraStream'); document.getElementById('family-photo-start-controls').style.display = 'none'; document.getElementById('family-camera-container').style.display = 'block'; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { try { const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' }, audio: false }); video.srcObject = stream; } catch (err) { console.warn('Cam non disponibile:', err); alert("Impossibile accedere alla fotocamera. Verifica i permessi del browser."); document.getElementById('family-photo-start-controls').style.display = 'block'; document.getElementById('family-camera-container').style.display = 'none'; } } else { alert("La fotocamera non è supportata da questo browser."); } }, stopFamilyCamera: function() { const video = document.getElementById('familyCameraStream'); if (video && video.srcObject) { video.srcObject.getTracks().forEach(track => track.stop()); video.srcObject = null; } }, captureFamilyPhoto: function() { audioFX.playSuccess(); const video = document.getElementById('familyCameraStream'); const canvas = document.createElement('canvas'); const width = 480; const height = 360; canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); if(video && video.readyState === 4) { ctx.drawImage(video, 0, 0, width, height); } else { ctx.fillStyle = "#120F24"; ctx.fillRect(0, 0, width, height); } this.familyPhotoBase64 = canvas.toDataURL('image/jpeg'); this.stopFamilyCamera(); document.getElementById('family-camera-container').style.display = 'none'; const previewContainer = document.getElementById('family-photo-preview-container'); const previewImg = document.getElementById('family-photo-preview'); previewImg.src = this.familyPhotoBase64; previewContainer.style.display = 'block'; document.getElementById('family-patto-status-msg').innerText = "SELFIE DI SQUADRA ACQUISITO! PRONTO PER IL SIGILLO."; document.getElementById('btn-confirm-family-patto').removeAttribute('disabled'); }, retakeFamilyPhoto: function() { audioFX.playClick(); this.familyPhotoBase64 = ''; document.getElementById('family-photo-preview-container').style.display = 'none'; document.getElementById('btn-confirm-family-patto').setAttribute('disabled', 'true'); document.getElementById('family-patto-status-msg').innerText = "STATO: PATTO NON ANCORA FIRMATO CON IL SELFIE"; this.startFamilyCamera(); }, confirmFamilyPatto: function() { if(!this.familyPhotoBase64) { alert("Scatta prima il selfie di famiglia per sigillare l'accordo!"); return; } if(this.isFamilyPattoSigned) return; this.isFamilyPattoSigned = true; audioFX.playSuccess(); this.updateXpHud(200); try { localStorage.setItem('ecoquest_family_signed_' + this.player.gametag, 'true'); } catch(e) {} document.getElementById('family-patto-status-msg').innerText = "PATTO FIRMATO E SELFIE SQUADRA SALVATO! +200 XP AGGIUNTI 🌟"; document.getElementById('btn-confirm-family-patto').style.display = 'none'; this.showCyberPopup("🏆 PATTO DI FAMIGLIA SIGILLATO CON SUCCESSO!\n\nSei ufficialmente l'Energy Manager di casa. +200 XP aggiunti al tuo profilo!"); setTimeout(() => { this.closeFamilyDealModal(); }, 2000); }, openPattoModal: function() { audioFX.playClick(); document.getElementById('patto-user-gt').innerText = this.player.gametag || 'AGENTE'; document.getElementById('patto-energiadi-modal').style.display = 'flex'; }, initDiaryEvents: function() { const self = this; document.getElementById('btn-verify-diario-gametag')?.addEventListener('click', () => { audioFX.playClick(); const gtInput = document.getElementById('diario-input-gametag'); if (!gtInput) return; const gt = gtInput.value.trim().toUpperCase(); if (!gt || gt.length { if (!res.ok) throw new Error("Utente non trovato nel cloud"); return res.json(); }) .then(serverData => { self.player.gametag = serverData.student_profile.gametag; self.player.missionCode = serverData.student_profile.mission_code; self.player.avatar = serverData.student_profile.avatar; self.player.xp = serverData.game_metrics.xp_totali; self.isPattoSigned = serverData.game_metrics.patto_signed; self.isFamilyPattoSigned = serverData.game_metrics.family_patto_signed || false; let remoteDiary = serverData.diary_bordo; if (typeof remoteDiary === 'string') { try { remoteDiary = JSON.parse(remoteDiary); } catch(e) {} } if (remoteDiary && remoteDiary.logs) { localStorage.setItem('ecoquest_diary_' + gt, JSON.stringify(remoteDiary)); } if (self.isPattoSigned) { localStorage.setItem('ecoquest_signed_' + gt, 'true'); } if (self.isFamilyPattoSigned) { localStorage.setItem('ecoquest_family_signed_' + gt, 'true'); } proceedToDiaryView(gt); }) .catch(() => { proceedToDiaryView(gt); }); }); function proceedToDiaryView(gt) { self.currentDiaryGametag = gt; self.player.gametag = gt; const loginView = document.getElementById('diario-login-view'); const checkinView = document.getElementById('diario-checkin-view'); const welcomeTxt = document.getElementById('diario-welcome-txt'); if (loginView) loginView.style.display = 'none'; if (checkinView) checkinView.style.display = 'block'; if (welcomeTxt) welcomeTxt.innerText = `CRONACHE ECO-HACKER: ${gt}`; self.renderDiaryLogs(gt); } document.querySelectorAll('.btn-diario-status').forEach(btn => { btn.addEventListener('click', function() { audioFX.playClick(); const status = this.dataset.status; const gt = self.currentDiaryGametag || self.player.gametag; if (!gt) return; try { const storageKey = 'ecoquest_diary_' + gt; let diaryData = JSON.parse(localStorage.getItem(storageKey) || '{"logs":[]}'); const now = new Date(); if (diaryData.logs.length > 0) { const lastLog = new Date(diaryData.logs[diaryData.logs.length - 1].date); const diffHours = (now - lastLog) / (1000 * 60 * 60); if (diffHours STORICO CHECK-IN (CRONACHE ECO-HACKER):
`; }); }, overrideStep: 0, overrideCalcData: {}, tickerInterval: null, // Alfabeto italiano a 21 lettere (1..21) per coerenza totale tra calcolo iniziale e matrice finale italianAlphabet: "ABCDEFGHILMNOPQRSTUVZ", // Matrice delle 13 domande/risposte (corrispondenti alle somme delle cifre 1..13 nell'alfabeto italiano) matrice13Domande: { 1: { lettera: 'A', parola: 'AZZERARE', domanda: "Qual è l'azione di spegnere totalmente un dispositivo anziché lasciarlo in standby?" }, 2: { lettera: 'B', parola: 'BLUETOOTH', domanda: "Quale connessione wireless a corto raggio conviene spegnere quando non usi cuffie o smartwatch per risparmiare batteria?" }, 3: { lettera: 'C', parola: 'CARICATORE', domanda: "Quale accessorio consuma corrente 'fantasma' se lasciato attaccato alla presa a vuoto?" }, 4: { lettera: 'D', parola: 'DATI', domanda: "Cosa trasporta la rete 4G/5G consumando fino a 5 volte più energia rispetto al Wi-Fi?" }, 5: { lettera: 'E', parola: 'ENERGIA', domanda: "Quale risorsa invisibile bruciano H24 i datacenter per mantenere attivi i server?" }, 6: { lettera: 'F', parola: 'FERMA', domanda: "Cosa bisogna fare all'autoplay dei video per bloccare lo spreco automatico di giga?" }, 7: { lettera: 'G', parola: 'GIGA', domanda: "Quale unità di misura del traffico dati schizza alle stelle guardando video in 4K?" }, 8: { lettera: 'H', parola: 'HACKER', domanda: "Come si chiama l'agente speciale che sconfigge le impostazioni di fabbrica (Default)?" }, 9: { lettera: 'I', parola: 'INTERNET', domanda: "Come si chiama la 'Nazione Invisibile' che consuma circa il 10% dell'elettricità mondiale?" }, 10: { lettera: 'L', parola: 'LITIO', domanda: "Quale metallo leggero compone le batterie ricaricabili di smartphone e console?" }, 11: { lettera: 'M', parola: 'MEME', domanda: "Come si chiamano le immagini divertenti virali che, inviate e scaricate a raffica nelle chat, pesano molto più del semplice testo?" }, 12: { lettera: 'N', parola: 'NOTIFICHE', domanda: "Quali avvisi continui risvegliano i server e illuminano lo schermo del telefono in background?" }, 13: { lettera: 'O', parola: 'OFFLINE', domanda: "In quale modalità senza connessione puoi leggere, ascoltare musica già scaricata o giocare risparmiando energia?" } }, // Restituisce la parola chiave tematica e l'indizio (senza svelare il numero di lettere) per annullare A getAppKeywordChallenge: function(appLettersCount) { const challenges = { 6: { word: "SERVER", clue: "Sottrai il numero di lettere del computer centrale che ospita e invia i video online (inizia per S):" }, 7: { word: "STANDBY", clue: "Sottrai il numero di lettere dello stato di 'finto spegnimento' con la lucina rossa accesa (inizia per S):" }, 8: { word: "BATTERIA", clue: "Sottrai il numero di lettere del componente al litio che alimenta lo smartphone (inizia per B):" }, 9: { word: "STREAMING", clue: "Sottrai il numero di lettere della trasmissione video continua in diretta o on-demand via internet (inizia per S):" }, 10: { word: "DATACENTER", clue: "Sottrai il numero di lettere degli enormi capannoni pieni di computer che raffreddano il cloud (inizia per D):" } }; return challenges[appLettersCount] || { word: "SERVER", clue: "Sottrai il numero di lettere del computer centrale che ospita i dati online (inizia per S):" }; }, // Converte una lettera dell'alfabeto italiano (A-Z -> 1-21) o un numero 1-21 parseItalianLetterOrNumber: function(val) { const clean = val.trim().toUpperCase(); if (/^[A-Z]$/.test(clean)) { const idx = this.italianAlphabet.indexOf(clean); if (idx !== -1) return idx + 1; // Gestione eventuali lettere straniere J, K, W, X, Y ricondotte alla posizione standard const fullIdx = clean.charCodeAt(0) - 64; return Math.min(21, fullIdx); } const num = parseInt(clean, 10); if (!isNaN(num) && num >= 1 && num t.id === targetId); if (!target) return; this.currentOverrideTarget = target; this.overrideStep = 1; const appLettersCount = target.name.replace(/[^A-Z]/g, '').length; this.overrideCalcData = { appName: target.name, appLettersDefault: appLettersCount, runningTotal: 0, userInitialVal: 0, appLettersVal: 0, menuStepsVal: 0, friendInitialVal: 0, finalMatrixIndex: 1, lockedSlots: [], unlockedWord: null }; const modal = document.getElementById('override-modal'); document.getElementById('override-title').innerHTML = `TERMINALE OVERRIDE: ${target.name}`; const iconDisplay = document.getElementById('ov-target-icon-display'); if (iconDisplay) iconDisplay.innerHTML = target.icon; document.getElementById('ov-default-label').innerText = `TARGET: ${target.trigger} (${target.action})`; document.getElementById('ov-clue-box').style.display = 'none'; this.buildQuantumSecCoreUI(); this.startQuantumSecCoreTicker(); this.runOverrideStepPrompt(); modal.style.display = 'flex'; }, buildQuantumSecCoreUI: function() { const verifyContainer = document.getElementById('ov-verify-container'); verifyContainer.style.display = 'flex'; verifyContainer.style.flexDirection = 'column'; verifyContainer.style.gap = '10px'; verifyContainer.innerHTML = `
[QUANTUM_DECODER // SEC_CORE: INITIALIZING...]
`; const inputEl = document.getElementById('secret-code-input'); if (inputEl) { inputEl.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this.verifyOverrideCode(); } }); } }, startQuantumSecCoreTicker: function() { const tickerEl = document.getElementById('matrix-ticker-display'); if (!tickerEl) return; if (this.tickerInterval) clearInterval(this.tickerInterval); const chars = "0123456789ABCDEFGHILMNOPQRSTUVZ#@&%"; const totalSlots = 9; // 8 passaggi algebrici + 1 slot finale parola chiave const randChunk = (len) => { let s = ""; for (let i = 0; i { const locked = this.overrideCalcData.lockedSlots || []; const unlockedWord = this.overrideCalcData.unlockedWord; let segments = []; for (let idx = 0; idx ${locked[idx]}`); } else if (idx === totalSlots - 1 && unlockedWord) { segments.push(`${unlockedWord}`); } else if (idx === totalSlots - 1) { segments.push(`[${randChunk(4)}]`); } else { segments.push(`${randChunk(4)}`); } } tickerEl.innerHTML = `SEC_CORE // ${segments.join(' - ')}`; }, 75); }, lockNextSecCoreSlot: function(partialValue) { this.overrideCalcData.lockedSlots.push(partialValue); const tickerEl = document.getElementById('matrix-ticker-display'); if (tickerEl) { tickerEl.style.borderColor = "var(--lime-green)"; setTimeout(() => { tickerEl.style.borderColor = "var(--cyan-electric)"; }, 300); } }, runOverrideStepPrompt: function() { const pathText = document.getElementById('ov-path-text'); const inputField = document.getElementById('secret-code-input'); if (inputField) { inputField.value = ''; inputField.focus(); } let promptMessage = ""; switch(this.overrideStep) { case 1: promptMessage = "PASSAGGIO 1/9:\nIn che anno siamo? (Inserisci l'anno attuale, es. 2026):"; if (inputField) inputField.placeholder = "ES. 2026"; break; case 2: promptMessage = "PASSAGGIO 2/9:\nAggiungi l'INIZIALE DEL TUO NOME (alfabeto italiano A=1 ... Z=21, scrivi la lettera o il numero):"; if (inputField) inputField.placeholder = "ES. M (OPPURE 11)"; break; case 3: promptMessage = `PASSAGGIO 3/9:\nAggiungi il numero di lettere del nome della app "${this.overrideCalcData.appName}":`; if (inputField) inputField.placeholder = "CONTA LE LETTERE..."; break; case 4: promptMessage = "PASSAGGIO 4/9:\nAggiungi il numero di passaggi effettuati nei menu per trovare l'impostazione (massimo 5):"; if (inputField) inputField.placeholder = "ES. 3 (MAX 5)"; break; case 5: promptMessage = "PASSAGGIO 5/9:\nSottrai I TUOI ANNI (inserisci la tua età):"; if (inputField) inputField.placeholder = "ES. 13"; break; case 6: promptMessage = "PASSAGGIO 6/9:\nAggiungi l'INIZIALE DEL NOME DEL TUO MIGLIORE AMICO (lettera A-Z o numero 1-21):"; if (inputField) inputField.placeholder = "ES. L (OPPURE 10)"; break; case 7: promptMessage = "PASSAGGIO 7/9:\nSottrai il tuo ANNO DI NASCITA (es. 2013):"; if (inputField) inputField.placeholder = "ES. 2013"; break; case 8: const kwChallenge = this.getAppKeywordChallenge(this.overrideCalcData.appLettersVal); this.overrideCalcData.expectedKeyword = kwChallenge.word; promptMessage = `PASSAGGIO 8/9 (ENIGMA DI CALIBRAZIONE):\n${kwChallenge.clue}`; if (inputField) inputField.placeholder = "NUMERO DI LETTERE (O LA PAROLA)..."; break; case 9: const idx = this.overrideCalcData.finalMatrixIndex; const entry = this.matrice13Domande[idx] || this.matrice13Domande[1]; this.overrideCalcData.parolaCorretta = entry.parola; promptMessage = `CALIBRAZIONE COMPLETATA! Osserva l'ultimo numero rimasto nel SEC_CORE.\n\n1) Somma le cifre che compongono quel numero (se supera 13, sommale ancora) e trova la lettera corrispondente nell'alfabeto italiano (1=A, 2=B... 10=L, 11=M, 12=N, 13=O).\n2) Rispondi all'enigma con la parola chiave che inizia per quella lettera:\n\n"${entry.domanda}"`; if (inputField) inputField.placeholder = "INSERISCI LA PAROLA CHIAVE..."; const btn = document.getElementById('btn-verify-override'); if (btn) btn.innerText = "[ 🔓 SBLOCCA SEC_CORE ]"; break; } pathText.innerHTML = ""; let i = 0; if(this.windowInterval) clearInterval(this.windowInterval); this.windowInterval = setInterval(() => { if (i '; else { pathText.innerHTML += char; if (i % 4 === 0) audioFX.playClick(); } i++; } else { clearInterval(this.windowInterval); } }, 12); }, verifyOverrideCode: function() { const inputField = document.getElementById('secret-code-input'); if (!inputField) return; const rawVal = inputField.value.trim().toUpperCase(); if (!rawVal) { audioFX.playError(); alert("Inserisci un valore prima di confermare!"); return; } const d = this.overrideCalcData; if (this.overrideStep === 1) { const anno = parseInt(rawVal, 10); if (isNaN(anno) || anno 2100) { audioFX.playError(); alert("Inserisci un anno valido (es. 2026)."); return; } audioFX.playClick(); d.runningTotal = anno; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 2; this.runOverrideStepPrompt(); } else if (this.overrideStep === 2) { const valNome = this.parseItalianLetterOrNumber(rawVal); if (!valNome) { audioFX.playError(); alert("Inserisci una lettera (A-Z) oppure un numero da 1 a 21."); return; } audioFX.playClick(); d.userInitialVal = valNome; d.runningTotal += valNome; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 3; this.runOverrideStepPrompt(); } else if (this.overrideStep === 3) { const lettereApp = parseInt(rawVal, 10); if (isNaN(lettereApp) || lettereApp 30) { audioFX.playError(); alert("Inserisci il numero di lettere del nome della app."); return; } if (lettereApp !== d.appLettersDefault) { audioFX.playError(); alert(`Conta bene le lettere di "${d.appName}" (escludendo eventuali spazi)!`); return; } audioFX.playClick(); d.appLettersVal = lettereApp; d.runningTotal += lettereApp; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 4; this.runOverrideStepPrompt(); } else if (this.overrideStep === 4) { const passaggi = parseInt(rawVal, 10); if (isNaN(passaggi) || passaggi 5) { audioFX.playError(); if (typeof this.showCyberPopup === 'function') { this.showCyberPopup( "⚠️ ROTTA NON OTTIMALE RILEVATA!\n\nPer completare l'override servono al massimo 5 passaggi nei menu. Ripercorri la strada più diretta nelle impostazioni dell'app e inserisci un numero uguale o inferiore a 5.", null ); } else { alert("⚠️ Rotta non ottimale! Servono al massimo 5 passaggi nei menu. Riprova con 99) { audioFX.playError(); alert("Inserisci la tua età in anni (es. 13)."); return; } audioFX.playClick(); d.runningTotal -= eta; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 6; this.runOverrideStepPrompt(); } else if (this.overrideStep === 6) { const valAmico = this.parseItalianLetterOrNumber(rawVal); if (!valAmico) { audioFX.playError(); alert("Inserisci la lettera iniziale del tuo migliore amico (A-Z) o un numero 1-21."); return; } audioFX.playClick(); d.friendInitialVal = valAmico; d.runningTotal += valAmico; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 7; this.runOverrideStepPrompt(); } else if (this.overrideStep === 7) { const annoNascita = parseInt(rawVal, 10); if (isNaN(annoNascita) || annoNascita 2022) { audioFX.playError(); alert("Inserisci un anno di nascita valido (es. 2013)."); return; } audioFX.playClick(); d.runningTotal -= annoNascita; this.lockNextSecCoreSlot(d.runningTotal); this.overrideStep = 8; this.runOverrideStepPrompt(); } else if (this.overrideStep === 8) { const expectedWord = d.expectedKeyword || "SERVER"; const expectedLen = expectedWord.length; // Accetta sia il numero esatto di lettere sia la parola stessa convertita nella sua lunghezza let subVal = null; if (rawVal === expectedWord) { subVal = expectedLen; } else { const parsedNum = parseInt(rawVal, 10); if (!isNaN(parsedNum) && parsedNum === expectedLen) { subVal = parsedNum; } } if (subVal === null) { audioFX.playError(); alert(`❌ Valore non corretto! Indovina la parola chiave dall'indizio (inizia per '${expectedWord.charAt(0)}') e inserisci il numero delle sue lettere.`); return; } audioFX.playClick(); d.runningTotal -= subVal; // Evitiamo eventuali residui negativi in casi limite assicurando almeno 1 const finalNum = Math.max(1, d.runningTotal); d.runningTotal = finalNum; this.lockNextSecCoreSlot(finalNum); // Riduzione reale delle cifre del numero finale rimasto fino a rientrare in 1..13 let ridotto = finalNum; while (ridotto > 13) { ridotto = String(ridotto) .split('') .reduce((acc, digit) => acc + parseInt(digit, 10), 0); } d.finalMatrixIndex = ridotto; this.overrideStep = 9; this.runOverrideStepPrompt(); } else if (this.overrideStep === 9) { const parolaAttesa = d.parolaCorretta || "FERMA"; if (rawVal === parolaAttesa) { d.unlockedWord = parolaAttesa; audioFX.playSuccess(); const tickerEl = document.getElementById('matrix-ticker-display'); if (tickerEl) { tickerEl.style.borderColor = "var(--lime-green)"; tickerEl.style.boxShadow = "0 0 18px var(--lime-green)"; } setTimeout(() => { if (this.tickerInterval) clearInterval(this.tickerInterval); this.dossierArchive.push({ type: 'software_hack', target: this.currentOverrideTarget.name, status: `OVERRIDE SEC_CORE (${parolaAttesa})`, imgRaw: 'https://www.energiadi.it/wp-content/uploads/2026/10/Risorsa-1.png' }); document.getElementById('override-modal').style.display = 'none'; this.completeHack(this.currentOverrideTarget, 'override'); }, 1600); } else { audioFX.playError(); alert("❌ Accesso negato dal SEC_CORE! Controlla la somma delle cifre dell'ultimo numero rimasto, verifica la lettera corrispondente nell'alfabeto italiano e riprova."); } } }, completeHack: function(target, actionType) { audioFX.playSuccess(); this.tatticheCompletate++; this.updateXpHud(target.xp); document.getElementById('override-modal').style.display = 'none'; const cardEl = document.getElementById('mini-' + target.id); const statusEl = document.getElementById('status-' + target.id); if(cardEl) cardEl.classList.add('completed'); if(statusEl) statusEl.innerText = 'HACKED'; if ((this.tatticheCompletate + this.ninjaCompletate) >= 1) { document.getElementById('btn-go-to-debriefing').style.display = 'block'; } }, generateDebriefing: function() { const totalHacks = this.tatticheCompletate + this.ninjaCompletate; let pName = "AGENTE OPERATIVO", pDesc = "Hai iniziato il tuo percorso per sconfiggere il Default.", pColor = "#00f0ff"; if (totalHacks >= 9 && this.ninjaCompletate >= 6) { pName = "CYBER GHOST 👻"; pDesc = "Vivi fuori dal Default e la tua impronta di spreco è nulla."; pColor = "#39ff14"; } else if (totalHacks >= 8) { pName = "NET-ECOLOGY MASTER 🏆"; pDesc = "Hai dominato ogni vulnerabilità. Sei un vero leader della decarbonizzazione."; pColor = "#ffd700"; } else if (this.ninjaCompletate >= 4) { pName = "NATIVE NINJA 🥷"; pDesc = "Molte app erano già a prova di spreco. Hai un'ottima immunità."; pColor = "#39ff14"; } else if (this.cloudActiveGB > 400 && totalHacks >= 4) { pName = "CLOUD OPTIMIZER ☁️"; pDesc = "Hai alleggerito drasticamente il carico sulle antenne e sui server."; pColor = "#ff00ff"; } else if (this.localWasteKwh > 20 && totalHacks >= 2) { pName = "VAMPIRE SLAYER 🧛♂️"; pDesc = "Hai scovato un forte spreco elettrico silente."; pColor = "#fff"; } else if (totalHacks >= 4) { pName = "CYBER RANGER 🛡️"; pDesc = "Hai difeso la tua rete con astuzia e metodo."; pColor = "#00f0ff"; } else { pName = "ROOKIE HACKER 🛠️"; pDesc = "Hai fatto il tuo primo passo fuori dalla matrice del Default."; pColor = "#00f0ff"; } this.player.profileName = pName; document.getElementById('ap-avatar-icon').innerText = this.player.avatar; document.getElementById('ap-title').innerText = pName; document.getElementById('ap-title').style.color = pColor; document.getElementById('ap-desc').innerText = pDesc; document.getElementById('agent-profile-box').style.borderColor = pColor; document.getElementById('agent-profile-box').style.boxShadow = `0 0 15px ${pColor}80`; const gbSaved = totalHacks * 250; const co2Saved = Math.round(gbSaved * 0.042); const euroRisparmiati = Math.round(this.localWasteKwh * 0.30); const ricariche = totalHacks >= 3 ? '1.5' : '1'; document.getElementById('loot-euro').innerText = euroRisparmiati; document.getElementById('loot-gb').innerText = gbSaved; document.getElementById('loot-co2').innerText = co2Saved; document.getElementById('loot-batt').innerText = ricariche; const initialCO2 = Math.round((this.cloudActiveGB + this.cloudBackgroundGB) * 0.042); const finalCO2 = Math.max(0, initialCO2 - co2Saved); document.getElementById('deb-user-co2-val').innerText = finalCO2 + ' kg CO₂'; const maxFinalCo2 = Math.max(99, finalCO2, 10); const avgDebPct = Math.round((99 / maxFinalCo2) * 100); const userDebPct = Math.round((finalCO2 / maxFinalCo2) * 100); document.getElementById('deb-avg-bar').setAttribute('data-width', avgDebPct + '%'); document.getElementById('deb-user-bar').setAttribute('data-width', userDebPct + '%'); let msg = "> SINCRONIZZAZIONE DATI...\n> RICALCOLO IMPRONTA COMPLETATO.\n\nHAI TAGLIATO IL CORDONE CHE NUTRE LO SPRECO DEI SERVER GLOBALI E LA TUA BOLLETTA.\n\nECCO IL TUO IMPATTO REALE."; if(totalHacks >= 8) { msg += "\n\n🏆 BADGE SBLOCCATO: MASTER! (+100 XP EXTRA)"; this.updateXpHud(100); } this.showCyberPopup(msg, () => { this.showStage(5); setTimeout(() => { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.querySelectorAll('.hud-bar-fill').forEach(bar => { const w = bar.getAttribute('data-width'); if(w) bar.style.width = w; }); observer.unobserve(entry.target); } }); }, { threshold: 0.1 }); const debriefBox = document.getElementById('debrief-chart-box'); if (debriefBox) observer.observe(debriefBox); }, 150); }); }, printDossierMissione: function() { audioFX.playClick(); let printContainer = document.getElementById('print-dossier'); if (!printContainer) { printContainer = document.createElement('div'); printContainer.id = 'print-dossier'; document.body.appendChild(printContainer); } const totalHacks = this.tatticheCompletate + this.ninjaCompletate; const gbSaved = totalHacks * 250; const co2Saved = Math.round(gbSaved * 0.042); const euroRisparmiati = Math.round(this.localWasteKwh * 0.30); const pattoPrintText = this.isPattoSigned ? "FIRMATO CON IMPRONTA BIOMETRICA ✔️ (IMPEGNO 2 MESI)" : "NON FIRMATO"; const familyPrintText = this.isFamilyPattoSigned ? "FIRMATO E SELFIE SQUADRA SCATTATO ✔️ (+200 XP)" : "NON FIRMATO"; let html = `
⚡ wattORO Generati per le Energiadi: ${this.wattOro} wO 📜 Patto con le Energiadi: ${pattoPrintText} 🏆 Patto di Famiglia (Energy Manager): ${familyPrintText} 🏫 Assegnato a Squadra: ${this.player.missionCode}
1. ANALISI DEI CONSUMI (L'ICEBERG)
🔌 HARDWARE LOCALE
Energia Utile: ${Math.round(this.localUsefulKwh)} kWh/a Vampire Drain: ${Math.round(this.localWasteKwh)} kWh/a