274 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			274 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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
 | 
						|
}
 | 
						|
 |