const path = require("path"); const _wineFunctions = require(path.join(__dirname, "/wine")); const _personFunctions = require(path.join(__dirname, "/person")); const Message = require(path.join(__dirname, "/message")); const VirtualWinner = require(path.join( __dirname, "/schemas/VirtualWinner" )); const PreLotteryWine = require(path.join( __dirname, "/schemas/PreLotteryWine" )); const getWinesToWinnerById = async (req, res) => { let id = req.params.id; let foundWinner = await VirtualWinner.findOne({ id: id }); if (!foundWinner) { return res.json({ success: false, message: "No winner with this id.", existing: false, turn: false }); } let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); if ( allWinners[0].id != foundWinner.id || foundWinner.timestamp_limit == undefined || foundWinner.timestamp_sent == undefined ) { return res.json({ success: false, message: "Not the winner next in line!", existing: true, turn: false }); } return res.json({ success: true, existing: true, turn: true, name: foundWinner.name, color: foundWinner.color }); }; const registerWinnerSelection = async (req, res) => { let id = req.params.id; let wineName = req.body.wineName; let foundWinner = await VirtualWinner.findOne({ id: id }); if (!foundWinner) { return res.json({ success: false, message: "No winner with this id." }) } else if (foundWinner.timestamp_limit < new Date().getTime()) { return res.json({ success: false, message: "Timelimit expired, you will receive a wine after other users have chosen.", limit: true }) } let date = new Date(); date.setHours(5, 0, 0, 0); let prelotteryWine = await PreLotteryWine.findOne({ name: wineName }); if (!prelotteryWine) { return res.json({ success: false, message: "No wine with this name.", wine: false }); } let wonWine = await _wineFunctions.findSaveWine(prelotteryWine); await prelotteryWine.delete(); await _personFunctions.findSavePerson(foundWinner, wonWine, date); await Message.sendWineConfirmation(foundWinner, wonWine, date); await foundWinner.delete(); console.info("Saved winners choice."); return findAndNotifyNextWinner() .then(() => res.json({ message: "Choice saved and next in line notified.", success: true })) .catch(error => res.json({ message: error["message"] || "Error when notifing next winner.", success: false })) }; const chooseLastWineForUser = (winner, preLotteryWine) => { let date = new Date(); date.setHours(5, 0, 0, 0); return _wineFunctions.findSaveWine(preLotteryWine) .then(wonWine => _personFunctions.findSavePerson(winner, wonWine, date)) .then(() => preLotteryWine.delete()) .then(() => Message.sendLastWinnerMessage(winner, preLotteryWine)) .then(() => winner.delete()) .catch(err => { console.log("Error thrown from chooseLastWineForUser: " + err); throw err; }) } const findAndNotifyNextWinner = async () => { let nextWinner = undefined; let winnersLeft = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); let winesLeft = await PreLotteryWine.find(); if (winnersLeft.length > 1) { console.log("multiple winners left, choose next in line") nextWinner = winnersLeft[0]; // multiple winners left, choose next in line } else if (winnersLeft.length == 1 && winesLeft.length > 1) { console.log("one winner left, but multiple wines") nextWinner = winnersLeft[0] // one winner left, but multiple wines } else if (winnersLeft.length == 1 && winesLeft.length == 1) { console.log("one winner and one wine left, choose for user") nextWinner = winnersLeft[0] // one winner and one wine left, choose for user wine = winesLeft[0] return chooseLastWineForUser(nextWinner, wine); } if (nextWinner) { return Message.sendWineSelectMessage(nextWinner) .then(messageResponse => startTimeout(nextWinner.id)) } else { console.info("All winners notified. Could start cleanup here."); return Promise.resolve({ message: "All winners notified." }) } }; const sendNotificationToWinnerById = async (req, res) => { const { id } = req.params; let winner = await VirtualWinner.findOne({ id: id }); if (!winner) { return res.json({ message: "No winner with this id.", success: false }) } return Message.sendWineSelectMessage(winner) .then(success => res.json({ success: success, message: `Message sent to winner ${id} successfully!` })) .catch(err => res.json({ success: false, message: "Error while trying to send sms.", error: err })) } function startTimeout(id) { const minute = 60000; const minutesForTimeout = 10; console.log(`Starting timeout for user ${id}.`); console.log(`Timeout duration: ${ minutesForTimeout * minute }`) setTimeout(async () => { let virtualWinner = await VirtualWinner.findOne({ id: id }); if (!virtualWinner) { console.log(`Timeout done for user ${id}, but user has already sent data.`); return; } console.log(`Timeout done for user ${id}, sending update to user.`); Message.sendWineSelectMessageTooLate(virtualWinner); virtualWinner.timestamp_drawn = new Date().getTime(); virtualWinner.timestamp_limit = null; virtualWinner.timestamp_sent = null; await virtualWinner.save(); findAndNotifyNextWinner(); }, minutesForTimeout * minute); return Promise.resolve() } module.exports = { getWinesToWinnerById, registerWinnerSelection, findAndNotifyNextWinner, sendNotificationToWinnerById };