Winners are rather marked with prize_selected and have it's own endpoint to remove all winners.
		
			
				
	
	
		
			111 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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
 | |
| };
 |