PADGopt = (Lis,evnt,grp,grpAll,updateFun) => {
let LL = JSON.parse(JSON.stringify(Lis))
let evn = JSON.parse(JSON.stringify(evnt))
let M = grp.map(e => {
return {name: e.name,assignment: -1}
})
let S = evn.map(ele => {
return {
name: ele.name,
min: ele.min,
max: ele.max,
groups: ele.hasOwnProperty('groups') ? ele.groups : []
}
})
if(typeof(S.playerCount) === 'undefined') {
S.playerCount = (e) => {
if(S[e].groups.length > 0) {
return S[e].groups.reduce((a, b) => {
return a+grpAll.filter(g=>g.name === b)[0].size
}, 0);
} else {
return 0
}
}
}
let P = []
P.createEntry = (newEntry) => {
P.push({name: newEntry.name,
min: newEntry.min,
max: newEntry.max,
})
}
P.removeEntry = (eventName) => {
let ind = P.findIndex(ele => ele.name === eventName)
P.splice(ind,1)
}
P.includes = (eventName) => {
//check if event named eventName is in P
if(P.filter(ele => ele.name === eventName).length === 1) {
return 1
} else {
return 0
}
}
//define deficit
let deficit = 0
//initialize V to be the same as groups
let V = grp.slice()
//MAIN LOOP STARTS HERE
LL = LL.filter(ele => ele.gain > 0)
while(LL.length>0) {
let u = LL.pop() // u 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
let numPlayersToThisEvent = 0
grp.filter(ele => {
return typeof(ele.pref.find(p => p===u.event)) !== 'undefined'})
.forEach(ele => {
numPlayersToThisEvent = numPlayersToThisEvent + ele.size
})
if(u.gain === 0 || numPlayersToThisEvent < evnt[u.event].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
continue
}
let Mind = M.findIndex(g => g.name === u.name)
if(M[Mind].assignment === -1 && (S.playerCount(u.event) + u.size) <= S[u.event].max) {
// user u is not assigned and there is space in the event where we try to place u
//console.log('before')
//console.log(S.playerCount(u.event))
let playersBefore = S.playerCount(u.event)
if(S.playerCount(u.event) === 0) {
//no players in S or S is not yet a real event
if( deficit + (evnt[u.event].min - u.size) < V.length) {
// adding u to this event does not decrease deficit over critical size
// since event is not in S add it to P
// add to deficit how much space was left over in this event
deficit = deficit + (evnt[u.event].min - u.size)
if(P.includes(S[u.event].name) === 0) {
let newPEntry = {
name: evnt[u.event].name,
min: evnt[u.event].min,
max: evnt[u.event].max,
}
P.createEntry(newPEntry)
}
} else {
continue
}
} else {
// S has players and is happening anyway
if(P.includes(evnt[u.event].name) === 1) {
deficit = deficit - u.size
}
}
S[u.event].groups.push(u.name)
V = V.filter(ele => ele.name !== u.name)
if(S.playerCount(u.event) >= S[u.event].min && P.includes(S[u.event].name) === 0) {
// this event is not a phantom event, set M(u) to a
M[Mind].assignment = u.event
// remove u from other events
S.forEach(ele => {
if(ele.name !== S[u.event].name) {
let nPlayersBefore = S.playerCount(S.findIndex(s=>s.name === ele.name))
ele.groups = ele.groups.filter(e => e !== u.name)
// check that there are enough players in this event
let nPlayersAfter = S.playerCount(S.findIndex(s=>s.name === ele.name))
//if nPlayers < ele.min add this event as a phantom event
if(nPlayersAfter < nPlayersBefore && nPlayersAfter < ele.min) {
if(P.includes(ele.name) === 0) {
P.createEntry({
name: ele.name,
min: ele.min,
max: ele.max
})
}
// remove assignment
ele.groups.forEach(e => {
let MindTemp = M.findIndex(m => m.name === e)
if(M[MindTemp].assignment === S.findIndex(s=>s.name === ele.name)) {
M[MindTemp].assignment = -1;
}
})
}
}
})
}
if(S.playerCount(u.event) >= S[u.event].min && P.includes(S[u.event].name) === 1) {
// this event is a phantom event but has now enough players to be a real event
//console.log(u.event)
P.removeEntry(S[u.event].name) // remove this event from phantom events
S[u.event].groups.forEach(el => {
let MindTemp = M.findIndex(m => m.name === el)
M[MindTemp].assignment = u.event
})
for(let g in S[u.event].groups) {
S.forEach(ele => {
if(ele.name !== S[u.event].name) {
let nPlayersBefore = S.playerCount(S.findIndex(s=>s.name === ele.name))
ele.groups = ele.groups.filter(e => e !== S[u.event].groups[g])
// check that there are enough players in this event
let nPlayersAfter = S.playerCount(S.findIndex(s=>s.name === ele.name))
//if nPlayers < ele.min add this event as a phantom event
if(nPlayersAfter < nPlayersBefore && nPlayersAfter < ele.min) {
if(P.includes(ele.name) === 0) {
P.createEntry({
name: ele.name,
min: ele.min,
max: ele.max
})
}
// remove assignment if there is assignment to this event that is now phantom event
ele.groups.forEach(e => {
let MindTemp = M.findIndex(m => m.name === e)
if(M[MindTemp].assignment === S.findIndex(s=>s.name === ele.name)) {
M[MindTemp].assignment = -1;
}
})
}
}
})
}
}
//Update list LL if there was no assignment
if(M[Mind].assignment === -1) {
let gInd = grp.findIndex(g => g.name === u.name)
LL = updateFun(LL,grp,gInd)
}
}
}
return M
}