Skip to content

Commit

Permalink
resolve #4: improve stable rank and confidence interval calc.
Browse files Browse the repository at this point in the history
  • Loading branch information
zyr17 committed Feb 12, 2024
1 parent 500d7ca commit 49e3132
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 38 deletions.
9 changes: 4 additions & 5 deletions i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,12 +325,11 @@
"Different stable stars in different room corresponding to the latter title to enter this room. e.g. stable stars 4.5 in Gold Room means Expert 4.5.",
"About Expert 4.5, when stable stars bigger than 3, with enough matches you will upgrade your title. For upgrading title will change the penalty step and open new rooms, we can't cimply say Expert 4.5 = Master 1.5. For same reason, when stable ranks is less than 1, you will fall with enough matches.",
"",
"<b>Confidence Interval: </b>",
"<b>Stable Rank Calculation and Confidence Interval: </b>",
"For confidence interval, in simple, the more matches analyzed, the smaller the confidence interval, and the stable stars is more accurate. alpha=0.05",
"The procedure when calculating confidence interval may having many mistakes, if you are good at this (and familiar with Chinese), please help me.",
"Below are some data about these in Chinese.",
"<b>Issue: </b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>",
"<b>Introduction of calculating stable rank and confidence interval: </b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/blob/master/doc/stable-rank.md\">stable-rank.md</a>"
"The procedure uses random sampling and simulation to calculate stable rank and confidence interval. It simulates 1000 times based on prior 1-2-3-4 place rate. ",
"You can find details in the following Issue.",
"<b>Issue: </b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>"
]
},
"TITLE": {
Expand Down
7 changes: 3 additions & 4 deletions i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,9 @@
"<b>置信区间:</b>",
"置信区间表示了安定星数的可信程度。简单来说,置信区间越小说明计算场次越多,估计的安定星数越准确。",
"详细了解置信区间需要概率论和统计的基础数学知识,如果没有基础知识可以忽略以下内容。",
"本程序计算的置信区间为0.95置信区间。使用正态分布进行估计,在盘数小于100时由于分布的离散性很不准确。",
"程序所采用的公式在盘数大于1000时和随机采样结果进行比较结果相近因此采用,其数学原理没有依据。如果有擅长此方面的大佬存在欢迎指正。",
"<b>相关Issue:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>",
"<b>程序的安定星数和置信区间计算说明:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/blob/master/doc/stable-rank.md\">stable-rank.md</a>"
"本程序计算的置信区间为0.95置信区间。使用正态分布进行估计,在盘数过少时由于分布的离散性很不准确。",
"程序使用1000次随机采样模拟的方式计算近似安定段位和置信区间,具体算法可参考下方Issue。",
"<b>相关Issue:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>"
]
},
"TITLE": {
Expand Down
5 changes: 2 additions & 3 deletions i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,8 @@
"置信區間表示了安定星數的可信程度。簡單來說,置信區間越小說明計算場次越多,估計的安定星數越準確。",
"詳細了解置信區間需要概率論和統計的基礎數學知識,如果沒有基礎知識可以忽略以下內容。",
"本程序計算的置信區間為0.95置信區間。使用正態分布進行估計,在盤數小於100時由於分布的離散性很不準確。",
"程序所採用的公式在盤數大於1000時和隨機採樣結果進行比較結果相近因此採用,其數學原理沒有依據。如果有擅長此方面的大佬存在歡迎指正。",
"<b>相關Issue:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>",
"<b>程序的安定星數和置信區間計算說明:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/blob/master/doc/stable-rank.md\">stable-rank.md</a>"
"程序使用1000次隨機采樣模擬的方式計算近似安定段位和置信區間,具體算法可參考下方Issue。",
"<b>相關Issue:</b><a href=\"https://github.com/zyr17/MajsoulPaipuAnalyzer/issues/4\">Github Issue</a>"
]
},
"TITLE": {
Expand Down
2 changes: 1 addition & 1 deletion result.html

Large diffs are not rendered by default.

80 changes: 56 additions & 24 deletions src/algo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ namespace SR{
}

void stablerank(int round, double &stablerank, std::pair<double, double> &CI, int roomnumber){
// new calculator, proposed by @yuanhang0. Simulate 1000 times.
assert(round == 4 || round == 8);
if (ME.size() != ROOMNUMBER) initializerounddata();
auto &rds = round == 4 ? ME : MS;
Expand All @@ -767,41 +768,72 @@ namespace SR{
if (roomnumber == INVALIDROOM)
roomnumber= 0;
}
std::cout << "stablerank " << round << ' ' << roomnumber << std::endl;
assert(roomnumber == 0 || roomnumber == 100 || (roomnumber >= 0 && roomnumber < ROOMNUMBER && considerroom[roomnumber]));
auto &rd = rds[roomnumber];
if (!(rd.pt123.size() + rd.pt4.size())){
if (!(rd.pts[0].size())){
stablerank = CI.first = CI.second = NAN;
return;
}

std::vector<double> pt = rd.pt123;
double total = 0;
for (auto i : rd.pt123)
total += i;
for (auto i : rd.pt4)
total += i;
double r4 = 1.0 * rd.pt4.size() / (rd.pt123.size() + rd.pt4.size());
double every4 = total / rd.pt4.size();
for (auto i : rd.pt4)
pt.push_back(i - every4);
CI = confidenceinterval(pt);
stablerank = (every4 - rd.roombase) / rd.roomdelta;
CI.first = CI.first / rd.roomdelta / r4 + stablerank;
CI.second = CI.second / rd.roomdelta / r4 + stablerank;
//std::cout << total << ' ' << r4 << ' ' << every4 << ' ' << stablerank << ' ' << CI.first << ' ' << CI.second << '\n';
const int sim_time = 1000;

// average delta_pt
double delta_pt = 0;
for (auto i : rd.pts[0])
delta_pt += i;
int total_number = rd.pts[0].size();
std::cout << rd.pts[0].size() << ' ' << rd.pts[1].size() << ' ' << rd.pts[2].size() << ' ' << rd.pts[3].size() << ' ' << rd.pts[4].size() << std::endl;
delta_pt /= total_number;
std::vector<int> numbers;
std::cout << 12321 << ' ' << delta_pt << std::endl;
for (int i = 1; i <= 4; i ++ ) {
numbers.push_back(rd.pts[i].size());
if (i != 4)
for (auto j : rd.pts[i]) {
assert(j == rd.pts[i][0]); // all pt should be same
}
}
std::cout << 32123 << std::endl;
std::cout << numbers[0] << ' ' << numbers[1] << ' ' << numbers[2] << ' ' << numbers[3] << std::endl;
std::discrete_distribution<> dist(numbers.begin(), numbers.end());
std::mt19937 gen(19260817);
std::vector<double> sim_res;
double sim_total = 0;
std::cout << 22222 << std::endl;
for (int i = sim_time; i -- ; ){
std::vector<int> counts(4, 0);
for (int j = total_number; j -- ; )
counts[dist(gen)] ++ ;
double nowpt = 0;
for (int j = 0; j < 3; j ++ )
if (counts[j] > 0)
nowpt += counts[j] * rd.pts[j + 1][0];
if (counts[3] == 0) counts[3] = 1; // if no 4, use 1 to avoid divide by 0
nowpt /= counts[3];
sim_res.push_back(nowpt + delta_pt);
sim_total += nowpt + delta_pt;
}
std::cout << 44444 << std::endl;
std::sort(sim_res.begin(), sim_res.end());
stablerank = (sim_total / sim_time - rd.roombase) / rd.roomdelta;
CI = std::make_pair(sim_res[sim_time * 0.025], sim_res[sim_time * 0.975]);
CI.first = (CI.first - rd.roombase) / rd.roomdelta;
CI.second = (CI.second - rd.roombase) / rd.roomdelta;
std::cout << stablerank << ' ' << CI.first << ' ' << CI.second << std::endl;
}

void addgamedata(int nroom, int round, int rank, int pt, int point){
assert(nroom >= 0 && nroom < ROOMNUMBER || nroom == 100);
// std::cout << "addgamedata " << nroom << ' ' << round << ' ' << rank << ' ' << pt << ' ' << point << std::endl;
// assert(nroom >= 0 && nroom < ROOMNUMBER || nroom == 100 || nroom == 99 || nroom == 98);
if (round != 4 && round != 8) return;
if (ME.size() != ROOMNUMBER) initializerounddata();
if (nroom == 100 || !considerroom[nroom]) return;
if (nroom >= ROOMNUMBER || !considerroom[nroom]) return;
auto &rd = round == 4 ? ME[nroom] : MS[nroom];
if (rank != 4) rd.pt123.push_back(pt);
else{
pt = (point - 25000) / 1000;
rd.pt4.push_back(pt);
}
int delta_pt = (point + 900 - rank * 10000 + 1000000) / 1000 - 1000;
pt -= delta_pt;
rd.pts[0].push_back(delta_pt);
rd.pts[rank].push_back(pt);
}

int getroom(int round){
Expand All @@ -810,7 +842,7 @@ namespace SR{
auto &rds = round == 4 ? ME : MS;
int roomnumber = INVALIDROOM;
for (int i = 0; i < ROOMNUMBER; i ++ ){
if (considerroom[i] && (rds[i].pt123.size() + rds[i].pt4.size()))
if (considerroom[i] && (rds[i].pts[0].size()))
roomnumber = i;
}
if (roomnumber < 0 || roomnumber > 5 || !considerroom[roomnumber]) return INVALIDROOM;
Expand Down
4 changes: 3 additions & 1 deletion src/algo.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef _ALGO_H
#define _ALGO_H

#include <random>
#include <algorithm>
#include "header.h"
#include "analyzer.h"
#include "consts.h"
Expand Down Expand Up @@ -67,7 +69,7 @@ namespace Algo{
struct RoundData{
const int roombase, roomdelta;
int room = INVALIDROOM;
std::vector<double> pt123, pt4;
std::vector<double> pts[5]; // 0 for delta pts by final points, 1-4 for 1-4 place pts.
RoundData(const int roombase, const int roomdelta) : roombase(roombase), roomdelta(roomdelta) {}
};

Expand Down

0 comments on commit 49e3132

Please sign in to comment.