@@ -1,3 +1,16 @@
+// ==UserScript==
+// @name ShogiDB2 DownloadLinkCreator
+// @description 将棋DB2の検索結果一覧ページに棋譜ダウンロードボタンを追加します。
+// @include https://shogidb2.com/latest
+// @include https://shogidb2.com/floodgate
+// @include https://shogidb2.com/tournament/*
+// @include https://shogidb2.com/player/*
+// @include https://shogidb2.com/strategy/*
+// @require https://cdn.rawgit.com/polygonplanet/encoding.js/master/encoding.min.js
+// @namespace knoa.jp
+// @version 1.0
+// ==/UserScript==
+
(function () {
console.log('ShogiDB2 DownloadLinkCreator');
var KEYWORDS = ['竜王戦','名人戦','順位戦','王位戦','王座戦','棋王戦','王将戦','棋聖戦'];/*対局情報に含まれていればハイライト*/
// ==UserScript==
// @name ShogiDB2 DownloadLinkCreator
// @description 将棋DB2の検索結果一覧ページに棋譜ダウンロードボタンを追加します。
// @include https://shogidb2.com/latest
// @include https://shogidb2.com/floodgate
// @include https://shogidb2.com/tournament/*
// @include https://shogidb2.com/player/*
// @include https://shogidb2.com/strategy/*
// @require https://cdn.rawgit.com/polygonplanet/encoding.js/master/encoding.min.js
// @namespace knoa.jp
// @version 1.0
// ==/UserScript==
(function () {
console.log('ShogiDB2 DownloadLinkCreator');
var KEYWORDS = ['竜王戦','名人戦','順位戦','王位戦','王座戦','棋王戦','王将戦','棋聖戦'];/*対局情報に含まれていればハイライト*/
var TITLES = ['竜王','名人','王位','王座','棋王','王将','棋聖','叡王','朝日杯','銀河','NHK杯','JT杯'];/*対局者名から取り除く称号*/
var FILETYPE = 'KIF';/*棋譜ファイルの形式(CSA,KIF,KI2)*/
var ENCODING = 'SJIS';/*棋譜ファイルの文字コード変換(SJIS,UTF8,...)※ブックマークレット実行時は無効*/
var INTERVAL = 1000;/*短時間連続読み込みの抑制*/
var LIMIT = 100;/*取得数制限(デバッグ用)*/
var games = document.querySelectorAll('a.list-group-item');/*検索結果一覧*/
var core = {
/*初期化*/
'initialize': function(){
console.log('initialize...');
var a, script;
core.attatchStyle();
a = document.createElement('a');
a.className = 'make-downloads btn btn-primary';
a.innerHTML = 'ダウンロードボタン生成';
a.addEventListener('click', function(e){
this.classList.add('disabled');
/*棋譜データ処理スクリプトを取得してからボタン生成を始める*/
script = document.createElement('script');
script.src = '/js/shogiboard.min.js';
script.addEventListener('load', function(e){
core.createLink(0);
});
document.getElementsByTagName('head')[0].appendChild(script);
});
document.querySelector('h2').appendChild(a);
},
/*スタイル付与*/
'attatchStyle': function(){
console.log('attatchStyle...');
var style, css = '';
css += 'a.keywords{background:#ccddee!important;}';
css += 'a.make-downloads{position:absolute;right:15px;}';
css += 'a.download{position:absolute;right:30px;margin-top:-45px;}';
style = document.createElement('style');
style.innerHTML = css;
document.getElementsByTagName('head')[0].appendChild(style);
for(var i=0; games[i]; i++){
if(games[i].innerText.match(new RegExp(KEYWORDS.join('|'))) != null){
games[i].classList.add('keywords');
}
}
},
/*棋譜ダウンロードボタン生成*/
'createLink': function (i) {
console.log('createLink...', i);
var a, xhr, d, table, date, title, sente, gote, kifu;
/*無効状態のボタンを作っておく*/
a = document.createElement('a');
a.className = 'download btn btn-primary disabled';
a.innerHTML = FILETYPE + '形式';
games[i].parentNode.insertBefore(a, games[i].nextSibling);
setTimeout(function () {
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
d = xhr.responseXML;
/*ここからファイル名構築*/
table = d.querySelector('table');
date = table.querySelector('tr:nth-child(1) td').innerText.replace(/\b([1-9])(月|日)/g, '0$1$2');
title = table.querySelector('tr:nth-child(2) td').innerText;
sente = core.normalizeName(table.querySelector('tr:nth-child(4) td').innerText);
gote = core.normalizeName(table.querySelector('tr:nth-child(5) td').innerText);
a.download = [date, title, sente, gote].join('-') + '.' + FILETYPE.toLowerCase();
/*ここから棋譜取得*/
eval(d.querySelector('body>script[type]').innerText);/*"var data = {(json)}"であることを信頼*/
kifu = core.exportKifu(data);
/*ここからボタン有効化*/
a.href = core.kifuToObjectURL(kifu);
a.classList.remove('disabled');
}
};
xhr.open('GET', games[i].href);
xhr.responseType = 'document';
xhr.send();
if (!games[i+1] || LIMIT <= i+1){
console.log('done.');
return;
}
core.createLink(i+1);
}, INTERVAL);
},
/*段位タイトルを削除*/
'normalizeName': function(name){
var dan = new RegExp('((女流|奨励会)?[初一二三四五六七八九・](級|段|冠)|' + TITLES.join('|') + ')$', 'g');
name = name.replace(dan, '');
name = name.replace(/ | /g, '');
return name;
},
/*指定形式で棋譜ファイル生成*/
'exportKifu': function(data){
switch(FILETYPE){
case 'CSA':
return new CSAExporter(data).export();
case 'KIF':
return new KifExporter(data).export();
case 'KI2':
return new KI2Exporter(data).export();
}
},
/*棋譜ファイルからobjectURL生成*/
'kifuToObjectURL': function(kifu){
var kifuArray;
if(typeof Encoding === 'undefined' || ENCODING == 'UTF8'){
kifuArray = [new Uint8Array([0xEF, 0xBB, 0xBF])/*BOM追加*/, kifu];
}else{
kifuArray = [new Uint8Array(Encoding.convert(kifu, {to:ENCODING, from:'AUTO', type:'array'}))];
}
return window.URL.createObjectURL(new Blob(kifuArray));
}
};
core.initialize();
}) ();