Edit in JSFiddle

function elorating(winrate)
{
  if (winrate <= 0) return Number.NEGATIVE_INFINITY;
  if (winrate >= 1) return Number.POSITIVE_INFINITY;
  return 400 * Math.log10(winrate / (1 - winrate));
}
function elorating_inv(rdiff)
{
  return 1 / (1 + Math.exp(-Math.LN10 * 0.0025 * rdiff));
}
function clopper_pearson(k, n, alpha)
{
  var alpha2 = (1 - alpha) / 2;
  // 勝率・敗率をあわせて計算(0%,100%に近い勝率の情報落ち・桁落ち誤差を減らすため)
  // beta.inv(p, a, b) == 1 - beta.inv(1 - p, b, a)
  var lower_w = jStat.beta.inv(alpha2, k, n - k + 1); // 勝率
  var lower_l = jStat.beta.inv(1 - alpha2, n - k + 1, k); // 敗率
  var upper_w = jStat.beta.inv(1 - alpha2, k + 1, n - k); // 勝率
  var upper_l = jStat.beta.inv(alpha2, n - k, k + 1); // 敗率
  return {
    lower: Number.isNaN(lower_w) ? Number.isNaN(lower_l) ? 0 : 1 - lower_l : (lower_w <= 0.5 || Number.isNaN(lower_l)) ? lower_w : 1 - lower_l,
    upper: Number.isNaN(upper_w) ? Number.isNaN(upper_l) ? 1 : 1 - upper_l : (upper_w <= 0.5 || Number.isNaN(upper_l)) ? upper_w : 1 - upper_l,
    lower_win: lower_w,
    lower_lose: lower_l,
    upper_win: upper_w,
    upper_lose: upper_l,
    lowerrate: Number.isNaN(lower_w) ? Number.isNaN(lower_l) ? Number.NEGATIVE_INFINITY : -elForate(lower_l) : (lower_w <= 0.5 || Number.isNaN(lower_l)) ? elorating(lower_w) : -elorating(lower_l),
    upperrate: Number.isNaN(upper_w) ? Number.isNaN(upper_l) ? Number.POSITIVE_INFINITY : -elorating(upper_l) : (upper_w <= 0.5 || Number.isNaN(upper_l)) ? elorating(upper_w) : -elorating(upper_l),
    k: k,
    n: n,
    alpha: alpha
  };
}
function addtd(parent, text, classes, attr)
{
  if(!text) text = "";
  if(!classes) classes = "";
  if(!attr) attr = {};
  var elem = document.createElement("td");
  text.split("\n").forEach(function(t, i, a)
  {
    elem.appendChild(document.createTextNode(t));
    if(i + 1 < a.length)
      elem.appendChild(document.createElement("br"));
  });
  classes.split(" ").forEach(function(c){
    if(c !== "") elem.classList.add(c);
  });
  Object.keys(attr).forEach(function(key)
  {
    elem.setAttribute(key, attr[key]);
  });
  parent.appendChild(elem);
}
function calc_dist()
{
  var calcptn_e = document.getElementById("calcptn");
  var calcptn = calcptn_e.options[calcptn_e.selectedIndex].value;
  var relptn_e = document.getElementById("relptn");
  var relptn = relptn_e.options[relptn_e.selectedIndex].value;
  
  var params = [];
  var params_percent = [
    0.25, 0.50, 0.75,
    0.80, 0.90,
    0.95, 0.98, 0.99,
    0.998, 0.999,
    0.9998, 0.9999,
    0.99998, 0.99999,
    0.999998, 0.999999,
    0.9999998, 0.9999999,
    0.99999998, 0.99999999,
    0.999999998, 0.999999999
  ];
  var params_sigma = [
    0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0
  ].map(function(v){ return jStat.erf(v * Math.SQRT1_2); });
  switch(relptn)
  {
  case "all":
    params = params_percent.concat(params_sigma);
    params.sort(function(a, b){ return a - b; });
    break;
  case "percent":
    params = params_percent;
    break;
  case "sigma":
    params = params_sigma;
    break;
  }
  var win = Math.max(Math.round(+document.getElementById("win").value), 0);
  var draw = Math.max(Math.round(+document.getElementById("draw").value), 0);
  var lose = Math.max(Math.round(+document.getElementById("lose").value), 0);
  var match = win + lose;
  var allmatch = win + draw + lose;
  var pretext =
    "Win-Draw-Lose: " + win + "-" + draw + "-" + lose + "\n" +
    "有効試合数: " + match + ", " +
    "有効勝率: " + (100 * win / match).toFixed(2) + "%, " +
    "有効ΔR: " + (win >= lose && match > 0 ? "+" : "") + elorating(win / match).toFixed(2) + "\n" +
    "総試合数: " + allmatch + ", " +
    "勝率(引分0.5勝換算): " + (100 * (0.5 * draw + win) / allmatch).toFixed(2) + "%, " +
    "ΔR(引分0.5勝換算): " + (win >= lose && allmatch > 0 ? "+" : "") + elorating((0.5 * draw + win) / allmatch).toFixed(2) + ", " +
    "引分率: " + (100 * draw / allmatch).toFixed(2) + "%";
  var docf = document.createDocumentFragment();
  params.forEach(function(p)
  {
    var tr = document.createElement("tr");
    
    addtd(tr, jStat.normal.inv(p * 0.5 + 0.5, 0, 1).toFixed(3) + "σ: " + (p * 100).toFixed(7) + "%", "reliability", calcptn == "all" ? {rowSpan: 4} : {});

    if(calcptn == "draw0" || calcptn == "all")
    {
      var result1 = clopper_pearson(win, match, p);
      
      addtd(tr, (result1.lowerrate >= 0 ? "+" : "") + result1.lowerrate.toFixed(2), "right draw0");
      addtd(tr, "(" + (100 * result1.lower).toFixed(2) + "%)", "right draw0");
      addtd(tr, "~", "draw0");
      addtd(tr, (result1.upperrate >= 0 ? "+" : "") + result1.upperrate.toFixed(2), "right draw0");
      addtd(tr, "(" + (100 * result1.upper).toFixed(2) + "%)", "right draw0");
      addtd(tr, (result1.upperrate - result1.lowerrate).toFixed(2), "right draw0");
      addtd(tr, "引分=無効", "draw0");

      docf.appendChild(tr);
      tr = document.createElement("tr");
    }
    
    if(calcptn == "draw1" || calcptn == "all")
    {
      var result2 = clopper_pearson(0.5 * draw + win, allmatch, p, "draw1");
      
      addtd(tr, (result2.lowerrate >= 0 ? "+" : "") + result2.lowerrate.toFixed(2), "right draw1");
      addtd(tr, "(" + (100 * result2.lower).toFixed(2) + "%)", "right draw1");
      addtd(tr, "~", "draw1");
      addtd(tr, (result2.upperrate >= 0 ? "+" : "") + result2.upperrate.toFixed(2), "right draw1");
      addtd(tr, "(" + (100 * result2.upper).toFixed(2) + "%)", "right draw1");
      addtd(tr, (result2.upperrate - result2.lowerrate).toFixed(2), "right draw1");
      addtd(tr, "引分=0.5勝", "draw1");

      docf.appendChild(tr);
      tr = document.createElement("tr");
    }

    if(calcptn == "draw2" || calcptn == "all")
    {
      var result3 = clopper_pearson(Math.floor(0.5 * draw) + win, Math.floor(0.5 * draw) * 2 + match, p);

      addtd(tr, (result3.lowerrate >= 0 ? "+" : "") + result3.lowerrate.toFixed(2), "right draw2");
      addtd(tr, "(" + (100 * result3.lower).toFixed(2) + "%)", "right draw2");
      addtd(tr, "~", "draw2");
      addtd(tr, (result3.upperrate >= 0 ? "+" : "") + result3.upperrate.toFixed(2), "right draw2");
      addtd(tr, "(" + (100 * result3.upper).toFixed(2) + "%)", "right draw2");
      addtd(tr, (result3.upperrate - result3.lowerrate).toFixed(2), "right draw2");
      addtd(tr, "引分=0.5勝(端数無効)", "draw2");

      docf.appendChild(tr);
      tr = document.createElement("tr");
    }
    
    if(calcptn == "draw3" || calcptn == "all")
    {
      var result4 = clopper_pearson(Math.floor(0.5 * draw) + win, allmatch, p);
      var result5 = clopper_pearson(Math.ceil(0.5 * draw) + win, allmatch, p);

      addtd(tr, (result4.lowerrate >= 0 ? "+" : "") + result4.lowerrate.toFixed(2), "right draw3");
      addtd(tr, "(" + (100 * result4.lower).toFixed(2) + "%)", "right draw3");
      addtd(tr, "~", "draw3");
      addtd(tr, (result5.upperrate >= 0 ? "+" : "") + result5.upperrate.toFixed(2), "right draw3");
      addtd(tr, "(" + (100 * result5.upper).toFixed(2) + "%)", "right draw3");
      addtd(tr, (result5.upperrate - result4.lowerrate).toFixed(2), "right draw3");
      addtd(tr, "引分=0.5勝(端数切下げ/切上げ)", "draw3");

      docf.appendChild(tr);
      tr = document.createElement("tr");
    }
    
  });
  document.getElementById("preout").innerText = pretext;
  var tout = document.getElementById("tout");
  while (tout.firstChild) { tout.removeChild(tout.firstChild); }
  tout.appendChild(docf);
}
calc_dist();
document.getElementById("win").onchange = calc_dist;
document.getElementById("draw").onchange = calc_dist;
document.getElementById("lose").onchange = calc_dist;
document.getElementById("calcbtn").onclick = calc_dist;
document.getElementById("calcptn").onchange = calc_dist;
document.getElementById("relptn").onchange = calc_dist;

var elor = [
  0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59,
  0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69,
  0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79,
  0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89,
  0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99,
  0.991, 0.992, 0.993, 0.994, 0.995, 0.996, 0.997, 0.998, 0.999,
  0.9991, 0.9992, 0.9993, 0.9994, 0.9995, 0.9996, 0.9997, 0.9998, 0.9999,
  0.99991, 0.99992, 0.99993, 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99999
].map(function(v){ return elorating(v); }).concat([
  5, 10, 15, 20, 25, 30, 35, 40, 45, 50,
  55, 60, 65, 70, 75, 80, 85, 90, 95, 100,
  110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
  210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
  310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
  410, 420, 430, 440, 450, 460, 470, 480, 490, 500,
  550, 600, 650, 700, 750, 800, 850, 900, 950, 1000,
  1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900
]);
elor.sort(function(a, b){ return a - b; });
elor.forEach(function(v)
{
  var tr = document.createElement("tr");
  addtd(tr, (v >= 0 ? "+" : "") + v.toFixed(2), "right");
  addtd(tr, (elorating_inv(v) * 100).toFixed(3) + "%", "right");
  addtd(tr, (elorating_inv(-v) * 100).toFixed(3) + "%", "right");
  document.getElementById("elorating").appendChild(tr);
});
<h1>勝敗数→レーティング差推計</h1>
<p class="form">
勝数:<input type="number" id="win" min="0" max="999999999999" step="1" />,
引分:<input type="number" id="draw" min="0" max="999999999999" step="1" />,
敗数:<input type="number" id="lose" min="0" max="999999999999" step="1" />
<button id="calcbtn">recalc</button>
</p>
<p>
<select id="calcptn">
<option value="all">全種計算</option>
<option value="draw0">引分=無効</option>
<option value="draw1" selected>引分=0.5勝</option>
<option value="draw2">引分=0.5勝(端数無効)</option>
<option value="draw3">引分=0.5勝(端数切下げ/切上げ)</option>
</select>
<select id="relptn">
<option value="all" selected>全信頼度</option>
<option value="percent">パーセント点</option>
<option value="sigma">正規分布σ</option>
</select>
</p>
<pre id="preout"></pre>
<table><thead><th>信頼度</th><th colspan="5">信頼区間</th><th>区間幅</th><th>処理区分</th></thead><tbody id="tout"></tbody></table>
<ul>
<li>例: 信頼度「2.326σ: 98.0000000%」の場合、正規分布のグラフ上では 平均値±2.326σ の範囲に 98% が入ること、二項分布において信頼区間の範囲に収まる面積が 98% 、区間の下にぶれる可能性が 1% {=(100%-98%)/2} 、上にぶれる可能性が 1% である事を示しています。</li>
<li>「信頼区間」「区間幅」は、「区間下側のレーティング差(勝率)」~「区間上側のレーティング差(勝率)」、「区間上側のレーティング差-区間下側のレーティング差」をそれぞれ表記しています。</li>
<li>「引分」の信頼区間計算における扱い(例: Win-Draw-Lose: 1-3-1 の場合)<ul>
  <li>「引分=無効」: Win-Lose: 1-1 として計算</li>
  <li>「引分=0.5勝」: Win-Lose: 2.5-2.5 として計算</li>
  <li>「引分=0.5勝(端数無効)」: Win-Lose: 2-2 として計算(引分1を無効扱い)</li>
  <li>「引分=0.5勝(端数切下げ/切上げ)」: 下限は Win-Lose: 2-3 、上限は Win-Lose: 3-2 として計算</li>
</ul></li>
<li>入力される値によっては(特に小さすぎたり大きすぎたり、極端な値が入力される場合)、必ずしも表示される精度がそのまま有効な精度とは限りません。</li>
<li><a href="https://github.com/jstat/jstat">jStat</a> - JavaScript Statistical Library</li>
<li><a href="https://github.com/tibigame/HandicappedRook/tree/master/tool">tibigame/HandicappedRook/tool</a> - original code</li>
</ul>
<h2>レーティング差早見表</h2>
<table>
<thead><th>レート差</th><th>勝率</th><th>敗率</th></thead>
<tbody id="elorating"></tbody>
</table>
p.form { font-family: monospace; }
input { text-align: right; }
table { border-collapse: collapse; }
th {
color: #333;
background-color: #ddd;
border: 1px solid #b9b9b9;
}
td {
padding: 2px;
color: #333;
background-color: #fff;
border: 1px solid #b9b9b9;
font-family: 'Inconsolata', 'Consolas', monospace;
}
td.right { text-align: right; }
td.reliability { background-color: #ffffff; }
td.draw0 { background-color: #ffffff; }
td.draw1 { background-color: #f7f7f7; }
td.draw2 { background-color: #eeeeee; }
td.draw3 { background-color: #e6e6e6; }

External resources loaded into this fiddle: