CERTIFICATE OF ACHIEVEMENT

${cfg.festName} ${cfg.year}

${cfg.institution}


This is to certify that

${w.participant.name}

representing ${w.participant.team}

has won ${ranks[w.rank-1]||w.rank+'th'} Place in

${w.item.name}

${w.item.section} Category

Total Marks: ${w.marks.total} | Grade: ${w.marks.grade}

_________________
Jury Secretary
_________________
Organising Secretary

${cfg.venue||''} ยท ${cfg.date||''}

`); win.document.close(); win.print(); } // ============================================= // PRINT FUNCTIONS // ============================================= function printHeader(cfg){ return `

${cfg.festName} ${cfg.year}

${cfg.institution}

${cfg.venue||''} ${cfg.date?'| '+cfg.date:''}

`; } function openPrint(html){ const win=window.open('','_blank'); win.document.write(`${html}`); win.document.close(); win.print(); } function printReport(type){ const cfg=DB.config(), participants=DB.participants(), items=DB.items(), marks=DB.marks(), groups=DB.groups(); let html=printHeader(cfg); if(type==='participants'){ const teams=DB.teams(); html+='

📋 Participants List

'; teams.forEach(function(team){ const tp=participants.filter(function(p){return p.team===team.name;}).sort(function(a,b){return a.chestNo-b.chestNo;}); if(!tp.length) return; html+='

'+team.name+'

'; html+='' +tp.map(function(p,i){ var pItems=(p.items||[]).map(function(id){var it=items.find(function(x){return x.id===id;});return it?it.name:'';}).filter(Boolean).join(', '); return ''; }).join('')+'
#Chest NoNameSectionItems
'+(i+1)+''+p.chestNo+''+p.name+''+p.section+''+pItems+'
'; }); } else if(type==='codelist'){ items.filter(function(item){return marks.some(function(m){return m.itemId===item.id&&m.codeLetter;});}).forEach(function(item){ const itemMarks=marks.filter(function(m){return m.itemId===item.id&&m.codeLetter;}).sort(function(a,b){return a.codeLetter.localeCompare(b.codeLetter);}); html+='

🔤 '+item.name+' ('+item.section+')

' +itemMarks.map(function(m){ if(item.type==='group'){ var g=groups.find(function(gr){return gr.groupChestNo===m.chestNo&&gr.itemId===item.id;}); return ''; } const p=participants.find(function(pt){return pt.chestNo===m.chestNo;}); return ''; }).join('')+'
CodeNameChest NoTeam
'+m.codeLetter+''+(g?g.name:'?')+''+m.chestNo+''+(g?g.team:'?')+'
'+m.codeLetter+''+(p?p.name:'?')+''+m.chestNo+''+(p?p.team:'?')+'
'; }); } else if(type==='results'){ DB.sections().forEach(function(section){ const sectionItems=items.filter(function(i){return i.section===section&&marks.some(function(m){return m.itemId===i.id&&m.total>0;});}); if(!sectionItems.length) return; html+='

📚 '+section+'

'; sectionItems.forEach(function(item){ const im=marks.filter(function(m){return m.itemId===item.id&&m.total>0;}).sort(function(a,b){return b.total-a.total;}); html+='

'+item.name+(item.declared?' ✓ Declared':'')+'

' +'' +im.slice(0,3).map(function(m,idx){ var grp=item.type==='group'?groups.find(function(g){return g.groupChestNo===m.chestNo&&g.itemId===item.id;}):null; var p=participants.find(function(pt){return pt.chestNo===m.chestNo;}); var name=grp?grp.name:(p?p.name:'?'); var team=grp?grp.team:(p?p.team:'?'); return ''; }).join('')+'
RankNameTeamPointsGrade
'+(idx+1)+''+name+''+team+''+m.point+''+m.grade+'
'; }); }); } openPrint(html); }function printSectionPoints(section){ const cfg=DB.config(), tp=calcTeamPoints(); const data=Object.entries(tp).map(([name,pts])=>({name,pts:pts.sections[section]||{total:0,r1:0,r2:0,r3:0}})).sort((a,b)=>b.pts.total-a.pts.total); let html=printHeader(cfg)+`

๐Ÿ“‚ ${section} - Section Points

${data.map((d,i)=>``).join('')}
RankTeam1st2nd3rdTotal
${i+1}${d.name}${d.pts.r1}${d.pts.r2}${d.pts.r3}${d.pts.total}
`; openPrint(html); } function printIndvPoints(section, tab='overall'){ const cfg=DB.config(), participants=DB.participants(), marks=DB.marks(), items=DB.items(), cfgD=DB.config(); const declaredItems=items.filter(i=>i.declared); const filtered=section==='All'?participants:participants.filter(p=>p.section===section); const data=filtered.map(p=>{ let total=0,r1=0,r2=0,r3=0; declaredItems.forEach(item=>{ const m=marks.find(m=>m.itemId===item.id&&m.chestNo===p.chestNo&&m.total>0); if(!m) return; if(m.rank===1){total+=cfgD.pt1||5;r1++;}else if(m.rank===2){total+=cfgD.pt2||3;r2++;}else if(m.rank===3){total+=cfgD.pt3||1;r3++;} }); return {p,total,r1,r2,r3}; }).filter(x=>x.total>0).sort((a,b)=>b.total-a.total); let html=printHeader(cfg)+`

๐Ÿ‘ค Individual Points${section!=='All'?' - '+section:''}

${data.map((x,i)=>``).join('')}
RankNameGroupSection1st2nd3rdTotal
${i+1}${x.p.name}${x.p.team}${x.p.section}${x.r1}${x.r2}${x.r3}${x.total}
`; openPrint(html); } function printIndvDetailed(section){ const cfg=DB.config(), participants=DB.participants(), marks=DB.marks(), items=DB.items(); const declaredItems=items.filter(i=>i.declared); const filtered=section==='All'?participants:participants.filter(p=>p.section===section); let html=printHeader(cfg)+`

๐Ÿ“ Individual Detailed Points${section!=='All'?' - '+section:''}

`; filtered.forEach(p=>{ const pItems=declaredItems.filter(item=>(p.items||[]).includes(item.id)); if(!pItems.length) return; let total=0; const rows=pItems.map(item=>{ const m=marks.find(m=>m.itemId===item.id&&m.chestNo===p.chestNo); let pts=0; if(m&&m.total>0){if(m.rank===1) pts=cfg.pt1||5;else if(m.rank===2) pts=cfg.pt2||3;else if(m.rank===3) pts=cfg.pt3||1;} total+=pts; return {item,m,pts}; }); if(rows.every(r=>!r.m||r.m.total===0)) return; html+=`

${p.name} #${p.chestNo} ยท ${p.team} ยท ${p.section}

${rows.map(({item,m,pts})=>``).join('')}
EventMarksGradeRankPoints
${item.name}${m?.total||'-'}${m?.grade||'-'}${m?.rank>0?m.rank:'-'}${pts||'-'}
Total${total}
`; }); openPrint(html); } function printWinnerList(section){ const cfg=DB.config(), items=DB.items().filter(i=>i.declared), participants=DB.participants(), marks=DB.marks(); const filteredItems=section==='All'?items:items.filter(i=>i.section===section); let html=printHeader(cfg)+`

๐Ÿ… Winner List${section!=='All'?' - '+section:''}

`; filteredItems.forEach(item=>{ const im=marks.filter(m=>m.itemId===item.id&&m.total>0).sort((a,b)=>b.total-a.total).slice(0,3); if(!im.length) return; html+=`

${item.name} (${item.section})

${im.map((m,idx)=>{const p=participants.find(pt=>pt.chestNo===m.chestNo);return ``;}).join('')}
RankNameGroupMarksGrade
${idx+1}${p?.name||'?'}${p?.team||'?'}${m.total}${m.grade}
`; }); openPrint(html); } function printCodeDetailed(){ const cfg=DB.config(), items=DB.items(), participants=DB.participants(), marks=DB.marks(); const itemsWithP=items.filter(item=>participants.some(p=>(p.items||[]).includes(item.id))); let html=printHeader(cfg); itemsWithP.forEach(item=>{ const itemP=participants.filter(p=>(p.items||[]).includes(item.id)); const itemMarks=marks.filter(m=>m.itemId===item.id); const sorted=itemP.map(p=>({p,m:itemMarks.find(m=>m.chestNo===p.chestNo)})).sort((a,b)=>(a.m?.codeLetter||'').localeCompare(b.m?.codeLetter||'')); html+=`
${item.section}
${item.name}
${sorted.map(({p,m})=>` `).join('')}
Code Chest No. Name Group Signature
${m?.codeLetter||'?'} #${p.chestNo} ${p.name} ${p.team}  
`; }); openPrint(html); } // ============================================= // CONTACT US // ============================================= function renderContactUs(){ return `
๐Ÿ‘จโ€๐Ÿ’ป
Mubashir Rabbani
Developer & Designer
๐Ÿ“ž Get In Touch
๐Ÿ“ฑ
+91 9747415247
Tap to call
โœ‰๏ธ
mubashirakomr1@gmail.com
Tap to email
๐Ÿ’ฌ
WhatsApp
Chat on WhatsApp
โ˜• Buy Me a Coffee
If this app helped your event run smoothly, consider buying me a coffee via Google Pay!
โ˜•
Pay via Google Pay / UPI
9747415247 ยท Mubashir Rabbani
UPI ID: 9747415247@okbizaxis
๐Ÿ’ก Suggest an Update
Have an idea or found a bug? We'd love to hear from you!
`; } function sendFeedback(e){ e.preventDefault(); const name=document.getElementById('fb-name')?.value.trim()||'Anonymous'; const msg=document.getElementById('fb-msg')?.value.trim(); if(!msg) return toast('Please enter your feedback','error'); const text=encodeURIComponent(`*Sahithyotsav App Feedback* From: ${name} ${msg}`); window.open(`https://wa.me/919747415247?text=${text}`,'_blank'); } // ============================================= // DATA EXPORT / IMPORT // ============================================= function exportData(){ const data={config:DB.config(),teams:DB.teams(),sections:DB.sections(),items:DB.items(),participants:DB.participants(),marks:DB.marks(),exportDate:new Date().toISOString()}; const blob=new Blob([JSON.stringify(data,null,2)],{type:'application/json'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=`sahithyotsav_backup_${new Date().toISOString().split('T')[0]}.json`; a.click(); toast('Data exported!'); } function importData(event){ const file=event.target.files[0]; if(!file) return; const reader=new FileReader(); reader.onload=e=>{ try{ const data=JSON.parse(e.target.result); if(data.config) DB.saveConfig(data.config); if(data.teams) DB.saveTeams(data.teams); if(data.sections) DB.saveSections(data.sections); if(data.items) DB.saveItems(data.items); if(data.participants) DB.saveParticipants(data.participants); if(data.marks) DB.saveMarks(data.marks); toast('Data imported!'); navigate('dashboard'); }catch(err){toast('Invalid file','error');}}; reader.readAsText(file); } // ============================================= // UTILS // ============================================= function v(id){ const el=document.getElementById(id); return el?el.value:''; } function showModal(html){ document.getElementById('modalContent').innerHTML=html; document.getElementById('modalOverlay').classList.remove('hidden'); } function closeModal(){ document.getElementById('modalOverlay').classList.add('hidden'); } let toastTimer; function toast(msg,type='success'){ const ex=document.querySelector('.toast'); if(ex) ex.remove(); clearTimeout(toastTimer); const el=document.createElement('div'); el.className=`toast ${type==='error'?'error':''}`; el.textContent=msg; document.body.appendChild(el); toastTimer=setTimeout(()=>el.remove(),2500); } // ============================================= // INIT // ============================================= window.addEventListener('load',()=>{ initTheme(); setTimeout(()=>{ document.getElementById('splash').style.opacity='0'; setTimeout(()=>{ document.getElementById('splash').style.display='none'; document.getElementById('app').style.display='flex'; navigate('dashboard',{},false); },600); },1800); }); if('serviceWorker' in navigator){ window.addEventListener('load',()=>navigator.serviceWorker.register('/sw.js').catch(()=>{})); }