「rating」の編集履歴(バックアップ)一覧はこちら
「rating」(2016/03/14 (月) 18:53:52) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
#divclass(ao){レーティング表}
このページはjavascriptを用いてwikiのページを解析することによってリアルタイムにレーティング表を更新します。
何も表示されない場合、javascriptをONにしてください。
&link_anchor(simulation){シミュレーション}もできます。
#divclass(rating){
}
#divclass(midori){&anchor(simulation){シミュレーション}}
成立していない試合を入力し、仮想のレーティング計算をすることができます。
※レーティング表の更新またはページをリロードすると、編集中の表はクリアされます。
#divclass(simulation){
}
#divclass(simulated-rating){
}
#js(){{
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^[\s ]+|[\s ]+$/, '');
};
}
var ratingMap = {};
var testHistory = {};
var initCharacter = function(map, name) {
if (!map[name]) {
map[name] = {
rate: 1500,
matches: 0
};
}
return map;
};
var calc = function(map, winner, looser) {
map = initCharacter(map, winner.name);
map = initCharacter(map, looser.name);
// 浮動小数点数の計算誤差のため整数計算する
winner.c = looser.c = 5; // 収束係数(c) *10
var dc;
if (map[winner.name].matches < 4) {
dc = (4 - map[winner.name].matches);
winner.c += dc;
looser.c -= dc;
}
if (map[looser.name].matches < 4) {
dc = (4 - map[looser.name].matches);
winner.c -= dc;
looser.c += dc;
}
// 浮動小数点数に戻す
winner.c /= 10;
looser.c /= 10;
if (winner.point != 50) {
winner.c = 1 - Math.pow(1 - winner.c, winner.point / 50.0);
looser.c = 1 - Math.pow(1 - looser.c, winner.point / 50.0);
}
// レート変動幅(d)
var weight = 20;
// 変動幅係数(e)
var length = winner.point == 50 ? 1 : 50.0 / winner.point;
// (-A + B + d*(n-m)*e)
winner.balance =
-map[winner.name].rate +
map[looser.name].rate +
weight * (winner.point - looser.point) * length
;
looser.balance =
-map[looser.name].rate +
map[winner.name].rate +
weight * (looser.point - winner.point) * length
;
// レート増減分: c * (-A + B + d*(n-m)*e) / 2
winner.charge = winner.c * winner.balance / 2.0;
looser.charge = looser.c * looser.balance / 2.0;
map[winner.name].rate += winner.charge;
map[looser.name].rate += looser.charge;
map[winner.name].matches++;
map[looser.name].matches++;
return map;
};
var linkify = function(name) {
return $("<div>").append($("<a>")
.text(name)
.attr("href", "18.html?" + encodeURI(name))
).html();
};
var display = function(map, target) {
if (!target) {
target = ".rating";
}
var displayMap = [];
var displayMapIndex = 0;
$.each(map, function(name, data) {
displayMap[displayMapIndex] = data;
displayMap[displayMapIndex++].name = name;
});
displayMap.sort(function(a, b) {
if (a.rate > b.rate) {
return -1;
} else if(a.rate < b.rate) {
return 1;
}
return 0;
});
var html = "<table><thead><tr><th>HN</th><th>レーティング</th><th>対戦回数</th></tr></thead><tbody id=\"ratings\">";
for(var i = 0; i < displayMap.length; i++) {
var data = displayMap[i];
html +=
"<tr><th>" +
linkify(data.name) +
"</th><th>" +
parseInt(data.rate) +
"</th><th>" +
data.matches +
"</th></th>"
;
}
html += "</tbody></table>";
$(target).html(html);
};
var addTestGame = function(winner, looser) {
var hash = "t" + +new Date();
testHistory[hash] = {
winner: winner,
looser: looser
};
var deleteButton = $("<button>")
.attr("type", "button")
.text("削除")
.click(function() {
removeTestGame(hash);
})
;
var row = $("<tr>")
.append($("<th>").html(linkify(winner.name)))
.append($("<th>").text(winner.point))
.append($("<th>").text(looser.point))
.append($("<th>").html(linkify(looser.name)))
.append($("<th>").append(deleteButton))
.append($("<th>").text(" "))
.attr("id", hash)
.attr("class", "test-game")
;
$("#test-rows").append(row);
display(calcTestMap(), ".simulated-rating");
$(".simulated-rating").prepend($("<div>").attr("class", "aka").text("シミュレート結果"));
};
var removeTestGame = function(hash) {
delete testHistory[hash];
$("#test-rows").find("#" + hash).remove();
if ($.isEmptyObject(testHistory)) {
$(".simulated-rating").empty();
} else {
display(calcTestMap(), ".simulated-rating");
$(".simulated-rating").prepend($("<div>").attr("class", "aka").text("シミュレート結果"));
}
};
var clearTestGames = function() {
testHistory = {};
$("#test-rows").find(".test-game").remove();
$(".simulated-rating").empty();
};
var calcTestMap = function() {
var testMap = {};
var initCharacterTestMap = function(name) {
if (!testMap[name] && ratingMap[name]) {
testMap[name] = {
name: ratingMap[name].name,
rate: ratingMap[name].rate,
matches: ratingMap[name].matches
};
}
};
$.each(testHistory, function(gameIndex, game) {
initCharacterTestMap(game.winner.name);
initCharacterTestMap(game.looser.name);
testMap = calc(testMap, game.winner, game.looser);
});
return testMap;
};
var placeTestForm = function() {
var testForm = $("<form>"),
table = $("<table>"),
header = $("<thead>"),
body = $("<tbody>"),
clearButton = $("<button>"),
container = $(".simulation")
;
container.empty();
header.append($("<tr><th>勝者</th><th>勝者本数</th><th>敗者本数</th><th>敗者</th><th> </th><th> </th></tr>"));
var row = $("<tr>");
var addCol = function(colBody) {
var col = $("<td>");
col.append(colBody);
row.append(col);
}
var addInput = function(id, length) {
var input = $("<input>");
input
.attr("type", "text")
.attr("size", length)
.attr("id", id)
;
addCol(input);
};
addInput("test-winner-name", 10);
addInput("test-winner-point", 3);
addInput("test-looser-point", 3);
addInput("test-looser-name", 10);
addCol($("<input>").attr("type", "submit").attr("value", "追加"));
addCol($("<label>").append($("<input>").attr("type", "checkbox").attr("id", "test-clear-inputs")).append("追加時入力をクリア"));
body
.attr("id", "test-rows")
.append(row)
;
table
.append(header)
.append(body)
;
clearButton
.attr("type", "button")
.text("クリア")
.click(clearTestGames)
;
testForm
.attr("id", "test-form")
.append(table)
.append(clearButton)
.submit(function() {
var winner = {
name: $("#test-winner-name").val(),
point: $("#test-winner-point").val()
};
var looser = {
name: $("#test-looser-name").val(),
point: $("#test-looser-point").val()
};
var validate = function() {
if (!winner.name || !winner.point || !looser.name || !looser.point) {
alert("空欄があります");
return false;
}
winner.point = parseInt(winner.point);
looser.point = parseInt(looser.point);
if (isNaN(winner.point) || isNaN(looser.point)) {
alert("本数に数値が指定されていません");
return false;
}
if (winner.point < 1 || looser.point < 0) {
alert("本数には正の整数を指定してください");
return false;
}
return true;
};
if (validate()) {
addTestGame(winner, looser);
if ($("#test-clear-inputs").is(':checked')) {
$("#test-winner-name").val("");
$("#test-winner-point").val("");
$("#test-looser-point").val("");
$("#test-looser-name").val("");
}
$("#test-winner-name").focus();
}
return false;
})
;
container.append(testForm);
};
var loadRatingMap = function() {
$(".rating").load("25.html",function(data){});
};
var reloadButton = $("<button type=\"button\">更新</button>");
reloadButton.click(loadRatingMap);
$(".rating").before(reloadButton);
loadRatingMap();
}}
#divclass(ao){レーティング表}
このページはjavascriptを用いてwikiのページを解析することによってリアルタイムにレーティング表を更新します。
何も表示されない場合、javascriptをONにしてください。
&link_anchor(simulation){シミュレーション}もできます。
#divclass(rating){
}
#divclass(midori){&anchor(simulation){シミュレーション}}
成立していない試合を入力し、仮想のレーティング計算をすることができます。
※レーティング表の更新またはページをリロードすると、編集中の表はクリアされます。
#divclass(simulation){
}
#divclass(simulated-rating){
}
#js(){{
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^[\s ]+|[\s ]+$/, '');
};
}
var ratingMap = {};
var testHistory = {};
var initCharacter = function(map, name) {
if (!map[name]) {
map[name] = {
rate: 1500,
matches: 0
};
}
return map;
};
var calc = function(map, winner, looser) {
map = initCharacter(map, winner.name);
map = initCharacter(map, looser.name);
// 浮動小数点数の計算誤差のため整数計算する
winner.c = looser.c = 5; // 収束係数(c) *10
var dc;
if (map[winner.name].matches < 4) {
dc = (4 - map[winner.name].matches);
winner.c += dc;
looser.c -= dc;
}
if (map[looser.name].matches < 4) {
dc = (4 - map[looser.name].matches);
winner.c -= dc;
looser.c += dc;
}
// 浮動小数点数に戻す
winner.c /= 10;
looser.c /= 10;
if (winner.point != 50) {
winner.c = 1 - Math.pow(1 - winner.c, winner.point / 50.0);
looser.c = 1 - Math.pow(1 - looser.c, winner.point / 50.0);
}
// レート変動幅(d)
var weight = 20;
// 変動幅係数(e)
var length = winner.point == 50 ? 1 : 50.0 / winner.point;
// (-A + B + d*(n-m)*e)
winner.balance =
-map[winner.name].rate +
map[looser.name].rate +
weight * (winner.point - looser.point) * length
;
looser.balance =
-map[looser.name].rate +
map[winner.name].rate +
weight * (looser.point - winner.point) * length
;
// レート増減分: c * (-A + B + d*(n-m)*e) / 2
winner.charge = winner.c * winner.balance / 2.0;
looser.charge = looser.c * looser.balance / 2.0;
map[winner.name].rate += winner.charge;
map[looser.name].rate += looser.charge;
map[winner.name].matches++;
map[looser.name].matches++;
return map;
};
var linkify = function(name) {
return $("<div>").append($("<a>")
.text(name)
.attr("href", "18.html?" + encodeURI(name))
).html();
};
var display = function(map, target) {
if (!target) {
target = ".rating";
}
var displayMap = [];
var displayMapIndex = 0;
$.each(map, function(name, data) {
displayMap[displayMapIndex] = data;
displayMap[displayMapIndex++].name = name;
});
displayMap.sort(function(a, b) {
if (a.rate > b.rate) {
return -1;
} else if(a.rate < b.rate) {
return 1;
}
return 0;
});
var html = "<table><thead><tr><th>HN</th><th>レーティング</th><th>対戦回数</th></tr></thead><tbody id=\"ratings\">";
for(var i = 0; i < displayMap.length; i++) {
var data = displayMap[i];
html +=
"<tr><th>" +
linkify(data.name) +
"</th><th>" +
parseInt(data.rate) +
"</th><th>" +
data.matches +
"</th></th>"
;
}
html += "</tbody></table>";
$(target).html(html);
};
var addTestGame = function(winner, looser) {
var hash = "t" + +new Date();
testHistory[hash] = {
winner: winner,
looser: looser
};
var deleteButton = $("<button>")
.attr("type", "button")
.text("削除")
.click(function() {
removeTestGame(hash);
})
;
var row = $("<tr>")
.append($("<th>").html(linkify(winner.name)))
.append($("<th>").text(winner.point))
.append($("<th>").text(looser.point))
.append($("<th>").html(linkify(looser.name)))
.append($("<th>").append(deleteButton))
.append($("<th>").text(" "))
.attr("id", hash)
.attr("class", "test-game")
;
$("#test-rows").append(row);
display(calcTestMap(), ".simulated-rating");
$(".simulated-rating").prepend($("<div>").attr("class", "aka").text("シミュレート結果"));
};
var removeTestGame = function(hash) {
delete testHistory[hash];
$("#test-rows").find("#" + hash).remove();
if ($.isEmptyObject(testHistory)) {
$(".simulated-rating").empty();
} else {
display(calcTestMap(), ".simulated-rating");
$(".simulated-rating").prepend($("<div>").attr("class", "aka").text("シミュレート結果"));
}
};
var clearTestGames = function() {
testHistory = {};
$("#test-rows").find(".test-game").remove();
$(".simulated-rating").empty();
};
var calcTestMap = function() {
var testMap = {};
var initCharacterTestMap = function(name) {
if (!testMap[name] && ratingMap[name]) {
testMap[name] = {
name: ratingMap[name].name,
rate: ratingMap[name].rate,
matches: ratingMap[name].matches
};
}
};
$.each(testHistory, function(gameIndex, game) {
initCharacterTestMap(game.winner.name);
initCharacterTestMap(game.looser.name);
testMap = calc(testMap, game.winner, game.looser);
});
return testMap;
};
var placeTestForm = function() {
var testForm = $("<form>"),
table = $("<table>"),
header = $("<thead>"),
body = $("<tbody>"),
clearButton = $("<button>"),
container = $(".simulation")
;
container.empty();
header.append($("<tr><th>勝者</th><th>勝者本数</th><th>敗者本数</th><th>敗者</th><th> </th><th> </th></tr>"));
var row = $("<tr>");
var addCol = function(colBody) {
var col = $("<td>");
col.append(colBody);
row.append(col);
}
var addInput = function(id, length) {
var input = $("<input>");
input
.attr("type", "text")
.attr("size", length)
.attr("id", id)
;
addCol(input);
};
addInput("test-winner-name", 10);
addInput("test-winner-point", 3);
addInput("test-looser-point", 3);
addInput("test-looser-name", 10);
addCol($("<input>").attr("type", "submit").attr("value", "追加"));
addCol($("<label>").append($("<input>").attr("type", "checkbox").attr("id", "test-clear-inputs")).append("追加時入力をクリア"));
body
.attr("id", "test-rows")
.append(row)
;
table
.append(header)
.append(body)
;
clearButton
.attr("type", "button")
.text("クリア")
.click(clearTestGames)
;
testForm
.attr("id", "test-form")
.append(table)
.append(clearButton)
.submit(function() {
var winner = {
name: $("#test-winner-name").val(),
point: $("#test-winner-point").val()
};
var looser = {
name: $("#test-looser-name").val(),
point: $("#test-looser-point").val()
};
var validate = function() {
if (!winner.name || !winner.point || !looser.name || !looser.point) {
alert("空欄があります");
return false;
}
winner.point = parseInt(winner.point);
looser.point = parseInt(looser.point);
if (isNaN(winner.point) || isNaN(looser.point)) {
alert("本数に数値が指定されていません");
return false;
}
if (winner.point < 1 || looser.point < 0) {
alert("本数には正の整数を指定してください");
return false;
}
return true;
};
if (validate()) {
addTestGame(winner, looser);
if ($("#test-clear-inputs").is(':checked')) {
$("#test-winner-name").val("");
$("#test-winner-point").val("");
$("#test-looser-point").val("");
$("#test-looser-name").val("");
}
$("#test-winner-name").focus();
}
return false;
})
;
container.append(testForm);
};
var loadRatingMap = function() {
};
var reloadButton = $("<button type=\"button\">更新</button>");
reloadButton.click(loadRatingMap);
$(".rating").before(reloadButton);
loadRatingMap();
}}