DistractIQ / static /script.js
Muskan10sharma's picture
Update static/script.js
4c0c549 verified
Raw
History Blame Contribute Delete
33.6 kB
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
DistractIQ ยท script.js
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
// โ”€โ”€ Interactive Assets โ”€โ”€
const sounds = {
pop: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-modern-technology-select-3124.mp3'),
scan: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-futuristic-robotic-data-601.mp3'),
levelUp: new Audio('https://assets.mixkit.co/sfx/preview/mixkit-arcade-retro-changing-tab-206.mp3')
};
Object.values(sounds).forEach(s => s.volume = 0.2);
const trapRoasts = [
"Isliye tumhare exams clear nahi hote, distraction ki magnet ho tum! ๐Ÿงฒ",
"Focus focus focus... oh look, a useless button! - You, probably. ๐Ÿคก",
"Self-control: 0. Button clicking skills: 100. Proud of you. ๐Ÿ™„",
"Beta, career par dhyan de lo, is button par nahi. ๐Ÿงฌ",
"Physics wallah se pehle distraction wallah banoge tum. ๐Ÿ“‰"
];
/* โ”€โ”€ State โ”€โ”€ */
const S = {
name: '', quizDone: false, quizAnswers: [],
results: null, history: [], streak: 0,
xp: 0, darkMode: true,
inputs: { study:4, phone:3, social:2, sleep:7, notifications:50 }
};
/* โ”€โ”€ Persistence โ”€โ”€ */
function save(){ try{ localStorage.setItem('diq', JSON.stringify(S)); }catch(e){} }
function load(){
try{
const d = JSON.parse(localStorage.getItem('diq')||'null');
if(d){ Object.assign(S, d); }
}catch(e){}
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
GALAXY CANVAS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
(function initGalaxy(){
const cv = document.getElementById('galaxy');
const ctx = cv.getContext('2d');
let W, H, stars=[], nebulas=[];
function resize(){ W=cv.width=innerWidth; H=cv.height=innerHeight; }
function mkStars(){
stars = Array.from({length:220},()=>({
x:Math.random()*W, y:Math.random()*H,
r:Math.random()*1.6+.3,
a:Math.random(), da:(Math.random()-.5)*.008,
s:Math.random()*.4+.1
}));
nebulas = Array.from({length:5},()=>({
x:Math.random()*W, y:Math.random()*H,
r:Math.random()*180+80,
h:Math.random()*360, a:Math.random()*.18+.04
}));
}
function draw(){
ctx.clearRect(0,0,W,H);
nebulas.forEach(n=>{
const g=ctx.createRadialGradient(n.x,n.y,0,n.x,n.y,n.r);
g.addColorStop(0,`hsla(${n.h},80%,55%,${n.a})`);
g.addColorStop(1,'transparent');
ctx.fillStyle=g; ctx.fillRect(0,0,W,H);
});
stars.forEach(st=>{
st.a+=st.da;
if(st.a<0||st.a>1) st.da*=-1;
st.x-=st.s*.15;
if(st.x<0) st.x=W;
ctx.beginPath();
ctx.arc(st.x,st.y,st.r,0,Math.PI*2);
ctx.fillStyle=`rgba(255,255,255,${st.a})`;
ctx.fill();
});
requestAnimationFrame(draw);
}
window.addEventListener('resize',()=>{ resize(); mkStars(); });
resize(); mkStars(); draw();
})();
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
SCREEN SWITCHER
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function showScreen(id){
document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));
const el = document.getElementById(id);
el.classList.add('active');
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
LOGIN
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function doLogin(){
const n = document.getElementById('name-in').value.trim();
if(!n){ showToast('Please enter your name! ๐Ÿ‘€'); return; }
S.name = n;
if(!S.quizDone){ showScreen('s-quiz'); initQuiz(); }
else{ showScreen('s-input'); initInputs(); }
save();
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
PERSONALITY QUIZ
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
const QUIZ = [
{ q:'When do you feel most productive?', e:'๐Ÿ•',
opts:['Early morning (5โ€“9 AM)','Late morning (9โ€“12)','Afternoon vibes','Night owl mode ๐Ÿฆ‰'] },
{ q:'How often do you check your phone while studying?', e:'๐Ÿ“ฑ',
opts:['Every 5 mins (bad, I know)','Every 30 mins','Only on breaks','I forget phones exist'] },
{ q:'What kills your focus the most?', e:'๐Ÿ’€',
opts:['Social media notifications','Background noise','Random thoughts','Hunger / boredom'] },
{ q:'How many hours of deep work can you do daily?', e:'๐Ÿ”ฅ',
opts:['Less than 1 hour','1โ€“2 hours','3โ€“4 hours','5+ hours (beast mode)'] }
];
let qIdx=0;
function initQuiz(){
qIdx=0; S.quizAnswers=[];
renderQ();
}
function renderQ(){
const q=QUIZ[qIdx];
document.getElementById('qemoji').textContent=q.e;
document.getElementById('qtext').textContent=q.q;
document.getElementById('qlabel').textContent=`Question ${qIdx+1} of ${QUIZ.length}`;
document.getElementById('qprog').style.width=`${((qIdx)/QUIZ.length)*100}%`;
const oc=document.getElementById('qopts');
oc.innerHTML='';
q.opts.forEach((o,i)=>{
const b=document.createElement('button');
b.className='qopt'; b.textContent=o;
b.onclick=()=>pickQ(i, b);
oc.appendChild(b);
});
// Animate card in
const card=document.getElementById('qcard');
card.style.animation='none';
card.offsetHeight;
card.style.animation='popIn .4s cubic-bezier(.34,1.56,.64,1)';
}
function pickQ(i, btn){
document.querySelectorAll('.qopt').forEach(b=>b.classList.remove('sel'));
btn.classList.add('sel');
S.quizAnswers.push(i);
setTimeout(()=>{
qIdx++;
if(qIdx<QUIZ.length){ renderQ(); }
else{
S.quizDone=true; save();
showScreen('s-input'); initInputs();
}
},420);
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
INPUT SLIDERS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
const INPUTS_CFG = [
{ key:'study', icon:'๐Ÿ“š', title:'Study Hours Today', desc:'How many hours did you actually study?', min:0, max:16, step:.5, unit:'hrs', def:4 },
{ key:'phone', icon:'๐Ÿ“ฑ', title:'Phone Usage', desc:'Total time on phone today (hours)', min:0, max:16, step:.5, unit:'hrs', def:3 },
{ key:'social', icon:'๐ŸŒ', title:'Social Media Time', desc:'Time spent on Instagram, YouTube, etc.', min:0, max:16, step:.5, unit:'hrs', def:2 },
{ key:'sleep', icon:'๐Ÿ˜ด', title:'Sleep Last Night', desc:'How many hours did you sleep?', min:0, max:12, step:.5, unit:'hrs', def:7 },
{ key:'notifications', icon:'๐Ÿ””', title:'Notifications Today', desc:'How many notifications did you receive?', min:0, max:300, step:5, unit:'notifs',def:50 }
];
let inpIdx=0;
function initInputs(){
inpIdx=0;
renderInp();
renderDots();
}
function renderInp(){
const c=INPUTS_CFG[inpIdx];
document.getElementById('inp-icon').textContent=c.icon;
document.getElementById('inp-title').textContent=c.title;
document.getElementById('inp-desc').textContent=c.desc;
const sl=document.getElementById('inp-slider');
sl.min=c.min; sl.max=c.max; sl.step=c.step;
sl.value=S.inputs[c.key]!==undefined ? S.inputs[c.key] : c.def;
document.getElementById('slid-unit').textContent=c.unit;
onSlide(sl.value);
// re-trigger animation
const card=document.getElementById('inp-card');
card.style.animation='none'; card.offsetHeight;
card.style.animation='popIn .4s cubic-bezier(.34,1.56,.64,1)';
}
function onSlide(v){
document.getElementById('slid-val').textContent=v;
}
function nextInp(){
const val=parseFloat(document.getElementById('inp-slider').value);
S.inputs[INPUTS_CFG[inpIdx].key]=val;
// Animate card out
const card=document.getElementById('inp-card');
card.style.transform='scale(.9) translateY(-30px)';
card.style.opacity='0';
setTimeout(()=>{
card.style.transform=''; card.style.opacity='';
inpIdx++;
if(inpIdx<INPUTS_CFG.length){ renderInp(); renderDots(); }
else{ save(); callAPI(); }
},350);
}
function renderDots(){
const dc=document.getElementById('inp-dots');
dc.innerHTML='';
INPUTS_CFG.forEach((_,i)=>{
const d=document.createElement('div');
d.className='dot'+(i===inpIdx?' active':i<inpIdx?' done':'');
dc.appendChild(d);
});
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
API CALL
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function callAPI() {
// ๐Ÿ”Š Scanning sound start
sounds.scan.loop = true;
sounds.scan.play();
showToast('๐Ÿง  Analyzing your focus patternsโ€ฆ');
const body = {
study_hours_per_day: S.inputs.study,
phone_usage_hours: S.inputs.phone,
social_media_hours: S.inputs.social,
sleep_hours: S.inputs.sleep,
notifications: S.inputs.notifications
};
fetch('/predict', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
.then(r => r.json())
.then(d => {
// ๐Ÿ”‡ Scanning sound stop
sounds.scan.pause();
sounds.scan.currentTime = 0;
if (d.error) { showToast('โš ๏ธ ' + d.error); return; }
S.results = d;
processResults(d);
showScreen('s-dash');
showTab('home');
updateStreak();
save();
// ๐Ÿ† Level Up sound if good performance
if (d.productivity > 80) {
sounds.levelUp.play();
}
setTimeout(() => scheduleNotif(d.score), 4000);
})
.catch(e => {
// ๐Ÿ”‡ Error aane par bhi sound stop karein
sounds.scan.pause();
showToast('Connection error. Please try again.');
console.error(e);
});
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
PROCESS & RENDER RESULTS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function processResults(d){
const {score, risk, productivity, is_focused} = d;
// XP
const gainedXP = Math.round(productivity * 5);
S.xp = (S.xp||0) + gainedXP;
saveHistory(d);
// Greeting
const hour=new Date().getHours();
const greet=hour<12?'Good Morning โ˜€๏ธ':hour<17?'Good Afternoon ๐ŸŒค':hour<20?'Good Evening ๐ŸŒ†':'Good Night ๐ŸŒ™';
document.getElementById('greeting').textContent=`${greet}, ${S.name}! ๐Ÿ‘‹`;
// Sarcasm
document.getElementById('sarcasm').textContent=getSarcasm(score, hour);
document.getElementById('sarcasm').style.borderColor=score>75?'rgba(239,68,68,.4)':score>45?'rgba(245,158,11,.4)':'rgba(16,185,129,.4)';
// Animate rings
animRing('rg-dist', score, score>75?'#ef4444':score>45?'#f59e0b':'#10b981');
animRing('rg-risk', risk, risk>75?'#ef4444':risk>45?'#f59e0b':'#10b981');
animRing('rg-prod', productivity, productivity<40?'#ef4444':productivity<70?'#f59e0b':'#10b981');
animNum('n-dist', score);
animNum('n-risk', risk);
animNum('n-prod', productivity);
// Persona
const persona=getPersona(score, productivity, d.inputs||S.inputs);
document.getElementById('p-icon').textContent=persona.icon;
document.getElementById('p-name').textContent=persona.name;
document.getElementById('p-desc').textContent=persona.desc;
// Level & XP
const lv=getLevel(S.xp);
document.getElementById('lvl-name').textContent=lv.name;
document.getElementById('lvl-fill').style.width=lv.pct+'%';
document.getElementById('xp-ct').textContent=S.xp;
document.getElementById('xp-ct2').textContent=S.xp;
document.getElementById('xp-max').textContent=lv.max;
// Drivers
renderDrivers(d.inputs||S.inputs, score);
// Optimizer
renderOptimizer(d.inputs||S.inputs, score, productivity);
// Quote
document.getElementById('quote-txt').textContent=getQuote();
// Profile
document.getElementById('prof-name').textContent=S.name;
document.getElementById('prof-persona').textContent=persona.name;
// Stats
renderStats(score, productivity, risk);
// Streak
document.getElementById('streak-ct').textContent=S.streak;
document.getElementById('s-big').textContent=S.streak;
// History & breakdown
renderHistory();
renderBreakdown(d.inputs||S.inputs, score);
// Streaks calendar
renderCal();
// Achievements
renderAch();
}
/* โ”€โ”€ Ring animation โ”€โ”€ */
function animRing(id, val, color){
const el=document.getElementById(id);
el.style.stroke=color;
const offset=264-(264*(val/100));
requestAnimationFrame(()=>{ el.style.strokeDashoffset=offset; });
}
function animNum(id, target){
const el=document.getElementById(id);
let cur=0; const dur=1200; const start=performance.now();
function step(now){
const p=Math.min((now-start)/dur,1);
el.textContent=Math.round(cur+(target-cur)*easeOut(p));
if(p<1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
function easeOut(t){ return 1-Math.pow(1-t,3); }
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
CONTENT GENERATORS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function getSarcasm(score, hour){
if(hour>=23||hour<5){
const lateArr=['Sleep is optional, regret is guaranteed. ๐Ÿ˜ญ','Why are you awake? Your productivity isn\'t. ๐ŸŒ™','Your brain needs rest, not a late-night doom scroll.','2 AM productivity? Bold strategy. Let us know how it goes.'];
return rnd(lateArr);
}
if(score>75){
return rnd(['Focus gaya tel lene ๐Ÿ˜ญ','Productivity just left the chat.','Phone se rishta thoda kam karo. ๐Ÿ“ฑ','Your phone has more screen time than your textbook.','Distraction level: Olympic gold medalist.','Your attention span just filed for bankruptcy.']);
}
if(score>45){
return rnd(['You\'re almost productive. Almost. ๐Ÿค','Some focus detectedโ€ฆ very little.','Mediocre effort detected. Could be worse. Could be better.','The Wi-Fi is testing you and you\'re losing.','Half-focus is like half a parachute. ๐Ÿช‚']);
}
return rnd(['This is suspiciously impressive. ๐Ÿ‘€','Look at you getting things done! ๐Ÿš€','Productivity unlocked. Who are you?','Your focus game is on another level today.','Deep work mode: ACTIVATED. We stan. ๐Ÿ”ฅ']);
}
function getPersona(score, prod, inp){
const ph=inp.phone||S.inputs.phone;
const notif=inp.notifications||S.inputs.notifications;
if(prod>78) return {icon:'๐Ÿฅท',name:'Deep Work Ninja',desc:'You enter flow states effortlessly. Elite.'};
if(ph>7) return {icon:'๐Ÿ“ฑ',name:'Digital Drifter',desc:'Glued to the screen like it owes you money.'};
if(notif>140)return {icon:'โšก',name:'Chronic Multitasker',desc:'You juggle 10 things and finish 2. Progress.'};
return {icon:'โš–๏ธ',name:'Balanced Performer',desc:'Solid effort. A few tweaks and you\'re elite.'};
}
function getLevel(xp){
if(xp<500) return {name:'Beginner', pct:Math.round((xp/500)*100), max:500};
if(xp<2000) return {name:'Builder', pct:Math.round(((xp-500)/1500)*100), max:2000};
return {name:'Master', pct:Math.round(Math.min(((xp-2000)/3000)*100,100)), max:5000};
}
function renderDrivers(inp, score){
const cont=document.getElementById('drivers');
const drivers=[];
const ph=inp.phone||S.inputs.phone;
const sm=inp.social||S.inputs.social;
const sl=inp.sleep||S.inputs.sleep;
const nt=inp.notifications||S.inputs.notifications;
const st=inp.study||S.inputs.study;
if(ph>5) drivers.push({icon:'๐Ÿ“ฑ',label:'High Phone Usage', pct:Math.min(100,Math.round(ph/16*100)), color:'#ef4444'});
if(sm>3) drivers.push({icon:'๐Ÿ“ธ',label:'Social Media', pct:Math.min(100,Math.round(sm/16*100)), color:'#ec4899'});
if(sl<6) drivers.push({icon:'๐Ÿ˜ด',label:'Sleep Deficit', pct:Math.min(100,Math.round((6-sl)/6*100)), color:'#f59e0b'});
if(nt>80) drivers.push({icon:'๐Ÿ””',label:'Notification Storm',pct:Math.min(100,Math.round(nt/200*100)), color:'#8b5cf6'});
if(st<3) drivers.push({icon:'๐Ÿ“š',label:'Low Study Time', pct:Math.min(100,Math.round((3-st)/3*100)), color:'#06b6d4'});
if(!drivers.length) drivers.push({icon:'โœ…',label:'No major distractions!',pct:5,color:'#10b981'});
cont.innerHTML=drivers.map(d=>`
<div class="drv">
<div class="drv-lft">${d.icon} ${d.label}</div>
<div class="drv-bw"><div class="drv-bf" style="width:0%;background:${d.color}" data-w="${d.pct}"></div></div>
<div class="drv-pct">${d.pct}%</div>
</div>`).join('');
// Animate bars
setTimeout(()=>{
cont.querySelectorAll('.drv-bf').forEach(b=>{ b.style.width=b.dataset.w+'%'; });
},200);
}
function renderOptimizer(inp, score, prod){
const cont=document.getElementById('optimizer');
const tips=[];
const sm=inp.social||S.inputs.social;
const ph=inp.phone||S.inputs.phone;
const sl=inp.sleep||S.inputs.sleep;
const nt=inp.notifications||S.inputs.notifications;
const st=inp.study||S.inputs.study;
if(sm>1) tips.push(`๐Ÿ“‰ Cut social media by 1hr โ†’ +${Math.round(sm*4)}% productivity boost`);
if(ph>3) tips.push(`๐Ÿ“ต Phone-free study blocks โ†’ reduces distraction score by ~${Math.round(ph*3)} pts`);
if(sl<7) tips.push(`๐Ÿ›Œ Sleep 1hr more โ†’ clears mental fog, +${Math.round((7-sl)*8)}% focus`);
if(nt>50)tips.push(`๐Ÿ”• Silence notifications during study โ†’ recover ${Math.round(nt*.5)} min of deep work`);
if(st<5) tips.push(`๐Ÿ“– Add 1hr of study โ†’ +${Math.round(1*2*5)} productivity XP gained`);
if(!tips.length) tips.push('๐Ÿ† You\'re optimized! Keep this up for streak bonuses.');
cont.innerHTML=tips.map(t=>`<div class="tip"><span class="tip-ic">๐Ÿ’ก</span><span>${t}</span></div>`).join('');
}
const QUOTES=[
'"Deep work is the superpower of the 21st century." โ€” Cal Newport',
'"Focus is a matter of deciding what things you\'re NOT going to do." โ€” John Carmack',
'"Energy, not time, is the fundamental currency of high performance."',
'"The successful warrior is the average person with laser-like focus." โ€” Bruce Lee',
'"Concentrate all your thoughts upon the work at hand." โ€” Alexander Graham Bell',
'"Where focus goes, energy flows." โ€” Tony Robbins',
'"Do one thing at a time, and do it well."',
'"Your future is created by what you do today, not tomorrow."'
];
function getQuote(){ return rnd(QUOTES); }
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
HISTORY
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function saveHistory(d){
const entry={
date: new Date().toLocaleDateString('en-IN',{day:'numeric',month:'short'}),
score: d.score, risk: d.risk, productivity: d.productivity,
persona: getPersona(d.score, d.productivity, d.inputs||S.inputs).name
};
S.history = [entry, ...(S.history||[])].slice(0,30);
}
function renderHistory(){
const cont=document.getElementById('hist-list');
if(!S.history||!S.history.length){
cont.innerHTML='<div class="muted" style="font-size:.85rem;padding:8px 0">No history yet. Run your first analysis!</div>';
return;
}
cont.innerHTML=S.history.slice(0,10).map(h=>{
const cls=h.score>75?'hi':h.score>45?'md':'lo';
return `<div class="hitem">
<div class="hdot ${cls}"></div>
<div class="hinfo">
<div class="hdate">${h.date}</div>
<div class="hscore">Score: ${h.score} ยท Risk: ${h.risk}%</div>
<div class="hpers">${h.persona}</div>
</div>
<div style="font-family:var(--fd);font-size:.9rem;color:${h.productivity>70?'#10b981':h.productivity>45?'#f59e0b':'#ef4444'}">${h.productivity}%</div>
</div>`;
}).join('');
}
function renderBreakdown(inp, score){
const cont=document.getElementById('breakdown');
const ph=inp.phone||S.inputs.phone;
const sm=inp.social||S.inputs.social;
const nt=inp.notifications||S.inputs.notifications;
const st=inp.study||S.inputs.study;
const sl=inp.sleep||S.inputs.sleep;
const bars=[
{label:'Phone', val:Math.min(100,Math.round(ph/16*100)), color:'#ef4444'},
{label:'Social', val:Math.min(100,Math.round(sm/16*100)), color:'#ec4899'},
{label:'Notifs', val:Math.min(100,Math.round(nt/200*100)), color:'#8b5cf6'},
{label:'Study', val:Math.min(100,Math.round(st/16*100)), color:'#10b981'},
{label:'Sleep', val:Math.min(100,Math.round(sl/12*100)), color:'#3b82f6'}
];
cont.innerHTML=bars.map(b=>`
<div class="bki">
<div class="bkh"><span>${b.label}</span><span>${b.val}%</span></div>
<div class="bkbg"><div class="bkf" style="width:0%;background:${b.color};color:${b.color}" data-w="${b.val}"></div></div>
</div>`).join('');
setTimeout(()=>{
cont.querySelectorAll('.bkf').forEach(b=>{ b.style.width=b.dataset.w+'%'; });
},200);
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
STREAKS & CALENDAR
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function updateStreak(){
const today=new Date().toDateString();
const last=S.lastDay||'';
if(last===today) return;
const yesterday=new Date(Date.now()-86400000).toDateString();
if(last===yesterday){ S.streak=(S.streak||0)+1; }
else{ S.streak=1; }
S.lastDay=today;
S.streakDays=S.streakDays||[];
S.streakDays.push(today);
save();
}
function renderCal(){
const cont=document.getElementById('s-cal');
const today=new Date();
const year=today.getFullYear();
const month=today.getMonth();
const daysInMonth=new Date(year,month+1,0).getDate();
const firstDay=new Date(year,month,1).getDay();
const done=new Set(S.streakDays||[]);
let html='';
for(let i=0;i<firstDay;i++) html+=`<div class="cday"></div>`;
for(let d=1;d<=daysInMonth;d++){
const dt=new Date(year,month,d).toDateString();
const isToday=d===today.getDate();
const isDone=done.has(dt);
html+=`<div class="cday${isDone?' done':''}${isToday?' today':''}">${d}</div>`;
}
cont.innerHTML=html;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
ACHIEVEMENTS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
const ACHS=[
{icon:'๐Ÿš€',name:'First Launch', desc:'Completed first analysis', check:()=>S.history&&S.history.length>=1},
{icon:'๐Ÿ”ฅ',name:'3-Day Streak', desc:'3 days in a row', check:()=>(S.streak||0)>=3},
{icon:'๐Ÿ’Ž',name:'Focus Diamond', desc:'Productivity > 80%', check:()=>S.results&&S.results.productivity>80},
{icon:'๐Ÿง˜',name:'Zen Mode', desc:'Distraction score < 20', check:()=>S.results&&S.results.score<20},
{icon:'โšก',name:'500 XP Club', desc:'Earned 500 XP', check:()=>(S.xp||0)>=500},
{icon:'๐Ÿ†',name:'Week Warrior', desc:'7-day streak', check:()=>(S.streak||0)>=7},
];
function renderAch(){
document.getElementById('ach-list').innerHTML=ACHS.map(a=>{
const on=a.check();
return `<div class="ach ${on?'on':'off'}">
<div class="ach-ic">${a.icon}</div>
<div><div class="ach-nm">${a.name} ${on?'โœ…':''}</div><div class="ach-ds">${a.desc}</div></div>
</div>`;
}).join('');
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
STATS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function renderStats(score, prod, risk){
document.getElementById('prof-stats').innerHTML=`
<div class="st-row"><span>Total Analyses</span><span class="st-v">${S.history?S.history.length:1}</span></div>
<div class="st-row"><span>Current Score</span><span class="st-v">${score}</span></div>
<div class="st-row"><span>Productivity</span><span class="st-v">${prod}%</span></div>
<div class="st-row"><span>Risk Level</span><span class="st-v">${risk}%</span></div>
<div class="st-row"><span>Total XP</span><span class="st-v">${S.xp||0}</span></div>
<div class="st-row"><span>Best Streak</span><span class="st-v">${S.streak||0} days</span></div>
`;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
TABS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function showTab(name){
document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
document.querySelectorAll('.nb').forEach(b=>b.classList.remove('active'));
document.getElementById('tab-'+name).classList.add('active');
document.getElementById('nb-'+name).classList.add('active');
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
TOAST
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function showToast(msg, dur=3200){
const t = document.getElementById('toast');
if(!t) return;
// Play sound
sounds.pop.currentTime = 0;
sounds.pop.play();
t.textContent = msg;
t.classList.add('show');
setTimeout(() => t.classList.remove('show'), dur);
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
SARCASTIC NOTIFICATIONS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
const NOTIFS=[
'Hey, your phone misses you. Actually no, it doesn\'t. ๐Ÿ“ต',
'Your study notes won\'t read themselves. Or will they? ๐Ÿค”',
'Notification from: Reality. You have work to do.',
'Focus check: still alive? Put the phone down.',
'Your productivity just texted. It\'s lonely.',
'Average Indian student scrolls 3hrs/day. Don\'t be average.',
'Your future self is watching. Don\'t disappoint them. ๐Ÿ‘',
];
function scheduleNotif(score){
if(!document.getElementById('notif-tog').checked) return;
if(score>50) showToast('๐Ÿ”” '+rnd(NOTIFS));
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
THEME
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function toggleTheme(){
S.darkMode=!S.darkMode;
document.body.classList.toggle('light',!S.darkMode);
document.getElementById('theme-toggle' ) && (document.querySelector('.ico-btn').textContent=S.darkMode?'๐ŸŒ™':'โ˜€๏ธ');
const tog=document.getElementById('dark-tog');
if(tog) tog.checked=S.darkMode;
save();
}
function toggleThemeCheck(el){
S.darkMode=el.checked;
document.body.classList.toggle('light',!S.darkMode);
save();
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
RESET
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function rerun(){
inpIdx=0; S.inputs={study:4,phone:3,social:2,sleep:7,notifications:50};
showScreen('s-input'); initInputs();
}
function clearAll(){
if(!confirm('Reset all data? This cannot be undone.')) return;
localStorage.removeItem('diq');
location.reload();
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
UTILS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function rnd(arr){ return arr[Math.floor(Math.random()*arr.length)]; }
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
INIT
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
window.addEventListener('DOMContentLoaded', () => {
load();
if (S.darkMode === false) document.body.classList.add('light');
if (S.name) {
document.getElementById('name-in').value = S.name;
}
// Enter key on login
document.getElementById('name-in').addEventListener('keydown', e => {
if (e.key === 'Enter') doLogin();
});
// If returning user with results, go straight to dash
if (S.name && S.results && S.quizDone) {
document.getElementById('greeting').textContent = `Welcome back, ${S.name}! ๐Ÿ‘‹`;
showScreen('s-dash');
processResults(S.results);
showTab('home');
}
// --- TRAP BUTTON LOGIC (Sabke liye kaam karega) ---
const trapBtn = document.getElementById('trap-btn');
if (trapBtn) {
trapBtn.addEventListener('click', () => {
sounds.pop.currentTime = 0;
sounds.pop.play();
document.body.classList.add('trap-flash');
setTimeout(() => document.body.classList.remove('trap-flash'), 500);
const msg = trapRoasts[Math.floor(Math.random() * trapRoasts.length)];
showToast(msg);
});
}
});
// 1. Sarcastic Messages ka Database
const sarcasticVault = {
high: ["Focus gaya tel lene ๐Ÿ˜ญ", "Productivity just left the chat.", "เค‡เคคเคจเคพ scrolling? Dedication galat jagah pe hai.", "Phone se relationship strong haiโ€ฆ future se weak."],
medium: ["Youโ€™re almost productive. Almost.", "Half focus, half nonsense. Balanced life?", "Scrolling kam, kaam thoda zyada?", "Potential haiโ€ฆ use kab karoge?"],
low: ["Who are you and why are you so productive?", "Suspiciously impressive. Character development!", "Focus level: main character energy.", "Is thisโ€ฆ discipline? ๐Ÿ˜ณ"],
random: ["เคฌเฅเคฐเฅ‡เค• เคฒเคฟเคฏเคพ เคฅเคพ เคฏเคพ retirement?", "Motivation bufferingโ€ฆ please wait.", "เคซเฅ‹เคจ เคฐเค–เฅ‹. Future เค‰เค เคพเค“.", "เค•เคพเคฎ pending hai, attitude full hai ๐Ÿ˜ญ"]
};
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
SMART SARCASTIC NOTIFICATIONS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
SMART SARCASTIC NOTIFICATIONS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
function popSarcasticNotif() {
// Only roast if the user is logged in and the dashboard is active
const dashActive = document.getElementById('s-dash').classList.contains('active');
if (!S.name || !S.quizDone || !dashActive) return;
const toast = document.getElementById('toast');
if(!toast) return;
// Determine roast category based on the latest distraction score
let type = 'random';
if (S.results) {
const score = S.results.score;
type = score > 75 ? 'high' : score > 45 ? 'medium' : 'low';
}
const messages = sarcasticVault[type] || sarcasticVault.random;
const msg = messages[Math.floor(Math.random() * messages.length)];
// Severity-based accent colors
const colors = { high: "#ef4444", medium: "#f59e0b", low: "#10b981", random: "#8b5cf6" };
const color = colors[type] || colors.random;
// Audio cue
sounds.pop.currentTime = 0;
sounds.pop.play();
toast.innerText = "๐Ÿ”” " + msg;
toast.style.borderLeft = `6px solid ${color}`;
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 4000);
}
// Start the roast engine
// Set to 20s to balance humor without being annoying
setInterval(popSarcasticNotif, 20000);
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
DEBUG & LOGS
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
console.log("๐Ÿš€ DistractIQ Engine: Active & Ready to Roast.");