LoginSignup
1
1

More than 1 year has passed since last update.

AtWaker Contestのレーティング

Last updated at Posted at 2021-12-11

AtWaker Contestとは

東大生のたまり場、バーチャル東大DiscordというDiscordサーバー(通称VUTD)にはAtWakerというbotがいます。そのbotが毎朝7:30~12:00に開催している、早起きレーティングコンテストがAtWaker Contestです。

毎朝7:30にAtWakerが
「おはようございます! Good morning!
20yy-mm-ddのAtWaker Contest xxx開始です。
起きた人は下の「20yy-mm-dd」の
メッセージにでリアクションしてね。
徹夜勢の参加は禁止です。
一度寝てから出直してください。」
というメッセージを送信します。
その直後にAtWakerが「20yy-mm-dd」というメッセージを送信するので、
それに12:00までにでリアクションしてください。
時刻と各参加者の過去のパフォーマンスをもとに、
AtCoder Heuristic Contestの方法を少し改造した方法で
計算されたレーティングがコンテスト後に付与されます。
2回以上リアクションをしても、採用されるのは初回のみです。

2021/12/1112(2021/12/08にherokuの不具合があったせいでずれました)にAtWaker Contestは300回を迎えました。300回記念として(?)AtWaker Contestのレーティングの仕組みを解説します。

概要

毎朝7:30~12:00にAtWakerのメッセージにリアクションを付けた人には、パフォーマンスと呼ばれる点数が付きます。参加した回のパフォーマンスを集計して、レーティングが算出されます。今回はパフォーマンスの計算方法、レーティングの集計方法を解説します。

パフォーマンス

参加者が$n$人いるとします。早い順に参加者$1,\ldots,n$とします。参加者$i\ (i=1,\ldots,n)$がリアクションを押した時点から12:01:00までの秒数を$s_i$秒とします。参加者$i$のランク$l_i$を以下のように定めます。便宜上$l_0=0$とします。

$$l_i'=\frac{\max_{1\leq j \leq n} (s_j)-s_i}{16200}\times n\ (i=1,\ldots,n)\\
l_i=l_i'-\frac{3l_1'}{2}+\max\left(l_1',\frac{1}{16200}\right)\ (i=1,\ldots,n)$$
$\{l_i\}_{i=0,\ldots,n}$は単調増加で、すべての項が非負です。

次に各参加者の過去パフォーマンスの重み付き平均$a_i$を計算します。参加者$i$が前日までに$m_i$回参加しているとします。$m_i\geq 1$のとき、参加者$i$の過去パフォーマンスを時系列の逆順(新しい順)に$p_{i,1},\ldots,p_{i,m_i}$とし、

$$a_i=\frac{\sum_{j=1}^m0.9^jp_{i,j}}{\sum_{j=1}^m0.9^j}$$
とします。初参加者については、$a_i=1200$とします。

関数$f(x)$を
$$f(x)=\sum_{i=1}^n\frac{l_i-l_{i-1}}{1+6^{\frac{x-a_i}{400}}}$$
で定めます。$f(x)$は非負単調減少で、$\lim_{x\to\infty}f(x)=0$です。参加者$i$の暫定パフォーマンス$P_i'$は$f(P_i')\leq l_i$が成立する最小の整数です。最終的なパフォーマンス$P_i$は以下の式で求められます。$\lfloor x\rfloor$は$x$を超えない最大の整数を表します。

$$M'=\frac{1}{n}\sum_{i=1}^nP_i',\ D'=\sqrt{\frac{1}{n}\sum_{i=1}^n(P_i'-M')^2}\\
M=1200+300\ln(n),\ D=800\ln(6)\\
P_i''=\frac{D}{D'}(P_i'-M')+M\\
P_i=\left\{\begin{array}{ll}
\lfloor P_i''\rfloor&(P_i''>400)\\
\left\lfloor 400\times e^{\frac{P_i''-400}{400}}\right\rfloor&(P_i''\leq 400)
\end{array}\right.$$

レーティング

定数$W,S$を次のように定めます。この定数については後で解説します。

$$W=0.827197336426137,\ S=724.47443003358$$

参加者$i$の今回のパフォーマンスを$p_{i,0}(=P_i)$、過去パフォーマンスを時系列の逆順(新しい順)に$p_{i,1},\ldots,p_{i,m_i}$とします。さらに、参加者が時系列の逆順(新しい順)に$d_{i,0},d_{i,1},\ldots,d_{i,m_i}$日前に参加していたとします。つまり、$0=d_{i,0}<d_{i,1}<\cdots<d_{i,m_i}$で、参加者は$d_{i,j}$日前のAtWaker Contestでパフォーマンス$p_{i,j}$を獲得し、$d_{i,1}$日前、…、$d_{i,m_i}$日前以外の日は参加していないとします。修正パフォーマンス$p_{i,j}'\ (i=1,\ldots,n,\ j=1,\ldots,m_i)$を$p_{i,j}'=0.99^{d_{i,j}}p_{i,j}$として定めます。これによって、不参加(あるいは開催中止)により1日当たりレーティングが約1%減少するようになっています。参加者$i$に対し、数列$\{q_{i,k}\}_{k=1,\ldots,100(m_i+1)}$を以下のように定めます。

$$q_{i,100j+l}=p_{i,j}-S\ln(l)\ (j=0,\ldots,m_i,\ l=1,\ldots,100)$$

$\{q_{i,k}\}_{k=1,\ldots,100(m_i+1)}$を降順にソートしたものを$\{q_{i,k}'\}_{k=1,\ldots,100(m_i+1)}$とします。暫定レーティング$R_i'$は$\{q_{i,k}'\}_{k=1,\ldots,100(m_i+1)}$の先頭100項の重み付き平均として計算されます。

$$R_i'=\frac{\sum_{k=1}^{100}W^kq_{i,k}}{\sum_{k=1}^{100}W^k}$$

最終的なレーティング$R_i$は以下のように計算されます。

$$R_i=\left\{\begin{array}{ll}
\lfloor R_i'+0.5\rfloor&(R_i'>400)\\
\left\lfloor 400\times e^{\frac{R_i'-400}{400}}+0.5\right\rfloor&(R_i'\leq 400)
\end{array}\right.$$

非参加者についても同様に計算します。(ただし、今回参加していないので、$p_{i,0},d_{i,0}$などは除いて計算します。)

定数について

定数$W,S$は初参加者のパフォーマンスが$1600$以上のときにレーティングがパフォーマンスから$1000$を引いた値になり、なおかつ後述の$q_{i,1}',\ldots,q_{i,10}'$のレーティングへの寄与がちょうど全体の85%になるように調整したものです。具体的には、

$$\sum_{k=1}^{10}W^k=0.85\sum_{k=1}^{100}W^k\\
S=\frac{1000\sum_{k=1}^{100}W^k}{\sum_{k=1}^{100}W^k\ln(k)}$$

を満たすような$W,S$です。$W\neq 0,1$に注意して、一つ目の$W$の式を変形すると、

$$17W^{100}-20W^{10}+3=0$$

となります。$X=W^{10}$とおくと、

$$17X^{10}-20X+3=0$$

となります。これは10次方程式であり、代数的には解けないので、Halley's methodで近似値を求めます。

$$F(X)=17X^{10}-20X+3$$

とすると、

$$F'(X)=170X^9-20,\ F''(X)=1530X^8$$

となります。

$$G(X)=X-\frac{2F(X)F'(X)}{2(F'(X))^2-F(X)F''(X)}\
=\frac{26010X^{19}+24480X^{10}-5610X^9+120}{31790X^{18}+17000X^9-4590X^8+800}$$

初期値$X_0=0$として、$X_{i+1}=G(X_i)$を計算すると、

$$X_1=\frac{3}{20}=0.15\\
X_2=\frac{62914520938853327042075667}{419430125886693432194690620} \approx 0.15000000490153$$

となります。

$$f(X_2)\approx 4.10454\times 10^{-28}$$

なので、これで十分でしょう。

$$W\approx\left(\frac{62914520938853327042075667}{419430125886693432194690620}\right)^{\frac{1}{10}}\approx 0.827197336426137\\
S=\frac{1000\sum_{k=1}^{100}W^k}{\sum_{k=1}^{100}W^k\ln(k)}\approx 724.47443003358$$

となります。

最後に

実装はこちら。ただし、チャンネルがVUTDのatwaker-駒場東大前チャンネルに固定されているため、適宜変更を加えないと他サーバーでは使えません。

みんなAtWaker Contestに参加してね!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1