Skip to content

Instantly share code, notes, and snippets.

@anta0
Last active December 8, 2016 20:58
Show Gist options
  • Save anta0/6533ffd4ba792bd67b5d to your computer and use it in GitHub Desktop.
Save anta0/6533ffd4ba792bd67b5d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name SmartSubmit for AtCoder
// @version 0.200001
// @auther anta
// @description 問題閲覧画面で Ctrl+V をするだけで提出します。yukicoder <http://yukicoder.me/> の機能・コードを元にしています。
// @match http://*.contest.atcoder.jp/*
// @match https://*.contest.atcoder.jp/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @grant GM_xmlhttpRequest
// @run-at document-end
// ==/UserScript==
//License: MPL <https://www.mozilla.org/MPL/2.0/>
//Changelog:
//0.1: init
//0.2: add: isValidSource
//0.2: fix
//指定したい言語にマッチする正規表現 (コンテストによって使えるバージョンが違うことがあるので適切に)
var languageNameMatch = /C\+\+11 \(GCC [\d\.]+\)/.source;
//変な文字列とかを間違って提出してしまわないように
var sourceRegExp = /^#include/;
function log() {
console.log.apply(console, arguments);
}
function getTaskID() {
var href = $(".btn-large").attr("href");
if(!href) return null;
var match = href.match(/^\/submit\?task_id=(.*)$/);
if(!match) return null;
return match[1];
}
function getVar(name) {
return GM_getValue(name);
}
function setVar(name, val) {
GM_setValue(name, val);
}
function getSessionID(callback) {
var sessionCookie = $.cookie('_session');
if(getVar('sessionCookie') != sessionCookie || !getVar('cachedSessionID')) {
var err = function() {
log.apply(this, arguments);
};
if(sessionCookie) GM_xmlhttpRequest({
method: 'GET',
url: 'https://' + location.host + '/submit',
onload: function(r) {
var data = r.responseText;
var match = data.match(/name="__session" value="([0-9a-f]+)"/);
if(!match) {
// err('err', data);
return;
}
var sessionID = match[1];
setVar('sessionCookie', sessionCookie);
setVar('cachedSessionID', sessionID);
log('sessionID: ' + sessionID + ' for cookie ' + sessionCookie);
callback(sessionID);
},
onerror: err
});
}else {
callback(getVar('cachedSessionID'));
}
}
function getLanguageID(callback) {
var host = location.host, cacheName = 'cachedLanguageID[' + host + ']';
if(!getVar(cacheName)) {
var err = function() {
log.apply(this, arguments);
};
GM_xmlhttpRequest({
method: 'GET',
url: 'https://' + location.host + '/submit',
onload: function(r) {
var data = r.responseText;
var match = data.match(new RegExp('<option value="([^"]+)">(' + languageNameMatch + ')</option>'));
if(!match) {
err('language not found');
return;
}
var languageID = match[1];
setVar(cacheName, languageID);
log('languageID: ' + languageID + ' ' + match[2] + '');
callback(languageID);
},
onerror: err
});
}else {
callback(getVar(cacheName));
}
}
function isValidSource(source) {
if(!source) return false
if(!source.match(sourceRegExp)) return false;
return true;
}
//log('start');
getSessionID(function(sessionID) {
var taskID = getTaskID();
if(!taskID) return;
getLanguageID(function(languageID) {
log('taskID = ' + taskID + ', sessionID = ' + sessionID);
$('body').append($('<form action="https://' + location.host + '/submit?task_id=' + taskID + '" method="POST">'+
'<input type="hidden" name="__session" value="' + sessionID + '">'+
'<input type="hidden" name="task_id" value="' + taskID + '">'+
'<input type="hidden" name="language_id_' + taskID + '" value="' + languageID + '">'+
'<textarea name="source_code" id="smartsubmit-source" style="display: none; position: fixed"></textarea>'+
'<input type="submit" id="smartsubmit-submit" style="display: none">'+
'</form>'));
$(document).keydown(function(e){
var keyEvent = e || window.event;
//macのコマンドキーまたはコントロールキー
if(keyEvent.metaKey || keyEvent.ctrlKey){
//選択範囲がある時は動作しない。
var selObj = window.getSelection();
if (selObj.toString().length == 0 || keyEvent.keyCode == 86){
$("#smartsubmit-source").val("").show().focus();
}
}
});
$("#smartsubmit-source").keyup(function(e){
var keyEvent = e || window.event;
if(keyEvent.metaKey || keyEvent.ctrlKey){
}else{
$("#smartsubmit-source").hide();
}
});
$('#smartsubmit-source').bind('paste',function(ev){
var source = ev.originalEvent.clipboardData.getData('text/plain');
if(isValidSource(source)) {
setTimeout(function() {
$("#smartsubmit-source").val(source);
$("#smartsubmit-source").hide();
$("#smartsubmit-submit").click();
}, 10);
}else {
log("invalid source: " + source);
$("#smartsubmit-source").val('');
}
});
})});
/*
GM_listValues().forEach(function(val) {
console.log(val, GM_getValue(val));
});
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment