more abtmtr.link bullshit
This commit is contained in:
parent
a081c6a44b
commit
faaf3d1b13
6 changed files with 711 additions and 1 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,4 +5,5 @@ output/
|
|||
|
||||
# the world isn't ready yet
|
||||
views/projects/item/wavetapper
|
||||
views/projects/item/dice_2
|
||||
views/projects/item/dice_2
|
||||
views/projects/item/text
|
141
views/projects/item/fediverse-madness/index.html
Normal file
141
views/projects/item/fediverse-madness/index.html
Normal file
|
@ -0,0 +1,141 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Fediverse Madness - abtmtr.link</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/myapp.css" />
|
||||
<link rel="stylesheet" href="./style.css" />
|
||||
<style>
|
||||
:root {
|
||||
--base-color: 60, 40%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section>
|
||||
<h1>Fediverse Madness</h1>
|
||||
<p>Competitive bracket-based comparisons of Fediverse users.</p>
|
||||
</section>
|
||||
<section id="accessibility" hidden></section>
|
||||
</header>
|
||||
<main>
|
||||
<section id="whoami">
|
||||
<h3>Who are you?</h3>
|
||||
<span class="userinputbox">
|
||||
<span>@</span>
|
||||
<input type="text" name="user" id="user" class="userinstance" />
|
||||
<span>@</span>
|
||||
<input type="text" name="instance" id="instance" class="userinstance" />
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<hr />
|
||||
<button id="submitwhoami_followers">Play (Followers)</button>
|
||||
<button id="submitwhoami_following">Play (Following)</button>
|
||||
<p id="errorwhoami"></p>
|
||||
</section>
|
||||
<section id="followers" hidden>
|
||||
<h3>Followers list</h3>
|
||||
<p id="loadingfollowers">Retrieving followers... Please wait.</p>
|
||||
<table id="listfollowers" hidden>
|
||||
<tr id="listfollowersvalues">
|
||||
<th>S.</th>
|
||||
<th>Av.</th>
|
||||
<th>User</th>
|
||||
<th>Handle</th>
|
||||
</tr>
|
||||
</table>
|
||||
<div>
|
||||
<button id="selectallfollowers">Select all</button>
|
||||
<button id="selectnofollowers">Select none</button>
|
||||
<button id="selectrandomfollowers">Select random</button>
|
||||
<button id="deselectrandomfollowers">Deselect random</button>
|
||||
</div>
|
||||
<button id="morefollowers">Load more</button>
|
||||
<button id="submitfollowers" disabled>Done</button>
|
||||
</section>
|
||||
<section id="following" hidden>
|
||||
<h3>Following list</h3>
|
||||
<p id="loadingfollowing">Retrieving following... Please wait.</p>
|
||||
<table id="listfollowing" hidden>
|
||||
<tr id="listfollowingvalues">
|
||||
<th>S.</th>
|
||||
<th>Av.</th>
|
||||
<th>User</th>
|
||||
<th>Handle</th>
|
||||
</tr>
|
||||
</table>
|
||||
<div>
|
||||
<button id="selectallfollowing">Select all</button>
|
||||
<button id="selectnofollowing">Select none</button>
|
||||
<button id="selectrandomfollowing">Select random</button>
|
||||
<button id="deselectrandomfollowing">Deselect random</button>
|
||||
</div>
|
||||
<button id="morefollowing">Load more</button>
|
||||
<button id="submitfollowing" disabled>Done</button>
|
||||
</section>
|
||||
<section id="game" hidden>
|
||||
<h3>Fight!</h3>
|
||||
<p id="gameBracketLevel">Bracket Level ...</p>
|
||||
<p id="gameBracketFight">Round ...</p>
|
||||
<div class="gridUsersVert">
|
||||
<div class="gridUser" id="gameUserOne">
|
||||
<img src="" id="gameUserOneImage" width="128" height="128" />
|
||||
<div>
|
||||
<h3 id="gameUserOneName"></h3>
|
||||
<p id="gameUserOneId"></p>
|
||||
<p id="gameUserOneNote"></p>
|
||||
<table id="gameUserOneFields">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gridUser" id="gameUserTwo">
|
||||
<img src="" id="gameUserTwoImage" width="128" height="128" />
|
||||
<div>
|
||||
<h3 id="gameUserTwoName"></h3>
|
||||
<p id="gameUserTwoId"></p>
|
||||
<p id="gameUserTwoNote"></p>
|
||||
<table id="gameUserTwoFields">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<button id="gameSubmitLeft" disabled>Please wait...</button>
|
||||
<button id="gameSubmitRight" disabled>Please wait...</button>
|
||||
</section>
|
||||
<section id="winner" hidden>
|
||||
<h3>Winner</h3>
|
||||
<p id="winnermessage">Congratulations, ...</p>
|
||||
<div class="gridUser" id="winnerUser">
|
||||
<img src="" id="winnerUserImage" width="128" height="128" />
|
||||
<div>
|
||||
<h3 id="winnerUserName"></h3>
|
||||
<p id="winnerUserId"></p>
|
||||
<p id="winnerUserNote"></p>
|
||||
<table id="winnerUserFields">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Bracket</h3>
|
||||
<div class="flexUsersVert" id="winnerusers">
|
||||
</div>
|
||||
<hr />
|
||||
<button id="winnerPlayAgain">Play Again</button>
|
||||
</section>
|
||||
</main>
|
||||
<section id="accessibility" hidden></section>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
<script>
|
||||
let game = {
|
||||
USER_ID: "Abg3KCIlHi1Q2Gzx0y",
|
||||
INSTANCE: "local.abtmtr.link"
|
||||
};
|
||||
</script>
|
||||
<script src="./script.js"></script>
|
||||
<script src="./scripts/game.js"></script>
|
||||
</body>
|
||||
</html>
|
0
views/projects/item/fediverse-madness/script.js
Normal file
0
views/projects/item/fediverse-madness/script.js
Normal file
476
views/projects/item/fediverse-madness/scripts/game.js
Normal file
476
views/projects/item/fediverse-madness/scripts/game.js
Normal file
|
@ -0,0 +1,476 @@
|
|||
function escapeHtml(unsafe)
|
||||
{
|
||||
return unsafe
|
||||
.replace(/<\/?script\/?>/g, "")
|
||||
.replace(/<\/?img\/?>/g, "")
|
||||
.replace(/<\/?iframe\/?>/g, "")
|
||||
.replace(/<\/?xml\/?>/g, "")
|
||||
.replace(/<\/?audio\/?>/g, "")
|
||||
.replace(/<\/?video\/?>/g, "")
|
||||
.replace(/<\/?object\/?>/g, "");
|
||||
}
|
||||
|
||||
const el_id_user = document.querySelector("#user");
|
||||
const el_id_instance = document.querySelector("#instance");
|
||||
const el_id_whoami = document.querySelector("#whoami");
|
||||
const el_id_submitwhoamiFollowers = document.querySelector("#submitwhoami_followers");
|
||||
const el_id_submitwhoamiFollowing = document.querySelector("#submitwhoami_following");
|
||||
const el_id_errorwhoami = document.querySelector("#errorwhoami");
|
||||
let gamemodeFollowers;
|
||||
|
||||
el_id_user.addEventListener("input", (e) => {
|
||||
console.log(e);
|
||||
// User types @ Chrome autofill
|
||||
if (e.data === "@" || e.data === undefined) {
|
||||
el_id_user.value =
|
||||
el_id_user.value.replace(/@/gim, "");
|
||||
el_id_instance.focus();
|
||||
}
|
||||
})
|
||||
|
||||
async function verify() {
|
||||
const username = el_id_user.value.replace(/[^a-z0-9_]/gim, "");
|
||||
const instance = el_id_instance.value.replace(/@/gim, "");
|
||||
el_id_user.value = username;
|
||||
el_id_instance.value = instance;
|
||||
if (username.length < 1) return null;
|
||||
if (instance.length < 1) return null;
|
||||
let user_req;
|
||||
try {
|
||||
user_req = await fetch(`https://${instance}/api/v1/accounts/lookup?acct=${username}`);
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
const user_json = await user_req.json();
|
||||
if (user_req.ok) return {
|
||||
USER_ID: user_json.id,
|
||||
INSTANCE: instance
|
||||
};
|
||||
else return null;
|
||||
}
|
||||
|
||||
el_id_submitwhoamiFollowers.addEventListener("click", async (e) => {
|
||||
el_id_errorwhoami.innerHTML = "";
|
||||
const result = await verify();
|
||||
if (result == null) {
|
||||
el_id_errorwhoami.innerHTML = "Invalid user!";
|
||||
return false;
|
||||
}
|
||||
game = {
|
||||
...game,
|
||||
...result
|
||||
};
|
||||
|
||||
gamemodeFollowers = true;
|
||||
getFollowers();
|
||||
})
|
||||
|
||||
el_id_submitwhoamiFollowing.addEventListener("click", async (e) => {
|
||||
el_id_errorwhoami.innerHTML = "";
|
||||
const result = await verify();
|
||||
if (result == null) {
|
||||
el_id_errorwhoami.innerHTML = "Invalid user!";
|
||||
return false;
|
||||
}
|
||||
game = {
|
||||
...game,
|
||||
...result
|
||||
};
|
||||
|
||||
gamemodeFollowers = false;
|
||||
getFollowing();
|
||||
})
|
||||
|
||||
// Followers
|
||||
|
||||
const el_id_followers = document.querySelector("#followers");
|
||||
const el_id_loadingfollowers = document.querySelector("#loadingfollowers");
|
||||
const el_id_listfollowers = document.querySelector("#listfollowers");
|
||||
const el_id_listfollowersvalues = document.querySelector("#listfollowersvalues");
|
||||
const el_id_selectallfollowers = document.querySelector("#selectallfollowers");
|
||||
const el_id_selectrandomfollowers = document.querySelector("#selectrandomfollowers");
|
||||
const el_id_deselectrandomfollowers = document.querySelector("#deselectrandomfollowers");
|
||||
const el_id_selectnofollowers = document.querySelector("#selectnofollowers");
|
||||
const el_id_morefollowers = document.querySelector("#morefollowers");
|
||||
const el_id_submitfollowers = document.querySelector("#submitfollowers");
|
||||
let selectboxes = [];
|
||||
let userList = [];
|
||||
let lastId = "";
|
||||
let selectedUsers = [];
|
||||
|
||||
function renderNameHTML(name, user) {
|
||||
return escapeHtml(name).replace(/:([a-z0-9_-]+?):/gim, (m, p1) => {
|
||||
const emoji = user.emojis.find(x => x.shortcode == p1);
|
||||
if (emoji == null) return null;
|
||||
return `<img src="${emoji.url}" width="16" height="16" title=":${emoji.shortcode}:" />`;
|
||||
});
|
||||
}
|
||||
|
||||
async function getFollowers(dontLoadNew = false) {
|
||||
el_id_whoami.hidden = true;
|
||||
el_id_followers.hidden = false;
|
||||
el_id_submitfollowers.disabled = true;
|
||||
el_id_morefollowers.disabled = true;
|
||||
let res;
|
||||
let out;
|
||||
if (!dontLoadNew) {
|
||||
el_id_loadingfollowers.innerHTML = `Retrieving followers... Please wait.`;
|
||||
res = await fetch(`https://${game.INSTANCE}/api/v1/accounts/${game.USER_ID}/followers?limit=68${lastId.length > 0 ? `&max_id=${lastId}` : ""}`);
|
||||
out = await res.json();
|
||||
}
|
||||
el_id_submitfollowers.disabled = false;
|
||||
el_id_morefollowers.disabled = false;
|
||||
if (dontLoadNew) return false;
|
||||
if (out.length < 1) {
|
||||
el_id_loadingfollowers.innerHTML = `No followers found.`;
|
||||
return false;
|
||||
}
|
||||
el_id_listfollowers.hidden = false;
|
||||
el_id_listfollowers.innerHTML += out.reduce((pv, cuser) => {
|
||||
return pv + `<tr>
|
||||
<td><input type="checkbox" class="follower_checkbox" checked /></td>
|
||||
<td><img src="${cuser.avatar}" width="32" height="32" /></td>
|
||||
<td class="followers_namelabel">
|
||||
<a href="${cuser.url}" target="_blank">
|
||||
${renderNameHTML(cuser.display_name, cuser)}
|
||||
</a>
|
||||
</td>
|
||||
<td class="followers_namelabel">@${cuser.fqn}</td>
|
||||
</tr>`
|
||||
}, "");
|
||||
userList.push(...out.map(user => ({
|
||||
fqn: user.fqn,
|
||||
avatar: user.avatar,
|
||||
bot: user.bot,
|
||||
created_at: user.created_at,
|
||||
display_name: user.display_name,
|
||||
emojis: user.emojis,
|
||||
fields: user.fields,
|
||||
id: user.id,
|
||||
note: user.note,
|
||||
username: user.url,
|
||||
username: user.username
|
||||
})));
|
||||
lastId = userList.at(-1).id;
|
||||
selectboxes = Array.from(el_id_listfollowers.querySelectorAll(".follower_checkbox"));
|
||||
selectboxes.forEach(x => x.addEventListener("change", checkSelectedAmtFollowers));
|
||||
checkSelectedAmtFollowers();
|
||||
}
|
||||
|
||||
el_id_selectallfollowers.addEventListener("click", () => {
|
||||
selectboxes.forEach(x => x.checked = true);
|
||||
checkSelectedAmtFollowers();
|
||||
})
|
||||
|
||||
el_id_selectrandomfollowers.addEventListener("click", () => {
|
||||
const unselectedPick = selectboxes.filter(x => !x.checked);
|
||||
const selected = unselectedPick[Math.floor(Math.random() * (unselectedPick.length - 1))];
|
||||
if (selected == null) return;
|
||||
selected.checked = true;
|
||||
checkSelectedAmtFollowers();
|
||||
})
|
||||
|
||||
el_id_deselectrandomfollowers.addEventListener("click", () => {
|
||||
const selectedPick = selectboxes.filter(x => x.checked);
|
||||
const selected = selectedPick[Math.floor(Math.random() * (selectedPick.length - 1))];
|
||||
if (selected == null) return;
|
||||
selected.checked = false;
|
||||
checkSelectedAmtFollowers();
|
||||
})
|
||||
|
||||
el_id_selectnofollowers.addEventListener("click", () => {
|
||||
selectboxes.forEach(x => x.checked = false);
|
||||
checkSelectedAmtFollowers();
|
||||
})
|
||||
|
||||
el_id_morefollowers.addEventListener("click", () => getFollowers());
|
||||
|
||||
el_id_submitfollowers.addEventListener("click", () => {
|
||||
console.log(selectedUsers);
|
||||
selectboxes.forEach(({checked}, i) => {
|
||||
if (checked) selectedUsers.push(userList.at(i));
|
||||
});
|
||||
if (selectedUsers.length < 2) {
|
||||
selectedUsers = [];
|
||||
el_id_loadingfollowers.innerHTML = `Selected user count is less than 2! (${selectboxes.filter(x => x.checked).length} selected)`;
|
||||
return;
|
||||
}
|
||||
sortSelectedUsers();
|
||||
})
|
||||
|
||||
function checkSelectedAmtFollowers() {
|
||||
el_id_loadingfollowers.innerHTML = `${selectboxes.filter(x => x.checked).length} selected`;
|
||||
}
|
||||
|
||||
// Following
|
||||
|
||||
const el_id_following = document.querySelector("#following");
|
||||
const el_id_loadingfollowing = document.querySelector("#loadingfollowing");
|
||||
const el_id_listfollowing = document.querySelector("#listfollowing");
|
||||
const el_id_listfollowingvalues = document.querySelector("#listfollowingvalues");
|
||||
const el_id_selectallfollowing = document.querySelector("#selectallfollowing");
|
||||
const el_id_selectrandomfollowing = document.querySelector("#selectrandomfollowing");
|
||||
const el_id_deselectrandomfollowing = document.querySelector("#deselectrandomfollowing");
|
||||
const el_id_selectnofollowing = document.querySelector("#selectnofollowing");
|
||||
const el_id_morefollowing = document.querySelector("#morefollowing");
|
||||
const el_id_submitfollowing = document.querySelector("#submitfollowing");
|
||||
|
||||
async function getFollowing(dontLoadNew = false) {
|
||||
el_id_whoami.hidden = true;
|
||||
el_id_following.hidden = false;
|
||||
el_id_submitfollowing.disabled = true;
|
||||
el_id_morefollowing.disabled = true;
|
||||
let res;
|
||||
let out;
|
||||
if (!dontLoadNew) {
|
||||
el_id_loadingfollowing.innerHTML = `Retrieving following... Please wait.`;
|
||||
res = await fetch(`https://${game.INSTANCE}/api/v1/accounts/${game.USER_ID}/following?limit=68${lastId.length > 0 ? `&max_id=${lastId}` : ""}`);
|
||||
out = await res.json();
|
||||
}
|
||||
el_id_submitfollowing.disabled = false;
|
||||
el_id_morefollowing.disabled = false;
|
||||
if (dontLoadNew) return false;
|
||||
if (out.length < 1) {
|
||||
el_id_loadingfollowing.innerHTML = `No following found.`;
|
||||
return false;
|
||||
}
|
||||
el_id_listfollowing.hidden = false;
|
||||
el_id_listfollowing.innerHTML += out.reduce((pv, cuser) => {
|
||||
return pv + `<tr>
|
||||
<td><input type="checkbox" class="follower_checkbox" checked /></td>
|
||||
<td><img src="${cuser.avatar}" width="32" height="32" /></td>
|
||||
<td class="following_namelabel">
|
||||
<a href="${cuser.url}" target="_blank">
|
||||
${renderNameHTML(cuser.display_name, cuser)}
|
||||
</a>
|
||||
</td>
|
||||
<td class="following_namelabel">@${cuser.fqn}</td>
|
||||
</tr>`
|
||||
}, "");
|
||||
userList.push(...out.map(user => ({
|
||||
fqn: user.fqn,
|
||||
avatar: user.avatar,
|
||||
bot: user.bot,
|
||||
created_at: user.created_at,
|
||||
display_name: user.display_name,
|
||||
emojis: user.emojis,
|
||||
fields: user.fields,
|
||||
id: user.id,
|
||||
note: user.note,
|
||||
username: user.url,
|
||||
username: user.username
|
||||
})));
|
||||
lastId = userList.at(-1).id;
|
||||
selectboxes = Array.from(el_id_listfollowing.querySelectorAll(".follower_checkbox"));
|
||||
selectboxes.forEach(x => x.addEventListener("change", checkSelectedAmtFollowing));
|
||||
checkSelectedAmtFollowing();
|
||||
}
|
||||
|
||||
el_id_selectallfollowing.addEventListener("click", () => {
|
||||
selectboxes.forEach(x => x.checked = true);
|
||||
checkSelectedAmtFollowing();
|
||||
})
|
||||
|
||||
el_id_selectrandomfollowing.addEventListener("click", () => {
|
||||
const unselectedPick = selectboxes.filter(x => !x.checked);
|
||||
const selected = unselectedPick[Math.floor(Math.random() * (unselectedPick.length - 1))];
|
||||
if (selected == null) return;
|
||||
selected.checked = true;
|
||||
checkSelectedAmtFollowing();
|
||||
})
|
||||
|
||||
el_id_deselectrandomfollowing.addEventListener("click", () => {
|
||||
const selectedPick = selectboxes.filter(x => x.checked);
|
||||
const selected = selectedPick[Math.floor(Math.random() * (selectedPick.length - 1))];
|
||||
if (selected == null) return;
|
||||
selected.checked = false;
|
||||
checkSelectedAmtFollowing();
|
||||
})
|
||||
|
||||
el_id_selectnofollowing.addEventListener("click", () => {
|
||||
selectboxes.forEach(x => x.checked = false);
|
||||
checkSelectedAmtFollowing();
|
||||
})
|
||||
|
||||
el_id_morefollowing.addEventListener("click", () => getFollowing());
|
||||
|
||||
el_id_submitfollowing.addEventListener("click", () => {
|
||||
console.log(selectedUsers);
|
||||
selectboxes.forEach(({checked}, i) => {
|
||||
if (checked) selectedUsers.push(userList.at(i));
|
||||
});
|
||||
if (selectedUsers.length < 2) {
|
||||
selectedUsers = [];
|
||||
el_id_loadingfollowing.innerHTML = `Selected user count is less than 2! (${selectboxes.filter(x => x.checked).length} selected)`;
|
||||
return;
|
||||
}
|
||||
sortSelectedUsers();
|
||||
})
|
||||
|
||||
function checkSelectedAmtFollowing() {
|
||||
el_id_loadingfollowing.innerHTML = `${selectboxes.filter(x => x.checked).length} selected`;
|
||||
}
|
||||
|
||||
// Brackets
|
||||
|
||||
function shuf(array) {
|
||||
var count = array.length,
|
||||
randomnumber,
|
||||
temp;
|
||||
while (count) {
|
||||
randomnumber = Math.random() * count-- | 0;
|
||||
temp = array[count];
|
||||
array[count] = array[randomnumber];
|
||||
array[randomnumber] = temp
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function chunk(arr, size) {
|
||||
return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
|
||||
arr.slice(i * size, i * size + size)
|
||||
);
|
||||
}
|
||||
|
||||
const el_id_game = document.querySelector("#game");
|
||||
const el_id_gameUserOne = document.querySelector("#gameUserOne");
|
||||
const el_id_gameUserOneImage = document.querySelector("#gameUserOneImage");
|
||||
const el_id_gameUserOneName = document.querySelector("#gameUserOneName");
|
||||
const el_id_gameUserOneId = document.querySelector("#gameUserOneId");
|
||||
const el_id_gameUserOneNote = document.querySelector("#gameUserOneNote");
|
||||
const el_id_gameUserOneFields = document.querySelector("#gameUserOneFields");
|
||||
const el_id_gameUserTwo = document.querySelector("#gameUserTwo");
|
||||
const el_id_gameUserTwoImage = document.querySelector("#gameUserTwoImage");
|
||||
const el_id_gameUserTwoName = document.querySelector("#gameUserTwoName");
|
||||
const el_id_gameUserTwoId = document.querySelector("#gameUserTwoId");
|
||||
const el_id_gameUserTwoNote = document.querySelector("#gameUserTwoNote");
|
||||
const el_id_gameUserTwoFields = document.querySelector("#gameUserTwoFields");
|
||||
const el_id_gameSubmitLeft = document.querySelector("#gameSubmitLeft");
|
||||
const el_id_gameSubmitRight = document.querySelector("#gameSubmitRight");
|
||||
const el_id_gameBracketLevel = document.querySelector("#gameBracketLevel");
|
||||
const el_id_gameBracketFight = document.querySelector("#gameBracketFight");
|
||||
|
||||
let state = [];
|
||||
let curDepth = 0;
|
||||
let curFight = 0;
|
||||
|
||||
function sortSelectedUsers() {
|
||||
if (gamemodeFollowers)
|
||||
el_id_followers.hidden = true;
|
||||
else
|
||||
el_id_following.hidden = true;
|
||||
el_id_game.hidden = false;
|
||||
state.push(chunk(shuf(selectedUsers), 2));
|
||||
state.push([]);
|
||||
prepareGameStage();
|
||||
}
|
||||
|
||||
function prepareGameStage() {
|
||||
el_id_gameSubmitLeft.disabled = true;
|
||||
el_id_gameSubmitRight.disabled = true;
|
||||
el_id_gameSubmitLeft.innerHTML = "Please wait...";
|
||||
el_id_gameSubmitRight.innerHTML = "Please wait...";
|
||||
el_id_gameUserOneImage.src = "";
|
||||
el_id_gameUserTwoImage.src = "";
|
||||
el_id_gameBracketLevel.innerHTML = "Bracket Level " + (curDepth + 1);
|
||||
el_id_gameBracketFight.innerHTML = "Round " + (curFight + 1);
|
||||
const curSubStage = state[curDepth][curFight];
|
||||
el_id_gameUserOneImage.src = curSubStage[0].avatar;
|
||||
el_id_gameUserOneName.innerHTML = renderNameHTML(escapeHtml(curSubStage[0].display_name), curSubStage[0]);
|
||||
el_id_gameUserOneId.innerHTML = "@" + curSubStage[0].fqn;
|
||||
el_id_gameUserOneNote.innerHTML = escapeHtml(curSubStage[0].note);
|
||||
el_id_gameUserOneFields.innerHTML = curSubStage[0].fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||
el_id_gameUserTwoImage.src = curSubStage[1].avatar;
|
||||
el_id_gameUserTwoName.innerHTML = renderNameHTML(escapeHtml(curSubStage[1].display_name), curSubStage[1]);
|
||||
el_id_gameUserTwoId.innerHTML = "@" + curSubStage[1].fqn;
|
||||
el_id_gameUserTwoNote.innerHTML = escapeHtml(curSubStage[1].note);
|
||||
el_id_gameUserTwoFields.innerHTML = curSubStage[1].fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||
el_id_gameSubmitLeft.disabled = false;
|
||||
el_id_gameSubmitRight.disabled = false;
|
||||
el_id_gameSubmitLeft.innerHTML = "Pick " + "@" + curSubStage[0].fqn;
|
||||
el_id_gameSubmitRight.innerHTML = "Pick " + "@" + curSubStage[1].fqn;
|
||||
}
|
||||
|
||||
function addNewThingy(thingy) {
|
||||
if (state[curDepth + 1] == null) state.push([]);
|
||||
if (curFight % 2 == 0)
|
||||
state[curDepth + 1][Math.floor(curFight / 2)] = [];
|
||||
state[curDepth + 1][Math.floor(curFight / 2)].push(thingy);
|
||||
}
|
||||
|
||||
el_id_gameSubmitLeft.addEventListener("click", () => {
|
||||
addNewThingy(state[curDepth][curFight][0]);
|
||||
nextStage();
|
||||
})
|
||||
|
||||
el_id_gameSubmitRight.addEventListener("click", () => {
|
||||
addNewThingy(state[curDepth][curFight][1]);
|
||||
nextStage();
|
||||
})
|
||||
|
||||
function nextStage() {
|
||||
if (curFight >= state[curDepth].length - 1) {
|
||||
curDepth++;
|
||||
curFight = 0;
|
||||
} else curFight++;
|
||||
console.log(state, curFight, curDepth);
|
||||
if (state[curDepth][curFight].length < 2) {
|
||||
if (state[curDepth].length < 2) {
|
||||
endGame();
|
||||
return;
|
||||
}
|
||||
addNewThingy(state[curDepth][curFight][0]);
|
||||
curDepth++;
|
||||
curFight = 0;
|
||||
}
|
||||
prepareGameStage();
|
||||
}
|
||||
|
||||
// End
|
||||
|
||||
const el_id_winner = document.querySelector("#winner");
|
||||
const el_id_winnerUser = document.querySelector("#winnerUser");
|
||||
const el_id_winnerUserImage = document.querySelector("#winnerUserImage");
|
||||
const el_id_winnerUserName = document.querySelector("#winnerUserName");
|
||||
const el_id_winnerUserId = document.querySelector("#winnerUserId");
|
||||
const el_id_winnerUserNote = document.querySelector("#winnerUserNote");
|
||||
const el_id_winnerUserFields = document.querySelector("#winnerUserFields");
|
||||
const el_id_winnermessage = document.querySelector("#winnermessage");
|
||||
const el_id_winnerusers = document.querySelector("#winnerusers");
|
||||
const el_id_winnerPlayAgain = document.querySelector("#winnerPlayAgain");
|
||||
|
||||
function endGame() {
|
||||
el_id_game.hidden = true;
|
||||
el_id_winner.hidden = false;
|
||||
const winningPlayer = state[curDepth][curFight][0];
|
||||
el_id_winnerUserImage.src = winningPlayer.avatar;
|
||||
el_id_winnerUserName.innerHTML = renderNameHTML(escapeHtml(winningPlayer.display_name), winningPlayer);
|
||||
el_id_winnerUserId.innerHTML = "@" + winningPlayer.fqn;
|
||||
el_id_winnerUserNote.innerHTML = escapeHtml(winningPlayer.note);
|
||||
el_id_winnerUserFields.innerHTML = winningPlayer.fields.reduce((pv, fields) => pv + `<tr><td>${escapeHtml(fields.name)}</td><td>${escapeHtml(fields.value)}</td></tr>`, "");
|
||||
|
||||
el_id_winnermessage.innerHTML = `Congratulations, ${renderNameHTML(escapeHtml(winningPlayer.display_name), winningPlayer)}! You won the bracket!`;
|
||||
el_id_winnerusers.innerHTML = `<div>${state.reduce((pv, cs) => {
|
||||
return pv + `<div class="flexUser">${cs.reduce((pvus, cus) => {
|
||||
return pvus + cus.reduce((pvu, cu) => {
|
||||
return pvu + `<div class="flexUserUser">
|
||||
<img src="${cu.avatar}" width="64" height="64" />
|
||||
<h3>${renderNameHTML(escapeHtml(cu.display_name), cu)}</h3>
|
||||
<p>@${cu.fqn}</p>
|
||||
</div>`
|
||||
}, "")
|
||||
}, "")}</div>`
|
||||
}, "")}</div>`
|
||||
}
|
||||
|
||||
el_id_winnerPlayAgain.addEventListener("click", (x) => {
|
||||
el_id_winner.hidden = true;
|
||||
state = [];
|
||||
selectedUsers = [];
|
||||
curDepth = 0;
|
||||
curFight = 0;
|
||||
if (gamemodeFollowers)
|
||||
getFollowers(true);
|
||||
else
|
||||
getFollowing(true);
|
||||
})
|
78
views/projects/item/fediverse-madness/style.css
Normal file
78
views/projects/item/fediverse-madness/style.css
Normal file
|
@ -0,0 +1,78 @@
|
|||
.userinstance {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.userinputbox {
|
||||
border: var(--border-width) var(--border-style) var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
padding-inline: 0.25em;
|
||||
padding-block: 0.25em;
|
||||
}
|
||||
|
||||
.userinputbox * {
|
||||
vertical-align: 0%;
|
||||
}
|
||||
|
||||
#listfollowers, #listfollowing {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-height: 31.25em;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#listfollowers #listfollowersvalues,
|
||||
#listfollowing #listfollowingvalues {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.followers_namelabel,
|
||||
.following_namelabel {
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
.gridUser {
|
||||
display: grid;
|
||||
grid-template-columns: 128px auto;
|
||||
overflow: auto;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.gridUsersVert {
|
||||
display: grid;
|
||||
overflow: auto;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.flexUsersVert {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: safe center;
|
||||
overflow: auto;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.flexUser {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
width: 100%;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.flexUserUser {
|
||||
text-align: center;
|
||||
width: 256px;
|
||||
min-width: 256px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.flexUserUser * {
|
||||
word-wrap: break-word;
|
||||
}
|
|
@ -5,6 +5,20 @@
|
|||
"normalize": "#808080"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"name": "Fediverse Madness",
|
||||
"date": 1710804730000,
|
||||
"description": [
|
||||
"A March Madness style bracket-based competition for the entities on the Fediverse.",
|
||||
"Compate your friends! Have a meltdown-sized crisis over who you like more!",
|
||||
"This project will make you do it.",
|
||||
"SERIOUS TRIGGER WARNING: uncomfortable comparisons."
|
||||
],
|
||||
"url": "/projects/item/fediverse-madness/",
|
||||
"tags": [
|
||||
"normalize"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LastFMDownloader",
|
||||
"date": 1708382160000,
|
||||
|
|
Loading…
Reference in a new issue