Mount Olympus

Common features shared amongst all Olympian scripts.

2016/09/14のページです。最新版はこちら

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Mount Olympus
// @namespace    mobiusevalon.tibbius.com
// @version      1.4
// @author       Mobius Evalon
// @description  Common features shared amongst all Olympian scripts.
// @license      Creative Commons Attribution-ShareAlike 4.0; http://creativecommons.org/licenses/by-sa/4.0/
// @require      https://code.jquery.com/jquery-1.12.4.min.js
// @require      https://code.jquery.com/ui/1.11.4/jquery-ui.min.js
// @include      /^https{0,1}:\/\/\w{0,}\.?mturk\.com.+/
// @include      /^https{0,1}:\/\/\w*\.amazon\.com\/ap\/signin.*(?:openid\.assoc_handle|pf_rd_i)=amzn_mturk/
// @exclude      /&hit_scraper$/
// @exclude      /\/HM$/
// @grant        none
// ==/UserScript==

if(window.olympus === undefined) window.olympus = {};

// all of these are added separately because then i don't overwrite the entire olympus object,
// making it possible to initialize the scripts out of order
window.olympus.__init = function() {
	console.log("olympus init");
	olympus.style.add(
		"#javascriptDependentFunctionality {display: block !important;}"+
		".dialog.floats {border-radius: 8px; border: 2px solid #000000; max-height: 550px; position: absolute !important; z-index: 500; background-color: #7fb4cf;} "+
		".dialog.narrow {width: 300px; min-width: 300px;} "+
		".dialog.wide {width: 500px; min-width: 500px;} "+
		".dialog .scrolling-content {max-height: 350px; overflow-y: auto;} "+
		".dialog .actions {margin: 10px auto; padding: 0px; text-align: center; display: block;} "+
		".dialog .actions input:not(:last-of-type) {margin-right: 15px;} "+
		".dialog .head {padding: 0px; margin: 10px auto; font-size: 175%; font-weight: bold; width: 100%; text-align: center; cursor: move;} "+
		"#olympian_help {top: 25px; left: 200px;}"+
		"#olympian_help p.inset {margin-left: 25px;}"+
		"#olympian_help p.inset b {margin-left: -25px; display: block;}"+
		".anim_pulse {animation-name: anim_pulse; animation-duration: 350ms; animation-iteration-count: infinite; animation-timing-function: linear; animation-direction: alternate;}"+
		"@keyframes anim_pulse {from {opacity: 1;} to {opacity: 0.25;}} "
	);

	// append the fontawesome stylesheet to the page if it does not exist
	if(!$("link[rel='stylesheet'][href$='font-awesome.min.css']").length) $("head").append(
		$("<link/>")
			.attr({
				"rel":"stylesheet",
				"href":"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"
			})
	);

	Array.prototype.contains = function(item) {
		return (this.indexOf(item) > -1);
	};

	String.prototype.collapseWhitespace = function() {
		return this.replace(/\s{2,}/g," ").trim();
	};

	String.prototype.ucFirst = function() {
		return (this.charAt(0).toUpperCase()+this.slice(1));
	};

	String.prototype.contains = function(substring) {
		return (this.indexOf(substring) > -1);
	};

	// append the help window to the document
	$("body").append(
		$("<div/>")
			.attr({
				"id":"olympian_help",
				"class":"dialog wide floats"
			})
			.append(
				$("<h1/>")
					.attr("class","head")
					.text("Olympian help"),
				$("<div/>")
					.attr("class","scrolling-content")
					.append(
						$("<div/>").attr("class","explain")
					),
				$("<div/>")
					.attr("class","actions")
					.append(
						$("<button/>")
							.text("Close")
							.click(function() {
								olympus.help.hide();
							})
					)
			)
			.hide()
	);

	// use jqueryui.draggable() to make the help window movable
	$(".floats").draggable({handle:"h1.head"});

	// now that all dependencies are accounted for, initialize all olympians that are present
	// the order is semi-important: athena calls hermes so it must be initialized first
	if(olympus.hermes) olympus.hermes.__init();
	if(olympus.harpocrates) olympus.harpocrates.__init();
	if(olympus.athena) olympus.athena.__init();
	if(olympus.artemis) olympus.artemis.__init();
};

window.olympus.help = {
	__topics:{},
	add:function(obj) {
		if($.type(obj) === "object" && Object.keys(obj).length) {
			$.each(obj,function(key,val) {
				olympus.help.__topics[key] = val;
			});
		}
	},
	display:function(topic) {
		if(this.has_topic(topic)) {
			$("#olympian_help .explain").html(this.__topics[topic]);
			// parse elements with special functions
			$("#olympian_help .explain *[data-function]").each(function() {
				switch($(this).attr("data-function")) {
					case "fa-substitute": {
						$(this).addClass("fa fa-fw fa-2x "+olympus.athena.desc2fa($(this).attr("data-args")));
					}
				}
				$(this).removeAttr("data-function data-args");
			});
			// show help window
			$("#olympian_help").show();
		}
	},
	has_topic:function(topic) {
		return this.__topics.hasOwnProperty(topic);
	},
	hide:function() {
		$("#olympian_help").hide();
	}
};

window.olympus.settings = {
	get:function() {
		if($.type(arguments[0]) === "object" && arguments[0].hasOwnProperty("__name")) {
			var olympian = arguments[0],
				settings = (olympian.__settings || olympus.utilities.localstorage_obj(olympian.__name+"_settings") || olympian.default_settings());
			if(arguments.length < 2) return settings;
			else if($.type(arguments[1]) === "string") return settings[arguments[1]];
		}
	},
	init:function(olympian) {
		if($.type(olympian) === "object" && olympian.hasOwnProperty("__name")) {
			var settings = olympus.utilities.localstorage_obj(olympian.__name+"_settings"),
				defaults = olympian.default_settings();
			if($.type(settings) === "object") {
				$.each(defaults,function(k,v) {
					if(!settings.hasOwnProperty(k)) settings[k] = v;
				});
			}
			else settings = defaults;
			return settings;
		}
	},
	update:function() {
		if(arguments.length > 1 && $.type(arguments[0]) === "object" && arguments[0].hasOwnProperty("__name")) {
			var olympian = arguments[0],
				settings = (olympian.__settings || olympian.default_settings());
			if($.type(arguments[1]) === "object") {
				$.each(arguments[1],function(key,val) {
					if(settings.hasOwnProperty(key)) settings[key] = val;
				});
			}
			else if($.type(arguments[1]) === "string" && arguments.length > 2) if(settings.hasOwnProperty(arguments[1])) settings[arguments[1]] = arguments[2];

			localStorage[olympian.__name+"_settings"] = JSON.stringify(settings);
			olympian.__settings = settings;
		}
	}
};

window.olympus.style = {
	__css:"",
	__commit:function() {
		// retrieve the olympian style node, or create it if it does not yet exist
		var $style_node = $("#olympian_css");
		if(!$style_node.length) {
			$style_node = $("<style/>")
				.attr({
					"id":"olympian_css",
					"type":"text/css"
				});
			$("head").append($style_node);
		}

		// update the olympian style node with the new css
		$style_node.text(this.__css);
	},
	add:function(new_css,tokens) {
		if($.type(tokens) === "object" && Object.keys(tokens).length) new_css = this.expand(new_css,tokens);
		this.__css += new_css;
		this.__commit();
	},
	expand:function(css,tokens) {
		// olympians sometimes use bracketed tokens in their css to allow for centralized
		// style definitions from functions or for swapping values easily
		$.each(tokens,function(key,val) {css = css.replace(new RegExp(("\\["+key+"\\]"),"gi"),val);});
		return css;
	}
};

window.olympus.utilities = {
	datetime:{
		__day_string:function(int) {
			switch(int) {
				case 0: return "Sunday";
				case 1: return "Monday";
				case 2: return "Tuesday";
				case 3: return "Wednesday";
				case 4: return "Thursday";
				case 5: return "Friday";
				case 6: return "Saturday";
			}
		},
		__meridiem:function(int) {
			if(int > 12) return "pm";
			else return "am";
		},
		__meridiem_hour:function(int) {
			if(int > 12) int -= 12;
			return int;
		},
		__month_string:function(int) {
			switch(int) {
				case 0: return "January";
				case 1: return "February";
				case 2: return "March";
				case 3: return "April";
				case 4: return "May";
				case 5: return "June";
				case 6: return "July";
				case 7: return "August";
				case 8: return "September";
				case 9: return "October";
				case 10: return "November";
				case 11: return "December";
			}
		},
		__ordinal:function(int) {
			switch(int) {
				case 1: case 21: case 31: return "st";
				case 2: case 22: return "nd";
				case 3: case 23: return "rd";
			}
			return "th";
		},
		__short_year:function(int) {
			return (""+int).slice(-2);
		},
		getDayString:function() {
			return this.__day_string(this.__date.getDay());
		},
		getMeridiem:function() {
			return this.__meridiem(this.__date.getHours());
		},
		getMeridiemHours:function() {
			return this.__meridiem_hour(this.__date.getHours());
		},
		getMonthString:function() {
			return this.__month_string(this.__date.getMonth());
		},
		getOrdinal:function() {
			return this.__ordinal(this.__date.getDate());
		},
		getShortYear:function() {
			return this.__short_year(this.__date.getFullYear());
		},
		getUTCDayString:function() {
			return this.__day_string(this.__date.getUTCDay());
		},
		getUTCMeridiem:function() {
			return this.__meridiem(this.__date.getUTCHours());
		},
		getUTCMeridiemHours:function() {
			return this.__meridiem_hour(this.__date.getUTCHours());
		},
		getUTCMonthString:function() {
			return this.__month_string(this.__date.getUTCMonth());
		},
		getUTCOrdinal:function() {
			return this.__ordinal(this.__date.getUTCDate());
		},
		getUTCShortYear:function() {
			return this.__short_year(this.__date.getUTCFullYear());
		},
		getTokenizedOutput:function(t) {
			var r = "",
				i = -1;
			while(i++ < t.length) {
				switch(t.charAt(i)) {
					// escape sequence, ignore following character by advancing index beyond it
					case '\\': {r += t.charAt(++i); break;}

					// local year
					case 'y': {r += this.getShortYear(); break;}
					case 'Y': {r += this.__date.getFullYear(); break;}
					// local month
					case 'n': {r += (this.__date.getMonth()+1); break;}
					case 'm': {r += olympus.utilities.pad_string(this.__date.getMonth()+1,2); break;}
					case 'F': {r += this.getMonthString(); break;}
					case 'M': {r += this.getMonthString().slice(0,3); break;}
					// local day
					case 'j': {r += this.__date.getDate(); break;}
					case 'd': {r += olympus.utilities.pad_string(this.__date.getDate(),2); break;}
					case 'l': {r += this.getDayString(); break;}
					case 'D': {r += this.getDayString().slice(0,3); break;}
					case 'S': {r += this.getOrdinal(); break;}
					// local hour
					case 'g': {r += this.getMeridiemHours(); break;}
					case 'h': {r += olympus.utilities.pad_string(this.getMeridiemHours(),2); break;}
					case 'G': {r += this.__date.getHours(); break;}
					case 'H': {r += olympus.utilities.pad_string(this.__date.getHours(),2); break;}
					case 'a': {r += this.getMeridiem(); break;}
					case 'A': {r += this.getMeridiem().toUpperCase(); break;}
					// local minute, second
					case 'i': {r += olympus.utilities.pad_string(this.__date.getMinutes(),2); break;}
					case 's': {r += olympus.utilities.pad_string(this.__date.getSeconds(),2); break;}

					// utc year
					case 'z': {r += this.getUTCShortYear(); break;}
					case 'Z': {r += this.__date.getUTCFullYear(); break;}
					// utc month
					case 'p': {r += (this.__date.getUTCMonth()+1); break;}
					case 'q': {r += olympus.utilities.pad_string(this.__date.getUTCMonth()+1,2); break;}
					case 'T': {r += this.getUTCMonthString(); break;}
					case 'U': {r += this.getUTCMonthString().slice(0,3); break;}
					// utc day
					case 'f': {r += this.__date.getUTCDate(); break;}
					case 'e': {r += olympus.utilities.pad_string(this.__date.getUTCDate(),2); break;}
					case 'k': {r += this.getUTCDayString(); break;}
					case 'E': {r += this.getUTCDayString().slice(0,3); break;}
					case 'R': {r += this.getUTCOrdinal(); break;}
					// utc hour
					case 'b': {r += this.getUTCMeridiemHours(); break;}
					case 'c': {r += olympus.utilities.pad_string(this.getUTCMeridiemHours(),2); break;}
					case 'B': {r += this.__date.getUTCHours(); break;}
					case 'C': {r += olympus.utilities.pad_string(this.__date.getUTCHours()); break;}
					case 'o': {r += this.getUTCMeridiem(); break;}
					case 'O': {r += this.getUTCMeridiem().toUpperCase() ;break;}
					// utc minute, second
					case 'w': {r += olympus.utilities.pad_string(this.__date.getUTCMinutes(),2); break;}
					case 'x': {r += olympus.utilities.pad_string(this.__date.getUTCSeconds(),2); break;}

					default: {r += t.charAt(i); break;}
				}
			}
			return r;
		},
		output:function() {
			if(arguments.length) {
				if(arguments.length > 1) this.__date = new Date(arguments[0]);
				return this.getTokenizedOutput(arguments[arguments.length-1]);
			}
		}
	},
	ajax_get:function(mirrors,params,callback,scope) {
		var result = "";

		function exit() {
			if($.type(callback) === "function") callback.call(scope,result);
		}

		function domain_name(s) {
			return s.match(/^https{0,1}:\/\/(.+?)\//i)[1];
		}

		function request(url) {
			$.ajax({
				async:true,
				method:"GET",
				url:(url+params)
			})
			.fail(function() {
				console.log("Mount Olympus get request: attempt to gather data from '"+domain_name(url)+"' mirror failed");
				var idx = (mirrors.indexOf(url)+1);
				if(idx < mirrors.length) {
					console.log("Mount Olympus get request: attempting data request from mirror '"+domain_name(mirrors[idx])+"'...");
					request(mirrors[idx]);
				}
				else {
					console.log("Mount Olympus get request: attempts to gather data from all available mirrors has failed");
					exit();
				}
			})
			.done(function(response) {
				if(response.length) {
					console.log("Mount Olympus get request: query was successful");
					result = response;
				}
				exit();
			});
		}

		request(mirrors[0]);
	},
	dhms:function(secs) {
		// takes a number of seconds (chiefly, hitAutoAppDelayInSeconds) and returns a
		// "friendly" value in seconds, minutes, hours, or days.  has a precision of
		// tenths, e.g. "1.5 days" or "6.7 hours"
		function output(multiple,name) {
			function zeroes(num) {
				// removes ugly trailing zeroes (e.g. "1.0 days" or "2.40 hours")
				return +num.toFixed(1);
			}
			var units = zeroes((secs/multiple));
			return (""+units+" "+name+olympus.utilities.plural(units));
		}

		if($.type(secs) !== "number") secs = Math.round(secs*1);

		if(secs < 60) return output(1,"second");
		else if(secs < 3600) return output(60,"minute");
		else if(secs < 86400) return output(3600,"hour");
		else return output(86400,"day");
	},
	href_group_id:function(href) {
		if($.type(href) === "string") {
			href = href.match(/groupId=([^&\s]+)/i);
			if($.type(href) === "array") return href[1];
		}
	},
	href_requester_id:function(href) {
		if($.type(href) === "string") {
			href = href.match(/requesterId=([^&\s]+)/i);
			if($.type(href) === "array") return href[1];
		}
	},
	json_obj:function(json) {
		var obj;
		if(typeof json === "string" && json.trim().length) {
			try {obj = JSON.parse(json);}
			catch(e) {console.log("Malformed JSON object.  Error message from JSON library: ["+e.message+"]");}
		}
		return obj;
	},
	localstorage_obj:function(key) {
		var obj = this.json_obj(localStorage.getItem(key));
		if(typeof obj !== "object") localStorage.removeItem(key);
		return obj;
	},
	pad_string:function(string,width,padding,side) {
		string = (""+string);
		var pad_item = (padding || "0"),
			half = ((width-string.length)/2);
		padding = "";
		while((string.length+padding.length) < width) padding = (padding+pad_item);
		if(side === "both") return (padding.slice(0,Math.floor(half))+string+padding.slice(Math.ceil(half)*-1));
		else if(side === "right") return (string+padding).slice(0,width);
		else return (padding+string).slice(width*-1);
	},
	plural:function(num) {
		// returns the letter s if the number is not 1.  just for pretty display
		// to say something like "2 widgets" instead of "2 widget"
		if($.type(num) !== "number") num = +num;
		if(num != 1) return "s";
		return "";
	},
	turkopticon:function(rids,callback,scope) {
		var to_mirrors = [
				"https://mturk-api.istrack.in/multi-attrs.php?ids=",
				"https://turkopticon.ucsd.edu/api/multi-attrs.php?ids="
			],
			query_rids = [],
			query_result = {},
			cache_timeout = 14400000; // 4 hours in milliseconds (1000 ms in one second * 60 secs * 60 mins * 4 hours)

		function exit() {
			if($.type(callback) === "function") callback.call(scope,query_result);
		}

		// to caching functions of this script retain turkopticon information for 4 hours
		// and reuse it as necessary instead of querying the server every time
		function set_cache(rid,attrs) {
			var to_cache = (olympus.utilities.localstorage_obj("olympian_to_cache") || {});
			if($.type(attrs) !== "object") attrs = {};
			attrs.cache_time = new Date().getTime();
			to_cache[rid] = attrs;
			localStorage.olympian_to_cache = JSON.stringify(to_cache);
		}

		function get_cache(rid) {
			var to_cache = olympus.utilities.localstorage_obj("olympian_to_cache");
			if($.type(to_cache) === "object" && to_cache.hasOwnProperty(rid)) {
				var attrs = to_cache[rid];
				if((new Date().getTime()) - (attrs.cache_time*1) < cache_timeout) return attrs;
			}
		}

		// check the cache for relevant data we can use and query for the rest
		$.each(rids,function(k,v) {
			var cached = get_cache(v);
			if($.type(cached) === "object") query_result[v] = cached;
			else query_rids.push(v);
		});
		var num_cached = Object.keys(query_result).length,
			num_queried = query_rids.length;
		console.log("Mount Olympus Turkopticon: "+(num_cached > 0 ? ("using cached data for "+num_cached+" requesters") : "no available or timely cached data")+"; "+(num_queried > 0 ? ("querying for data on "+num_queried+" requesters") : "no queries necessary"));
		if(query_rids.length) {
			this.ajax_get(to_mirrors,query_rids.join(","),function(response) {
				var jsobj = olympus.utilities.json_obj(response);
				if($.type(jsobj) === "object") {
					$.each(jsobj,function(rid,attrs) {
						set_cache(rid,attrs);
						query_result[rid] = attrs;
					});
				}
				else console.log("Mount Olympus Turkopticon: query was successful but the response was malformed");
				exit();
			});
		}
		else exit();
	}
};

$(document).ready(function() {
	olympus.__init();
});