eventassigner-js
Version:
A NPM package to assign groups / persons to events based on their preference
193 lines (167 loc) • 6.93 kB
JavaScript
;
var _countPlayersInEvent = require('./countPlayersInEvent');
var _updateGroupsAfterAssignment = require('./updateGroupsAfterAssignment');
/* eslint-disable import/named */
function padgOpt(input) {
var groups = input.groups,
events = input.events,
list = input.list,
updateL = input.updateL;
var assignment = groups.map(function (group) {
var returnObject = {};
returnObject.id = group.id;
returnObject.assignment = -1;
return returnObject;
});
var phantomEvents = []; // Phantom events
// function definitions for PhantomEvents
phantomEvents.createEntry = function (newEntry) {
// function to create a new entry to S
phantomEvents.push({
id: newEntry.id,
min: newEntry.min,
max: newEntry.max
});
};
phantomEvents.removeEntry = function (eventid) {
var ind = phantomEvents.findIndex(function (ele) {
return ele.id === eventid;
});
phantomEvents.splice(ind, 1);
};
phantomEvents.includesEvent = function (event) {
// check if event named eventName is in P
if (phantomEvents.filter(function (e) {
return e.id === event.id;
}).length === 1) {
return 1;
} else {
return 0;
}
};
// define deficit
var deficit = 0;
// initialize V to be the same as groups
var unassignedGroups = groups.slice();
unassignedGroups.countPlayers = function () {
return unassignedGroups.reduce(function (total, group) {
return total + group.size;
}, 0);
};
unassignedGroups.removeGroup = function (groupId) {
var returnArray = unassignedGroups.filter(function (group) {
return group.id !== groupId;
});
returnArray.countPlayers = function () {
return returnArray.reduce(function (total, group) {
return total + group.size;
}, 0);
};
return returnArray;
};
// MAIN LOOP STARTS HERE
list = list.filter(function (ele) {
return ele.gain > 0;
});
var _loop = function _loop() {
var listElement = list.pop();
var eventInd = events.findIndex(function (e) {
return e.id === listElement.event;
});
var groupInd = groups.findIndex(function (g) {
return g.id === listElement.id;
});
var assignmentInd = assignment.findIndex(function (a) {
return a.id === listElement.id;
});
/* listElement is the last index of LL
check if there are enough people signed up for this game
in order to avoid matching some group with this event
without hope of this event ever happening */
var numPlayersToThisEvent = groups.reduce(function (total, group) {
if (typeof group.pref.find(function (p) {
return p === listElement.event;
}) !== 'undefined') {
return total + group.size;
} else {
return total;
}
}, 0);
if (listElement.gain === 0 || numPlayersToThisEvent < events[eventInd].min) {
// consider only cases where adding u to event increases happiness
// and those where there is even theoretically possible to have
// minimum number of players
// eslint-disable-next-line no-continue
return 'continue';
}
if (assignment[assignmentInd].assignment === -1 && (0, _countPlayersInEvent.countPlayersInEvent)(groups, events, listElement.event) + listElement.size <= events[eventInd].max) {
// group in listElement is not assigned and there is space in the event where we try to place
// const playersBefore =
if ((0, _countPlayersInEvent.countPlayersInEvent)(groups, events, listElement.event) === 0) {
// no players in this event
if (deficit + (events[eventInd].min - listElement.size) < unassignedGroups.countPlayers()) {
// adding listElement to this event does not decrease deficit over critical size
// since event is not yet real event add it to P
// add to deficit how much space was left over in this event and update deficit
deficit += events[eventInd].min - listElement.size;
if (phantomEvents.includesEvent(events[eventInd]) === 0) {
var newPEntry = {
id: events[eventInd].id,
min: events[eventInd].min,
max: events[eventInd].max
};
phantomEvents.createEntry(newPEntry);
}
} else {
// eslint-disable-next-line no-continue
return 'continue';
}
} else if (phantomEvents.includesEvent(events[eventInd]) === 1) {
// event has players, decrease deficit
deficit -= listElement.size;
}
events[eventInd].groups.push(listElement.id);
unassignedGroups.removeGroup(listElement.id);
if ((0, _countPlayersInEvent.countPlayersInEvent)(groups, events, listElement.event) >= events[eventInd].min && phantomEvents.includesEvent(events[eventInd]) === 0) {
// this event is not a phantom event, set M(u) to a
assignment[assignmentInd].assignment = listElement.event;
var updatedObjects = (0, _updateGroupsAfterAssignment.updateGroupsAfterAssignment)(events, phantomEvents, groups, unassignedGroups, assignment, groups[groupInd], listElement.event, 'real');
groups = updatedObjects.returnGroups;
events = updatedObjects.returnEvents;
deficit = updatedObjects.returnDeficit;
unassignedGroups = updatedObjects.returnUnassignedGroups;
phantomEvents = updatedObjects.returnPhantomEvents;
assignment = updatedObjects.returnAssignment;
}
if ((0, _countPlayersInEvent.countPlayersInEvent)(groups, events, listElement.event) >= events[eventInd].min && phantomEvents.includesEvent(events[eventInd]) === 1) {
// this event is a phantom event but has now enough players to be a real event
assignment[assignmentInd].assignment = listElement.event;
var _updatedObjects = (0, _updateGroupsAfterAssignment.updateGroupsAfterAssignment)(events, phantomEvents, groups, unassignedGroups, assignment, groups[groupInd], listElement.event, 'phantomToReal');
groups = _updatedObjects.returnGroups;
events = _updatedObjects.returnEvents;
deficit = _updatedObjects.returnDeficit;
unassignedGroups = _updatedObjects.returnUnassignedGroups;
phantomEvents = _updatedObjects.returnPhantomEvents;
assignment = _updatedObjects.returnAssignment;
}
// Update list LL if there was no assignment
if (assignment[assignmentInd].assignment === -1) {
list = updateL({
groups: groups,
events: events,
assignment: assignment,
unassignedGroups: unassignedGroups,
deficit: deficit,
list: list,
groupId: listElement.id
});
}
}
};
while (list.length > 0) {
var _ret = _loop();
if (_ret === 'continue') continue;
}
return assignment;
}
module.exports = { padgOpt: padgOpt };