Skip to content

Instantly share code, notes, and snippets.

@RGBD
Created April 21, 2016 20:24
Show Gist options
  • Save RGBD/d8ad8e25f0e78f840ff5494c119c91bb to your computer and use it in GitHub Desktop.
Save RGBD/d8ad8e25f0e78f840ff5494c119c91bb to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name rubylovo
// @namespace rubylovo.rubyroidlabs.com/
// @description rubylovo bot
// @include http://rubylovo.rubyroidlabs.com/
// @version 1
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
//# data
var gem_names = [
'Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf',
'Hotel', 'India', 'Juliet', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar',
'Papa', 'Quebec', 'Romeo', 'Sierra', 'Tango', 'Uniform', 'Victor',
'Whiskey', 'X-Ray', 'Yankee', 'Zulu', 'Abba', 'Abac', 'Arab', 'Bic', 'Boo',
'Bay', 'Ba', 'Bac', 'Brac', 'Baobab', 'Baboeb', 'Can', 'Cia', 'Cidr',
'Ciria', 'Ccc', 'Cab', 'Aacc', 'AcAc', 'Creon', 'Corn', 'Cans', 'Crc',
'Clic', 'Clac', 'Club', 'Coub', 'Calf', 'Carab'
]; // TODO: replace with real ones
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
//# abstract functions
function get_randint(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
function get_sample(ary) {
return ary[get_randint(0, ary.length)];
}
function get_gems_fl(gem_names) {
var gems_fl = {};
alphabet.forEach(function(first) {
gems_fl[first] = {};
alphabet.forEach(function(last) {
gems_fl[first][last] = [];
})
});
gem_names.forEach(function(name) {
name = name.toLowerCase();
first = name[0];
last = name[name.length - 1];
gems_fl[first][last].push(name.toLowerCase());
});
return gems_fl;
}
function gems_fl_size(gems_fl) {
var result = 0;
alphabet.forEach(function(first) {
alphabet.forEach(function(last) {
result += gems_fl[first][last].length;
})
});
return result;
}
function gems_fl_size_each_char(gems_fl) {
var result = {};
alphabet.forEach(function(first) {
result[first] = 0;
alphabet.forEach(function(last) {
result[first] += gems_fl[first][last].length;
})
});
return result;
}
function get_cum_sums(ary) {
cum_sums = [];
sum = 0;
ary.forEach(function(value) {
sum += value;
cum_sums.push(sum);
});
return cum_sums;
}
function bin_search(ary, value) {
var left = 0;
var right = ary.length - 1;
if (value >= ary[ary.length - 1]) return ary.length;
while (left < right) {
//console.log(left + " " + right);
var mid = Math.floor((left + right) / 2);
if (value >= ary[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
function get_weighted_random(gems_fl, first) {
var counts = [];
alphabet.forEach(function(last) {
counts.push(gems_fl[first][last].length);
});
var cum_sums = get_cum_sums(counts);
if (cum_sums[cum_sums.length - 1] == 0) {
//TODO: alert
console.log("no more names starting with '" + first + "'");
return first + '_not_found';
}
var pick = get_randint(0, cum_sums[cum_sums.length - 1]);
var idx = bin_search(cum_sums, pick);
var shift = null;
if (idx == 0) {
shift = pick;
} else {
shift = pick - cum_sums[idx - 1];
}
var last = String.fromCharCode('a'.charCodeAt(0) + idx);
//console.log('pick ' + pick + ' idx ' + idx + ' shift ' + shift + ' last ' +
// last + ' result ' + gems_fl[first][last][shift])
return gems_fl[first][last][shift];
}
function get_endgame_last(gems_fl, first) {
var sizes = gems_fl_size_each_char(gems_fl);
var sortable = [];
for (var c in sizes) {
sortable.push([c, sizes[c]]);
}
sortable.sort(function(a, b) {return a[1] - b[1]});
for (var i in sortable) {
var c = sortable[i][0];
if (gems_fl[first][c].length != 0) return c;
}
console.log("get_endgame_last: no more suggestions, giving up");
return null;
}
function get_endgame_pick(gems_fl, first) {
var last = get_endgame_last(gems_fl, first);
if (last == null) {
//TODO: alert
console.log("no more names starting with '" + first + "'");
return first + '_not_found';
}
return gems_fl[first][last][0];
}
function discard_name(gems_fl, name) {
name = name.toLowerCase();
first = name[0];
last = name[name.length - 1];
gems_fl[first][last] =
gems_fl[first][last].filter(function(n) {return n != name });
}
function discard_names(gems_fl, names) {
names.forEach(function(name) {
discard_name(gems_fl, name);
});
}
function load_gems_fl() {
console.log('load_gems_fl: begin');
var result = JSON.parse(GM_getValue('gems_fl'));
console.log('load_gems_fl: end');
return result;
}
function store_gems_fl(gems_fl) {
console.log('store_gems_fl: begin');
GM_setValue('gems_fl', JSON.stringify(gems_fl));
console.log('store_gems_fl: end');
}
//# parsers and selectors
function get_mutation_target() {
return document.querySelector('.word-input');
}
function get_answer_input() {
var input_list =
document.querySelectorAll('input[data-behavior="answer_pusher"]');
if (input_list.length != 1) {
alert('not single input' + input_list);
return null;
}
var input = input_list[0];
console.log(input);
return input
}
function get_submit_button() {
var button_list = document.querySelectorAll('button[type="submit"]');
if (button_list.length != 1) {
alert('not single submit' + button_list);
return null;
}
var button = button_list[0];
console.log(button);
return button;
}
function click_button(button) {
if(document.createEvent)
{
var click = document.createEvent("MouseEvents");
click.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
button.dispatchEvent(click);
button.focus();
} else if (document.documentElement.fireEvent) {
button.fireEvent("onclick");
button.focus();
}
}
function trigger_mutation(target) {
target.setAttribute('first-letter',
target.getAttribute('first-letter'));
}
function last_submitter_name() {
container = document.querySelector('.user_answers-container');
name_link = container.querySelector('.user-answer')
.querySelector('.user-name').getElementsByTagName('a')[0];
return name_link.innerText;
}
function last_submitted_names() {
container = document.querySelector('.user_answers-container');
children = container.getElementsByClassName('user_answer-text');
var results = [];
children = [].slice.call(children);
children.forEach(function(child) {
results.push(child.innerText);
})
return results;
}
//# bound to globals
function mutation_callback(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type != 'attributes' ||
mutation.attributeName != 'first-letter') {
console.log('false mutation, giving up');
return;
}
console.log('mutation_callback');
var first =
mutation.target.getAttribute('first-letter').toLowerCase();
//var suggestion = get_weighted_random(gems_fl, first);
var suggestion = get_endgame_pick(gems_fl, first);
console.log(suggestion);
answer_input.value = suggestion.substring(1);
if (autosubmit) {
console.log('autosubmitting');
var names_to_discard = last_submitted_names();
names_to_discard.push(suggestion);
console.log('names_to_discard');
console.log(names_to_discard);
discard_names(gems_fl, names_to_discard);
store_gems_fl(gems_fl);
console.log('>>>>>>>>start with ' + first + ' ' + gems_fl_size_each_char(gems_fl)[first]);
console.log('>>>>>>>>fl group ' + first + ' ' + last + ' ' +
gems_fl[first][last].length);
console.log('clicking_button');
setTimeout(function() {
click_button(submit_button);
}, 700);
console.log('button_will_be_clicked');
}
})
}
function create_mutation_observer(target) {
var observer = new MutationObserver(mutation_callback);
var config = { attributes: true };
observer.observe(target, config);
return observer;
}
//# real code
//TODO: load_db
console.log("fuu");
//var gems_fl = get_gems_fl(gem_names);
var gems_fl = load_gems_fl();
console.log("bar");
var answer_input = get_answer_input();
var submit_button = get_submit_button();
var mutation_target = get_mutation_target();
var observer = create_mutation_observer(mutation_target);
var self_name = 'Oleg Zubchenko';
var autosubmit = true;
if (last_submitter_name() != self_name) {
setTimeout(function() {
trigger_mutation(mutation_target);
}, 100);
}
console.log('gems_fl size ' + gems_fl_size(gems_fl));
console.log('each char: ');
console.log(gems_fl_size_each_char(gems_fl));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment