add everything
This commit is contained in:
251
js/content.js
Normal file
251
js/content.js
Normal file
@@ -0,0 +1,251 @@
|
||||
import { round, score } from './score.js';
|
||||
import { resetList } from './pages/List.js';
|
||||
import { resetLeaderboard } from './pages/Leaderboard.js';
|
||||
import { resetPacks } from './pages/ListPacks.js';
|
||||
import { store } from './main.js';
|
||||
|
||||
/**
|
||||
* Path to directory containing `_list.json` and all levels
|
||||
*/
|
||||
const dir = '/data';
|
||||
var theList = "dl";
|
||||
|
||||
|
||||
// Thing at the beginning of the file name to signify that the level is pending
|
||||
const pendingMark = "(u)_";
|
||||
|
||||
export async function fetchList() {
|
||||
const listResult = await fetch(`${dir}/${theList}/_list.json`);
|
||||
const packResult = await fetch(`${dir}/${theList}/_packlist.json`);
|
||||
|
||||
try {
|
||||
const list = await listResult.json();
|
||||
const packsList = await packResult.json();
|
||||
|
||||
// Create a lookup dictionary for ranks
|
||||
const ranksEntries = list
|
||||
.filter((path) => !path.startsWith(pendingMark))
|
||||
.map((path, index) => [path, index + 1]);
|
||||
const ranks = Object.fromEntries(ranksEntries);
|
||||
|
||||
return await Promise.all(
|
||||
list.map(async (path) => {
|
||||
const rank = ranks[path] || null;
|
||||
try {
|
||||
const levelResult = await fetch(`${dir}/${theList}/${path.startsWith(pendingMark) ? path.substring(4) : path}.json`);
|
||||
const level = await levelResult.json();
|
||||
let packs = packsList.filter((x) =>
|
||||
x.levels.includes(path)
|
||||
);
|
||||
let enjoymentSum = 0;
|
||||
for(let i = 0; i < level.records.length; i++){
|
||||
enjoymentSum += level.records[i].enjoyment;
|
||||
}
|
||||
return [
|
||||
null,
|
||||
rank,
|
||||
{
|
||||
...level,
|
||||
rank,
|
||||
packs,
|
||||
path,
|
||||
records: level.records.sort(
|
||||
(a, b) => b.percent - a.percent,
|
||||
),
|
||||
enjoyment: round((level.verifierEnjoyment + enjoymentSum)/(level.records.length + 1)),
|
||||
},
|
||||
null,
|
||||
];
|
||||
} catch {
|
||||
console.error(`Failed to load level #${rank} ${path}.`);
|
||||
return [path, rank, null];
|
||||
}
|
||||
}),
|
||||
);
|
||||
} catch {
|
||||
console.error(`Failed to load list.`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchEditors() {
|
||||
try {
|
||||
const editorsResults = await fetch(`${dir}/_editors.json`);
|
||||
const editors = await editorsResults.json();
|
||||
return editors;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchLeaderboard() {
|
||||
const list = await fetchList();
|
||||
const packResult = await (await fetch(`${dir}/${theList}/_packlist.json`)).json();
|
||||
const scoreMap = {};
|
||||
const errs = [];
|
||||
|
||||
if (list === null) {
|
||||
return [null, ["Failed to load list."]];
|
||||
}
|
||||
|
||||
list.forEach(([err, rank, level]) => {
|
||||
if (err) {
|
||||
errs.push(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rank === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verification
|
||||
const verifier = Object.keys(scoreMap).find(
|
||||
(u) => u.toLowerCase() === level.verifier.toLowerCase(),
|
||||
) || level.verifier;
|
||||
scoreMap[verifier] ??= {
|
||||
verified: [],
|
||||
completed: [],
|
||||
progressed: [],
|
||||
packs: [],
|
||||
};
|
||||
const { verified } = scoreMap[verifier];
|
||||
verified.push({
|
||||
rank: rank,
|
||||
level: level.name,
|
||||
score: score(rank, 100, level.percentToQualify) * 1.0,
|
||||
link: level.verification,
|
||||
path: level.path
|
||||
});
|
||||
|
||||
// Records
|
||||
level.records.forEach((record, index) => {
|
||||
const user = Object.keys(scoreMap).find(
|
||||
(u) => u.toLowerCase() === record.user.toLowerCase(),
|
||||
) || record.user;
|
||||
scoreMap[user] ??= {
|
||||
verified: [],
|
||||
completed: [],
|
||||
progressed: [],
|
||||
packs: [],
|
||||
path: level.path
|
||||
};
|
||||
const { completed, progressed } = scoreMap[user];
|
||||
if (record.percent === 100) {
|
||||
completed.push({
|
||||
rank: rank,
|
||||
level: level.name,
|
||||
score:
|
||||
index < 2
|
||||
? score(rank, 100, level.percentToQualify) * 1.0
|
||||
: score(rank, 100, level.percentToQualify),
|
||||
link: record.link,
|
||||
path: level.path,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
progressed.push({
|
||||
rank: rank,
|
||||
level: level.name,
|
||||
percent: record.percent,
|
||||
score: score(rank, record.percent, level.percentToQualify),
|
||||
link: record.link,
|
||||
path: level.path
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
for (let user of Object.entries(scoreMap)) {
|
||||
let levels = [...user[1]["verified"], ...user[1]["completed"]].map(
|
||||
(x) => x["path"]
|
||||
);
|
||||
|
||||
for (let pack of packResult) {
|
||||
if (pack.levels.every((e1) => levels.includes(e1))) {
|
||||
user[1]["packs"].push(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap in extra Object containing the user and total score
|
||||
const res = Object.entries(scoreMap).map(([user, scores]) => {
|
||||
const { verified, completed, progressed } = scores;
|
||||
const total = [verified, completed, progressed]
|
||||
.flat()
|
||||
.reduce((prev, cur) => prev + cur.score, 0);
|
||||
|
||||
return {
|
||||
user,
|
||||
total: round(total),
|
||||
...scores,
|
||||
};
|
||||
});
|
||||
|
||||
// Sort by total score
|
||||
console.log(scoreMap)
|
||||
return [res.sort((a, b) => b.total - a.total), errs];
|
||||
}
|
||||
|
||||
export async function fetchPacks() {
|
||||
try {
|
||||
const packResult = await fetch(`${dir}/${theList}/_packlist.json`);
|
||||
const packsList = await packResult.json();
|
||||
return packsList;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchPackLevels(packname) {
|
||||
const packResult = await fetch(`${dir}/${theList}/_packlist.json`);
|
||||
const packsList = await packResult.json();
|
||||
const selectedPack = await packsList.find((pack) => pack.name == packname);
|
||||
const listResult = await await fetch(`${dir}/${theList}/_list.json`);
|
||||
try {
|
||||
const list = await listResult.json();
|
||||
|
||||
// Create a lookup dictionary for ranks
|
||||
const ranksEntries = list
|
||||
.filter((path) => !path.startsWith(pendingMark))
|
||||
.map((path, index) => [path, index + 1]);
|
||||
const ranks = Object.fromEntries(ranksEntries);
|
||||
|
||||
return await Promise.all(
|
||||
selectedPack.levels.map(async (path, rank) => {
|
||||
const levelResult = await fetch(`${dir}/${theList}/${path}.json`);
|
||||
try {
|
||||
const level = await levelResult.json();
|
||||
const listRank = ranks[path] || null;
|
||||
return [
|
||||
{
|
||||
level,
|
||||
listRank,
|
||||
path,
|
||||
records: level.records.sort(
|
||||
(a, b) => b.percent - a.percent,
|
||||
),
|
||||
},
|
||||
null,
|
||||
];
|
||||
} catch {
|
||||
console.error(`Failed to load level #${rank} ${path} (${packname}).`);
|
||||
return [path, rank, null];
|
||||
}
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(`Failed to load packs.`, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function changeList(){
|
||||
var newList = document.getElementById("list_dropdown").value;
|
||||
console.log("theList: " + theList.toString() + ", dropdown value: " + document.getElementById("list_dropdown").value.toString());
|
||||
store.listType = newList;
|
||||
|
||||
theList = newList;
|
||||
resetList();
|
||||
resetLeaderboard();
|
||||
resetPacks();
|
||||
}
|
||||
Reference in New Issue
Block a user