Skip to content
This repository has been archived by the owner on Apr 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #236 from TCL606/TCL
Browse files Browse the repository at this point in the history
chore: add score calculate algorithm
  • Loading branch information
TCL606 authored May 19, 2022
2 parents 7413af7 + 1b239e5 commit c7bda91
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
79 changes: 79 additions & 0 deletions dependency/algorithm/final.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cassert>
using namespace std;

template <typename T>
using mypair = pair<T, T>;
double maxScore = 100;

double WinScore(double delta, double winnerGameScore) // 根据游戏得分差值,与绝对分数,决定最后的加分
{
assert(delta > 0);
double deltaRate = 0.035;
double scoreRate = 2e-5;
// 赢者至少加 half of maxScore,平局只加 a quarter of maxScore
// 差值引入非线性,差值越大非线性贡献的分数越多;绝对分数只用线性
double score = maxScore / 2 + (deltaRate + log10(delta) / maxScore + winnerGameScore * scoreRate) * delta;

cout << "delta contribution: " << deltaRate + log10(delta) / maxScore << endl;
cout << "winnerGameScore contribution: " << scoreRate * winnerGameScore << endl;

return score < maxScore ? score : maxScore;
}

// orgScore 是天梯中两队的分数;competitionScore 是这次游戏两队的得分
mypair<double> cal(mypair<double> orgScore, mypair<double> competitionScore)
{

// 调整顺序,让第一个元素成为获胜者,便于计算

bool reverse = false; // 记录是否需要调整

if (competitionScore.first < competitionScore.second)
{
reverse = true;
}
else if (competitionScore.first == competitionScore.second) // 平局,两边加quarter of maxScore
{
orgScore.first += maxScore / 4;
orgScore.second += maxScore / 4;
return orgScore;
}

if (reverse) // 如果需要换,换两者的顺序
{
swap(competitionScore.first, competitionScore.second);
swap(orgScore.first, orgScore.second);
}

double delta = competitionScore.first - competitionScore.second;
double addScore = WinScore(delta, competitionScore.first);
auto resScore = mypair<double>(orgScore.first + addScore, orgScore.second);
// 如果换过,再换回来
if (reverse)
{
swap(resScore.first, resScore.second);
}

return resScore;
}

void Print(mypair<double> score)
{
std::cout << " team1: " << score.first << std::endl
<< "team2: " << score.second << std::endl;
}

int main()
{
int x, y;
std::cout << "origin score of team 1 and 2: " << std::endl;
std::cin >> x >> y;
auto ori = mypair<double>(x, y);
std::cout << "game score of team 1 and 2: " << std::endl;
std::cin >> x >> y;
auto sco = mypair<double>(x, y);
Print(cal(ori, sco));
}
105 changes: 105 additions & 0 deletions dependency/algorithm/high_ladder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

template <typename T>
using mypair = pair<T, T>;

double PHI(double x) // THUAI3: Sigmoid; THUAI4: Tanh; THUAI5: Normal Distribution CDF
{
return erf(x / sqrt(2));
}

// orgScore 是天梯中两队的分数;competitionScore 是这次游戏两队的得分
mypair<int> cal(mypair<int> orgScore, mypair<int> competitionScore)
{

// 调整顺序,让第一个元素成为获胜者,便于计算

bool reverse = false; // 记录是否需要调整

if (competitionScore.first < competitionScore.second)
{
reverse = true;
}
else if (competitionScore.first == competitionScore.second)
{
if (orgScore.first == orgScore.second) // 完全平局,不改变天梯分数
{
return orgScore;
}

if (orgScore.first > orgScore.second) // 本次游戏平局,但一方天梯分数高,另一方天梯分数低,需要将两者向中间略微靠拢,因此天梯分数低的定为获胜者
{
reverse = true;
}
else
{
reverse = false;
}
}

if (reverse) // 如果需要换,换两者的顺序
{
swap(competitionScore.first, competitionScore.second);
swap(orgScore.first, orgScore.second);
}


// 转成浮点数
mypair<double> orgScoreLf;
mypair<double> competitionScoreLf;
orgScoreLf.first = orgScore.first;
orgScoreLf.second = orgScore.second;
competitionScoreLf.first = competitionScore.first;
competitionScoreLf.second = competitionScore.second;
mypair<int> resScore;

const double deltaWeight = 90.0; // 差距悬殊判断参数,比赛分差超过此值就可以认定为非常悬殊了,天梯分数增量很小,防止大佬虐菜鸡的现象造成两极分化

double delta = (orgScoreLf.first - orgScoreLf.second) / deltaWeight;
cout << "Normal CDF delta: " << PHI(delta) << endl;
{

const double firstnerGet = 1e-4; // 胜利者天梯得分权值
const double secondrGet = 7e-5; // 失败者天梯得分权值
const double possibleMaxScore = 1500.0; // 估计的最大得分数量

double deltaScore = 100.0; // 两队竞争分差超过多少时就认为非常大
double correctRate = (orgScoreLf.first - orgScoreLf.second) / 100.0; // 订正的幅度,该值越小,则在势均力敌时天梯分数改变越大
double correct = 0.5 * (PHI((competitionScoreLf.first - competitionScoreLf.second - deltaScore) / deltaScore - correctRate) + 1.0); // 一场比赛中,在双方势均力敌时,减小天梯分数的改变量

resScore.first = orgScore.first + round(competitionScoreLf.first * competitionScoreLf.first * firstnerGet * (1 - PHI(delta)) * correct); // 胜者所加天梯分
if (competitionScoreLf.second < possibleMaxScore)
resScore.second = orgScore.second - round((possibleMaxScore - competitionScoreLf.second) * (possibleMaxScore - competitionScoreLf.second) * secondrGet * (1 - PHI(delta)) * correct); // 败者所扣天梯分
else
resScore.second = orgScore.second; // 败者拿maxScore分,已经很强了,不扣分
}

// 如果换过,再换回来
if (reverse)
{
swap(resScore.first, resScore.second);
}

return resScore;
}

void Print(mypair<int> score)
{
std::cout << " team1: " << score.first << std::endl
<< "team2: " << score.second << std::endl;
}

int main()
{
int x, y;
std::cout << "origin score of team 1 and 2: " << std::endl;
std::cin >> x >> y;
auto ori = mypair<int>(x, y);
std::cout << "game score of team 1 and 2: " << std::endl;
std::cin >> x >> y;
auto sco = mypair<int>(x, y);
Print(cal(ori, sco));
}

0 comments on commit c7bda91

Please sign in to comment.