diff --git a/assets/styles/form.scss b/assets/styles/form.scss index 0330cc9..bd0404c 100644 --- a/assets/styles/form.scss +++ b/assets/styles/form.scss @@ -374,3 +374,44 @@ input[type=date]{ text-decoration: underline; font-weight: 600; } +.loader{ + width: 100px; + height: 100px; +} + +.circular{ + animation: rotate 2s linear infinite; + height: 100px; + position: relative; + width: 100px; +} + +.path { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; + stroke:var(--red); + animation: + dash 1.5s ease-in-out infinite, + ; + stroke-linecap: round; +} + +@keyframes rotate{ + 100%{ + transform: rotate(360deg); + } +} +@keyframes dash{ + 0%{ + stroke-dasharray: 1,200; + stroke-dashoffset: 0; + } + 50%{ + stroke-dasharray: 89,200; + stroke-dashoffset: -35; + } + 100%{ + stroke-dasharray: 89,200; + stroke-dashoffset: -124; + } +} \ No newline at end of file diff --git a/database/Schemas/Location.js b/database/Schemas/Location.js index 1dd3f1b..7c6ee04 100644 --- a/database/Schemas/Location.js +++ b/database/Schemas/Location.js @@ -1,7 +1,7 @@ const mongoose = require('mongoose'); const locationSchema = new mongoose.Schema({ - _id: { type: String, required: true }, + _id: { type: Number, required: true }, name: { type: String, required: true }, pointerQuestion: [{ type: String, required: true }], code: { type: String, required: true }, diff --git a/database/Schemas/Team.js b/database/Schemas/Team.js index ee643a3..5073651 100644 --- a/database/Schemas/Team.js +++ b/database/Schemas/Team.js @@ -12,7 +12,7 @@ const teamSchema = new mongoose.Schema({ phone: { type: String, required: true } } ], - status: { type: String, required: true }, + status: { type: String, required: true, enum: ['location-code', 'riddle-question', 'riddle-timeout', 'completed'] }, questionsAttempted: { type: Number, required: true, default: 0 }, order: [ { diff --git a/database/handler.js b/database/handler.js index a19a179..a81fb57 100644 --- a/database/handler.js +++ b/database/handler.js @@ -209,13 +209,13 @@ async function updateTeamStatus (ctx) { const team = await Team.findById(_id); team.status = status; if (status === 'riddle-timeout') { - team.timeout = new Date(Date.now() + 120 * 1000); + team.timeout = new Date(Date.now() + (120 + 5) * 1000); setTimeout(async () => { team.status = 'riddle-question'; team.timeout = null; await team.save(); - }, 120 * 1000); - } else if (status === 'location-code') { + }, (115 + 5) * 1000); + } else { team.questionsAttempted = ctx.questionNo; } return await team.save(); diff --git a/routers/base-router.js b/routers/base-router.js index 694166e..19a6d7f 100644 --- a/routers/base-router.js +++ b/routers/base-router.js @@ -4,8 +4,8 @@ router.get(['/home', '/'], (req, res) => { return res.renderFile('info/landing.njk'); }); -router.get('/information', (req, res) => { - return res.renderFile('info/information.njk'); +router.get('/instructions', (req, res) => { + return res.renderFile('info/instructions.njk'); }); module.exports = { diff --git a/routers/live-router.js b/routers/live-router.js index ffdb08d..abe8a40 100644 --- a/routers/live-router.js +++ b/routers/live-router.js @@ -4,10 +4,12 @@ const { body, validationResult } = require('express-validator'); const checker = require('../src/checker.js'); const teams = require('../src/samples/teams.json'); -// const locations = require('../src/samples/locations.json'); +const locations = require('../src/samples/locations.json'); const handlerContext = {}; +const ques = 6; + router.use((req, res, next) => { if (!req.loggedIn) return req.method === 'GET' ? res.redirect('/login') : res.status(403).send('Forbidden. Not logged in.'); return next(); @@ -15,24 +17,15 @@ router.use((req, res, next) => { router.use((req, res, next) => { if (handlerContext.huntStarted || req.isAdmin) return next(); - return req.method === 'GET' ? res.redirect('/') : res.status(400).send('Hunt not started'); + return req.method === 'GET' ? res.redirect('/') : res.status(786).send('ALLAHU AKBAR!!!'); }); -// const team = teams[1]; - -// const locationQuestion = { -// id: 1, -// question: 'Where is the best waifu', -// answer: 'Oregairu' -// }; - -// const riddleQuestion = riddleQuestions[0]; - -// const locationCode = 'ABC123'; - router.get('/', async (req, res) => { if (req.isAdmin) { const teamList = await dbh.getTeams(); + teamList.sort((t1, t2) => { + return -(t1._id < t2._id); + }); return res.renderFile('admin/team-list.njk', { teams: teamList }); @@ -40,66 +33,78 @@ router.get('/', async (req, res) => { // if (!handlerContext.quizStarted) return res.redirect('/'); return res.renderFile('live/interface.njk', { team: req.team, - started: handlerContext.huntStarted + started: true }); // return res.renderFile('live/interface.njk'); } }); -router.post('/get-data', async (req, res) => { +// combine the bottom 3 into one route +router.post('/get-data', (req, res) => { const teamID = req.body.teamID; if (teamID !== req.team._id) return res.status(500).send('WHy you hax'); - const locations = await dbh.getLocations(); - return res.status(200).send(JSON.stringify({ - team: req.team, - locations: req.team.order.map((o) => locations.find((l) => l._id === o.location)) - })); + return res.status(200).send(req.team); +}); + +router.post('/get-location-question', (req, res) => { + const attempted = req.team.questionsAttempted; + if (attempted >= ques) return res.status(418).send('Completed'); + return res.send( + req.team.order.map((o) => + handlerContext.locations.find((l) => l._id === o.location) + )[attempted].pointerQuestion[req.team.order[attempted].pointer] + ); +}); + +router.post('/get-riddle-question', (req, res) => { + const attempted = req.team.questionsAttempted; + if (attempted >= ques) return res.status(418).send('Completed'); + const location = req.team.order.map((o) => handlerContext.locations.find((l) => l._id === o.location))[attempted]; + return res.send({ + question: location.questions[req.team.order[attempted].question].question, + keywords: location.keywords + }); }); -router.post('/get-attempted', (req, res) => { - const teamID = req.body.teamID; - if (teamID !== req.team._id) return res.status(500).send('WHy you hax'); - return res.status(200).send(req.team.questionsAttempted); -}); -router.post('/get-state', (req, res) => { - const teamID = req.body.teamID; - if (teamID !== req.team._id) return res.status(500).send('WHy you hax'); - return res.status(200).send(req.team.status); -}); -router.post('/get-timeout', async (req, res) => { - if (req.team.status === 'riddle-timeout') { - return res.status(200).send(req.team.timeout); +router.post('/submit', async (req, res) => { + const attempted = req.team.questionsAttempted; + if (req.body.questionNo !== attempted) return res.status(420).send('Koi bkl hi hoga'); + if (req.body.state !== req.team.status) return res.status(420).send('Koi bkl hi hoga'); + if (req.body.state === 'riddle-question') { + if (attempted + 1 >= ques) { + await dbh.updateTeamStatus({ _id: req.team._id, status: 'completed', questionNo: 6 }); + return res.status(418).send('Completed'); + } + } + if (req.body.state === 'riddle-question') { + if ( + req.team.order.map((o) => + handlerContext.locations.find((l) => l._id === o.location) + )[attempted].questions[req.team.order[attempted].question].answer === parseInt(req.body.answer) + ) { + await dbh.updateTeamStatus({ _id: req.team._id, status: 'location-code', questionNo: req.body.questionNo + 1 }); + return res.status(200).send('correct answer'); + } + await dbh.updateTeamStatus({ _id: req.team._id, status: 'riddle-timeout', questionNo: req.body.questionNo }); + return res.status(469).send('wrong answer'); + } else if (req.body.state === 'location-code') { + if ( + req.team.order.map((o) => + handlerContext.locations.find((l) => l._id === o.location) + )[attempted].code === req.body.answer + ) { + await dbh.updateTeamStatus({ _id: req.team._id, status: 'riddle-question', questionNo: req.body.questionNo }); + return res.status(200).send('correct answer'); + } + return res.status(469).send('wrong answer'); } - return res.status(400).send(false); -}); - -router.post('/update-status', async (req, res) => { - // if (req.body.questionNo !== req.team.questionsAttempted) return; - await dbh.updateTeamStatus({ _id: req.team._id, status: req.body.status, questionNo: req.body.questionNo }); - return res.status(200).send('Updated Successfully'); -}); -router.post('/update-attempted', async (req, res) => { - await dbh.updateTeamStatus({ _id: req.team._id, status: req.body.status, questionNo: req.body.questionNo }); - return res.status(200).send('Updated Successfully'); }); -// router.patch('/location-code', async (req, res) => { -// const teamID = parseInt(req.body.id); -// const location = req.body.locationcode; -// // console.log(teamID); -// // console.log(location); -// // FIND TEAM BY ID IN LOCAL STORAGE -// // MARK TEAM AS COMPLETED FOR LOCATION BY FINDING TEAM BY ID AND ADDING LOCATION TO COMPLETED LOCATIONS LIST -// if (location === locationCode) { -// return res.send('correct'); -// } else { -// return res.status(400).send('incorrect location'); -// } -// }); - -router.post('/start-hunt', (req, res) => { +router.post('/start-hunt', async (req, res) => { if (!req.isAdmin) return res.status(403).send('Forbidden: Admin permissions not detected.'); handlerContext.huntStarted = true; + handlerContext.teams = await dbh.getTeams(); + handlerContext.locations = await dbh.getLocations(); return res.send('Hunt Started'); }); diff --git a/templates/_base.njk b/templates/_base.njk index ea87577..ef2a3b6 100644 --- a/templates/_base.njk +++ b/templates/_base.njk @@ -1,6 +1,6 @@ {% set navlinks = [ - { name: 'Information', href: 'information' }, - { name: 'Quiz Portal', href: 'live' } + { name: 'Instructions', href: 'instructions' }, + { name: 'Treasure Hunt', href: 'live' } ] %} {# array elements: { name, href } #} @@ -62,14 +62,8 @@ @@ -80,19 +74,16 @@
{% for link in navlinks %}
{{ link.name }}
- {% if not loop.last %}
{% endif %} +
{% endfor %} + {#
Our Society

Our Members
#} {% if loggedIn %} -
Profile
-
-
Logout
+
Logout
{% else %} -
Login
-
-
Register
+
Login
{% endif %}
diff --git a/templates/admin/team-edit.njk b/templates/admin/team-edit.njk index 177105f..1468a3f 100644 --- a/templates/admin/team-edit.njk +++ b/templates/admin/team-edit.njk @@ -9,8 +9,7 @@ {% block pagecontent %} {% call forms.form() %} {{ forms.heading('h1','Edit Team') }} -
- {{ forms.field('id','ID', team._id)}} +

{{ forms.field('teamName','Name', team.name)}}
diff --git a/templates/auth/login.njk b/templates/auth/login.njk index 067b38d..045956b 100644 --- a/templates/auth/login.njk +++ b/templates/auth/login.njk @@ -10,9 +10,8 @@ {% block pagecontent %} {% call forms.form() %} {{ forms.heading('h1','Login') }} - {{ forms.link('registerlink', "New to our site? ", 'Register Now!', link='/signup' )}} - {{ forms.field('username','Username')}} - {{ forms.field('password','Password',type='password')}} + {{ forms.field('username','Team ID')}} + {{ forms.field('password','Passcode',type='password')}} {{ forms.button('submit', 'Login', 'login') }} {% endcall %} {% endblock %} diff --git a/templates/info/information.njk b/templates/info/information.njk deleted file mode 100644 index 28a8c21..0000000 --- a/templates/info/information.njk +++ /dev/null @@ -1,53 +0,0 @@ -{% extends '_base.njk' %} - -{% set pagetitle = 'Information' %} -{% set thispage = 'information' %} - -{% block pagecontent %} -
-

Event Information

- - In case of any doubt, feel free to contact Aman (63773 08533) and Soumil (86975 63554) -
-{% endblock %} - -{% block customcss %} - -{% endblock %} diff --git a/templates/info/instructions.njk b/templates/info/instructions.njk new file mode 100644 index 0000000..2808945 --- /dev/null +++ b/templates/info/instructions.njk @@ -0,0 +1,71 @@ +{% extends '_base.njk' %} + +{% set pagetitle = 'Instructions' %} +{% set thispage = 'instructions' %} + +{% block pagecontent %} +
+

Event Information

+ +
+

Instructions

+
+ + In case of any doubt, feel free to contact Aman (63773 08533) and Soumil (86975 63554) +
+{% endblock %} + +{% block customcss %} + +{% endblock %} diff --git a/templates/info/landing.njk b/templates/info/landing.njk index eb7a7b2..dcf20b0 100644 --- a/templates/info/landing.njk +++ b/templates/info/landing.njk @@ -1,6 +1,6 @@ {% extends '_base.njk' %} -{% set pagetitle = 'Open Campus Anime Quiz' %} +{% set pagetitle = "Anime Seekers' Quest" %} {% block pagecontent %} {{ loadingscreen('main-page') }} @@ -21,13 +21,16 @@

Konnichiwa, minna-san!!!

-

We, MASK, have returned with an Open Campus Quiz for everyone in IIT Kharagpur, from UG students to PG students (and even professors if interested). For the freshers, this will be an introductory event and for the all of our beloved patrons, this will be an experience you wouldn't want to miss.

+

It's about time we came back with an event. Well, here we are. We welcome you to the second edition of the Anime Seekers' Quest, a treasure hunt event across the span of 2.2, just for you guys.

+

What can you expect?

-

Showcasing various aspects of our society, this event has a lot of things packed, be it the mind-boggling quiz, specially-curated prizes or the various surprises packed just for you.

+

Starting from our very own TSG, you will have to make your way through 2.2 using the clues given to you to search for our MASK members and solve a riddle. Those who finish all the riddles given to them shall return to TSG and redeem their prizes.

+

For more information, check out the Instructions page.

+

What are the questions from?

The questions are from a variety of popular anime, be it the never-ending One Piece or rom-coms like Oregairu, good ol' Death Note or popular new anime like Demon Slayer, Jujutsu Kaisen or Oshi No Ko. We have a vast collection which satisfies all kinds of fans. (Except maybe Samuel L. Jackson. I don't think we can give him what he wants.)

-

For more info, check out the Information page. Stay tuned for more updates.

-

Limited Seats Only! Register Soon!!!

+ +

Don your straw hats and set out to find your treasure.

{#
Information @@ -44,10 +47,11 @@ const timerElement = document.querySelector('#timer'); const timer = () => { let seconds, minutes, hours, days; - const timeLeftInSeconds = Math.floor((new Date('2023-09-03T14:20:00+0530').getTime() - new Date().getTime()) / 1000); + // const timeLeftInSeconds = Math.floor((new Date('2024-03-17T15:30:00+0530').getTime() - new Date().getTime()) / 1000); + const timeLeftInSeconds = -1; if (timeLeftInSeconds <= 0) { timerElement.innerHTML = ` - Join the Quiz!! + Start the Hunt!!! `; return false; } diff --git a/templates/live/interface.njk b/templates/live/interface.njk index 1600026..21a7690 100644 --- a/templates/live/interface.njk +++ b/templates/live/interface.njk @@ -8,66 +8,293 @@ {% block pagecontent %} {% if started %} -
- {% call forms.form() %} -
- {% endcall %} -
- - {{ loadingscreen('instructions') }} - + + {% else %}
Not Started
{% endif %} @@ -75,129 +302,130 @@ {% block customcss %} {{ forms.formCss() }} {% endblock %} @@ -205,219 +433,250 @@ {% block customjs %} {{ forms.formFunction() }} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/live/landing.njk b/templates/live/landing.njk index 842c045..a8af87c 100644 --- a/templates/live/landing.njk +++ b/templates/live/landing.njk @@ -1,6 +1,6 @@ {% extends 'info/landing.njk' %} -{% set pagetitle = 'Open Campus Anime Quiz' %} +{% set pagetitle = 'Anime Seekers‘ Quest' %} {% block extrajs %}