68 lines
1.5 KiB
JavaScript
68 lines
1.5 KiB
JavaScript
export function paretoFilter(movies, people, ratings) {
|
|
return movies.filter((movieA) => {
|
|
return !movies.some((movieB) => {
|
|
if (movieA === movieB) {
|
|
return false;
|
|
}
|
|
let allAtLeastAsGood = true;
|
|
let strictlyBetter = false;
|
|
for (const person of people) {
|
|
const a = ratings[person][movieA];
|
|
const b = ratings[person][movieB];
|
|
if (b < a) {
|
|
allAtLeastAsGood = false;
|
|
break;
|
|
}
|
|
if (b > a) {
|
|
strictlyBetter = true;
|
|
}
|
|
}
|
|
return allAtLeastAsGood && strictlyBetter;
|
|
});
|
|
});
|
|
}
|
|
|
|
export function nashScore(movie, people, ratings) {
|
|
let product = 1;
|
|
for (const person of people) {
|
|
product *= ratings[person][movie] + 1;
|
|
}
|
|
return product;
|
|
}
|
|
|
|
export function averageScore(movie, people, ratings) {
|
|
let total = 0;
|
|
for (const person of people) {
|
|
total += ratings[person][movie];
|
|
}
|
|
return total / people.length;
|
|
}
|
|
|
|
export function decideMovie({ movies, people, ratings }) {
|
|
if (movies.length < 1 || people.length < 1) {
|
|
throw new Error("Need at least one movie and one person");
|
|
}
|
|
const remaining = paretoFilter(movies, people, ratings);
|
|
const scored = remaining.map((movie) => {
|
|
return {
|
|
movie,
|
|
nash: nashScore(movie, people, ratings),
|
|
avg: averageScore(movie, people, ratings),
|
|
};
|
|
});
|
|
scored.sort((a, b) => {
|
|
if (b.nash !== a.nash) {
|
|
return b.nash - a.nash;
|
|
}
|
|
if (b.avg !== a.avg) {
|
|
return b.avg - a.avg;
|
|
}
|
|
return a.movie.localeCompare(b.movie);
|
|
});
|
|
return {
|
|
winner: scored[0],
|
|
remaining,
|
|
ranking: scored,
|
|
};
|
|
}
|