Skip to content

Instantly share code, notes, and snippets.

@Sasquire
Last active July 10, 2019 04:20
Show Gist options
  • Save Sasquire/684ba83c22137e08a4b1f81a328b6f2f to your computer and use it in GitHub Desktop.
Save Sasquire/684ba83c22137e08a4b1f81a328b6f2f to your computer and use it in GitHub Desktop.
A quick something to compare posts with an elo rating to try and find what your favorite is.
// ==UserScript==
// @name e621 elo compare
// @namespace http://tampermonkey.net/
// @version 1.00001
// @description try to take over the world!
// @author Sasquire
// @match https://e621.net/extensions/post_elo
// @match http://e621.net/extensions/post_elo
// @grant GM_addStyle
// ==/UserScript==
const starting_elo = 1000;
const elo_k = 30;
// Clears the page
(() => {
function clear_node(node){
while(node.children.length > 0){
node.removeChild(node.children[0]);
}
}
function remove_toJSON(){
// This gave me a lot of greif. e621 changes the toJSON
// methods and creates not optimal JSON.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
delete Object.prototype.toJSON;
delete Date.prototype.toJSON;
delete String.prototype.toJSON;
delete Array.prototype.toJSON;
delete Number.prototype.toJSON;
// Kira I don't know what this did, but it gave me errors. So I removed it.
jQuery.event.dispatch = () => '';
}
clear_node(document.head);
clear_node(document.body);
remove_toJSON();
document.body.innerHTML = `
<div id="main">
<div id="header"><button id="export">Export</button></div>
<div id="leftpost"></div>
<div id="rightpost"></div>
</div>
`;
GM_addStyle(`
#main {
height: 100vh;
display: grid;
grid-template-columns: auto 20px auto;
grid-template-rows: 75px auto;
}
#header {
grid-column: 1 / 3;
grid-rows: 1 / 1;
}
#leftpost {
grid-column: 1 / 1;
grid-rows: 2 / 2;
}
#rightpost {
grid-column: 3 / 3;
grid-rows: 2 / 2;
}
#leftpost > *, #rightpost > * {
max-width: 90%;
max-height: 90%;
margin: auto;
align-self: center;
}
`);
})();
async function get_all_posts(query){
const posts = {}
for(let page = 1; true; page++){
const data = await get_search_results(query, page);
data.forEach(e => (e.elo = starting_elo));
data.forEach(e => (e.hit = 0));
data.forEach(e => (posts[e.id] = e));
if(data.length != 320){
console.log('Posts loaded')
return posts;
}
}
}
async function get_search_results(query, page){
console.log(`Getting page ${page} for [${query}]\nThis could take a while`);
const url = new URL('https://e621.net/post/index.json');
url.searchParams.set('tags', query);
url.searchParams.set('page', page);
url.searchParams.set('limit', 320);
const res = await fetch(new Request(url));
const text = await res.text();
if(res.status != 200){
console.log(`Bad status code ${res.status}\n${text}`);
throw new Error(`Bad status code ${res.status}\n${text}`);
} else {
const data = JSON.parse(text);
return data;
}
}
function set(id, post){
const golder = document.getElementById(id);
// I know its not safe. this is something quick
if(post.file_ext == 'webm'){
golder.innerHTML = `
<video
poster="${post.sample_url}"
id="webm-container"
controls
loop="true"
>
<source src="${post.file_url}" type="video/webm" />
</video>`;
} else if(post.file_ext == 'swf') {
golder.innerHTML = `
<object>
<param name="movie" value="${post.file_url}">
<embed
type="application/x-shockwave-flash"
src="${post.file_url}"
allowscriptaccess="never"
>
</object>`;
} else {
golder.innerHTML = `<img src="${post.file_url}">`;
}
}
function compare_two(post1, post2){
set('leftpost', post1);
set('rightpost', post2);
document.getElementById('leftpost').setAttribute('data-id', post1.id);
document.getElementById('rightpost').setAttribute('data-id', post2.id);
}
function do_elo(rating1, rating2, winner){
function probability(r1, r2){
return 1 / (1 + Math.pow(10, (r1 - r2) / 400));
}
const p1 = probability(rating2, rating1); // Probability p1 wins
const p2 = probability(rating1, rating2);
if(winner == 1){
const nr1 = rating1 + elo_k * (1 - p1);
const nr2 = rating2 + elo_k * (0 - p2);
return [nr1, nr2]
} else {
const nr1 = rating1 + elo_k * (0 - p1);
const nr2 = rating2 + elo_k * (1 - p2);
return [nr1, nr2];
}
}
function select2(posts){
const all_posts = Object.values(posts).sort((a, b) => {
const hd = a.hit - b.hit;
if(hd != 0){ return hd; }
const ed = a.elo - b.elo;
if(ed != 0){ return ed; }
return Math.random() > 0.5 ? -1 : 1
});
compare_two(all_posts[0], all_posts[1]);
}
get_all_posts('').then(posts => {
select2(posts);
document.addEventListener('keydown', e => {
if(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Space'].includes(e.key) == false){ return; }
const get = id => parseInt(document.getElementById(id).getAttribute('data-id'), 10);
const left_id = get('leftpost');
const right_id = get('rightpost');
let r1 = posts[left_id].elo;
let r2 = posts[right_id].elo;
if(e.key == 'ArrowLeft'){
[r1, r2] = do_elo(r1, r2, 1);
} else if(e.key == 'ArrowRight'){
[r1, r2] = do_elo(r1, r2, 2);
} else if(e.key == 'ArrowUp'){
// Both win
let _ = null;
[r1, _] = do_elo(r1, r2, 1);
[_, r2] = do_elo(r1, r2, 2);
} else if(e.key == 'ArrowDown'){
// Both lose
let _ = null;
[r1, _] = do_elo(r1, r2, 2);
[_, r2] = do_elo(r1, r2, 1);
} else if(e.key == 'Space'){
}
posts[left_id].elo = r1;
posts[right_id].elo = r2;
posts[left_id].hit++;
posts[right_id].hit++;
select2(posts);
});
document.getElementById('export').addEventListener('click', () => {
console.log(Object.values(posts).map(e => ({
post_id: e.id,
elo: e.elo
})).map(e => `${e.post_id} ${e.elo}`))
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment