const path = require("path"); const crypto = require("crypto"); const config = require(path.join(__dirname, "/../config/defaults/lottery")); const Message = require(path.join(__dirname, "/message")); const { findAndNotifyNextWinner } = require(path.join(__dirname, "/virtualRegistration")); const Attendee = require(path.join(__dirname, "/schemas/Attendee")); const VirtualWinner = require(path.join(__dirname, "/schemas/VirtualWinner")); const PreLotteryWine = require(path.join(__dirname, "/schemas/PreLotteryWine")); const winners = async (req, res) => { let winners = await VirtualWinner.find(); let winnersRedacted = []; let winner; for (let i = 0; i < winners.length; i++) { winner = winners[i]; winnersRedacted.push({ name: winner.name, color: winner.color }); } res.json(winnersRedacted); }; const winnersSecure = async (req, res) => { let winners = await VirtualWinner.find(); return res.json(winners); }; const deleteWinners = async (req, res) => { await VirtualWinner.deleteMany(); var io = req.app.get('socketio'); io.emit("refresh_data", {}); return res.json(true); }; const attendees = async (req, res) => { let attendees = await Attendee.find(); let attendeesRedacted = []; let attendee; for (let i = 0; i < attendees.length; i++) { attendee = attendees[i]; attendeesRedacted.push({ name: attendee.name, raffles: attendee.red + attendee.blue + attendee.yellow + attendee.green, red: attendee.red, blue: attendee.blue, green: attendee.green, yellow: attendee.yellow }); } return res.json(attendeesRedacted); }; const attendeesSecure = async (req, res) => { let attendees = await Attendee.find(); return res.json(attendees); }; const addAttendee = async (req, res) => { const attendee = req.body; const { red, blue, yellow, green } = attendee; let newAttendee = new Attendee({ name: attendee.name, red, blue, green, yellow, phoneNumber: attendee.phoneNumber, winner: false }); await newAttendee.save(); var io = req.app.get('socketio'); io.emit("new_attendee", {}); return res.send(true); }; const deleteAttendees = async (req, res) => { await Attendee.deleteMany(); var io = req.app.get('socketio'); io.emit("refresh_data", {}); return res.json(true); }; const drawWinner = async (req, res) => { let allContestants = await Attendee.find({ winner: false }); if (allContestants.length == 0) { return res.json({ success: false, message: "No attendees left that have not won." }); } let raffleColors = []; for (let i = 0; i < allContestants.length; i++) { let currentContestant = allContestants[i]; for (let blue = 0; blue < currentContestant.blue; blue++) { raffleColors.push("blue"); } for (let red = 0; red < currentContestant.red; red++) { raffleColors.push("red"); } for (let green = 0; green < currentContestant.green; green++) { raffleColors.push("green"); } for (let yellow = 0; yellow < currentContestant.yellow; yellow++) { raffleColors.push("yellow"); } } raffleColors = shuffle(raffleColors); let colorToChooseFrom = raffleColors[Math.floor(Math.random() * raffleColors.length)]; let findObject = { winner: false }; findObject[colorToChooseFrom] = { $gt: 0 }; let tries = 0; const maxTries = 3; let contestantsToChooseFrom = undefined; while (contestantsToChooseFrom == undefined && tries < maxTries) { const hit = await Attendee.find(findObject); if (hit && hit.length) { contestantsToChooseFrom = hit; break; } tries++; } if (contestantsToChooseFrom == undefined) { return res.status(404).send({ success: false, message: `Klarte ikke trekke en vinner etter ${maxTries} forsøk.` }); } let attendeeListDemocratic = []; let currentContestant; for (let i = 0; i < contestantsToChooseFrom.length; i++) { currentContestant = contestantsToChooseFrom[i]; for (let y = 0; y < currentContestant[colorToChooseFrom]; y++) { attendeeListDemocratic.push({ name: currentContestant.name, phoneNumber: currentContestant.phoneNumber, red: currentContestant.red, blue: currentContestant.blue, green: currentContestant.green, yellow: currentContestant.yellow }); } } attendeeListDemocratic = shuffle(attendeeListDemocratic); let winner = attendeeListDemocratic[ Math.floor(Math.random() * attendeeListDemocratic.length) ]; var io = req.app.get('socketio'); io.emit("winner", { color: colorToChooseFrom, name: winner.name }); let newWinnerElement = new VirtualWinner({ name: winner.name, phoneNumber: winner.phoneNumber, color: colorToChooseFrom, red: winner.red, blue: winner.blue, green: winner.green, yellow: winner.yellow, id: sha512(winner.phoneNumber, genRandomString(10)), timestamp_drawn: new Date().getTime() }); await Attendee.update( { name: winner.name, phoneNumber: winner.phoneNumber }, { $set: { winner: true } } ); await newWinnerElement.save(); return res.json({ success: true, winner }); }; const finish = async (req, res) => { if (!config.gatewayToken) { return res.json({ message: "Missing api token for sms gateway.", success: false }); } let winners = await VirtualWinner.find({ timestamp_sent: undefined }).sort({ timestamp_drawn: 1 }); if (winners.length == 0) { return res.json({ message: "No winners to draw from.", success: false }); } Message.sendInitialMessageToWinners(winners.slice(1)); return findAndNotifyNextWinner() .then(() => res.json({ success: true, message: "Sent wine select message to first winner and update message to rest of winners." })) .catch(error => res.json({ message: error["message"] || "Unable to send message to first winner.", success: false })) }; const genRandomString = function(length) { return crypto .randomBytes(Math.ceil(length / 2)) .toString("hex") /** convert to hexadecimal format */ .slice(0, length); /** return required number of characters */ }; const sha512 = function(password, salt) { var hash = crypto.createHmac("md5", salt); /** Hashing algorithm sha512 */ hash.update(password); var value = hash.digest("hex"); return value; }; function shuffle(array) { let currentIndex = array.length, temporaryValue, randomIndex; // While there remain elements to shuffle... while (0 !== currentIndex) { // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; // And swap it with the current element. temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } module.exports = { deleteWinners, deleteAttendees, winners, winnersSecure, drawWinner, finish, attendees, attendeesSecure, addAttendee }