const path = require("path"); const Wine = require(path.join(__dirname, "/schemas/Wine")); const PreLotteryWine = require(path.join(__dirname, "/schemas/PreLotteryWine")); const VirtualWinner = require(path.join(__dirname, "/schemas/VirtualWinner")); const message = require(path.join(__dirname, "/message")); const historyRepository = require(path.join(__dirname, "/history")); const winnerRepository = require(path.join(__dirname, "/winner")); const wineRepository = require(path.join(__dirname, "/wine")); const prelotteryWineRepository = require(path.join(__dirname, "/prelotteryWine")); const { WinnerNotFound, WineSelectionWinnerNotNextInLine, WinnersTimelimitExpired } = require(path.join( __dirname, "/vinlottisErrors" )); const verifyWinnerNextInLine = async id => { let foundWinner = await VirtualWinner.findOne({ id: id }); if (!foundWinner) { throw new WinnerNotFound(); } else if (foundWinner.timestamp_limit < new Date().getTime()) { throw new WinnersTimelimitExpired(); } let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); if ( foundWinner.timestamp_limit == undefined || foundWinner.timestamp_sent == undefined || foundWinner.prize_selected == true ) { throw new WineSelectionWinnerNotNextInLine(); } return Promise.resolve(foundWinner); }; const claimPrize = (wine, winner) => { return wineRepository .addWine(wine) .then(_ => prelotteryWineRepository.addWinnerToWine(wine, winner)) // prelotteryWine.deleteById .then(_ => historyRepository.addWinnerWithWine(winner, wine)) // wines.js : addWine .then(_ => message.sendWineConfirmation(winner, wine)); }; const notifyNextWinner = async () => { let nextWinner = undefined; const winnersLeft = await VirtualWinner.find({ prize_selected: false }).sort({ timestamp_drawn: 1 }); const winesLeft = await PreLotteryWine.find({ winner: { $exists: false } }); 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 claimPrize(wine, nextWinner); } if (nextWinner) { return message.sendPrizeSelectionLink(nextWinner).then(_ => startTimeout(nextWinner.id)); } else { console.info("All winners notified. Could start cleanup here."); return Promise.resolve({ message: "All winners notified." }); } }; // these need to be register somewhere to cancel if something // goes wrong and we want to start prize distribution again 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, prize_selected: false }); 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(); notifyNextWinner(); }, minutesForTimeout * minute); return Promise.resolve(); } module.exports = { verifyWinnerNextInLine, claimPrize, notifyNextWinner };