ref: elo method;add: db methods;change: html file
This commit is contained in:
parent
60ab8fadba
commit
52c8518fb7
6
.gitignore
vendored
6
.gitignore
vendored
@ -4,3 +4,9 @@ pyelo/
|
|||||||
# config file
|
# config file
|
||||||
setup.cfg
|
setup.cfg
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# data
|
||||||
|
*.db
|
||||||
|
|
||||||
|
# cache
|
||||||
|
__pycache__/
|
30
lib/db_init.py
Normal file
30
lib/db_init.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
@File : db_init.py
|
||||||
|
@Author : liuyihui
|
||||||
|
@Email : liuyihui02@gmail.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
# here put the import lib
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy import Column, Integer, String, Float
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
class Person(Base):
|
||||||
|
__tablename__ = 'persons'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
name = Column(String)
|
||||||
|
work = Column(String)
|
||||||
|
rate = Column(Float, default=1400)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Person(name='%s', work='%s', rate='%f')>" % (self.name, self.work, self.rate)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
engine = create_engine('sqlite:///data.db', echo=True)
|
||||||
|
Base.metadata.create_all(engine, checkfirst=True)
|
52
lib/elo.py
52
lib/elo.py
@ -8,60 +8,40 @@
|
|||||||
|
|
||||||
# here put the import lib
|
# here put the import lib
|
||||||
import math
|
import math
|
||||||
from typing_extensions import Self
|
from db_init import Person
|
||||||
|
|
||||||
class Person(object):
|
def __compute_wre(A: Person, B: Person) -> float:
|
||||||
'''personal information
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
rate : elo rate
|
|
||||||
name : name
|
|
||||||
sex : male or female
|
|
||||||
link : baike link
|
|
||||||
|
|
||||||
Methods
|
|
||||||
-------
|
|
||||||
compute_K : compute the constant K
|
|
||||||
'''
|
|
||||||
def __init__(self, name: str, rate: float = 1400, *, sex: str = None, link: str = None) -> None:
|
|
||||||
self.name = name
|
|
||||||
self.rate = rate
|
|
||||||
self.link = link
|
|
||||||
|
|
||||||
if sex and sex not in ['male', 'female']:
|
|
||||||
raise ValueError("Sex must be male or female")
|
|
||||||
self.sex = sex
|
|
||||||
|
|
||||||
def compute_wre(self, B: Self) -> float:
|
|
||||||
'''compute win rate expectation (wre for short)
|
'''compute win rate expectation (wre for short)
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
B : another person
|
A, B : two persons
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
wre : win rate expectation
|
wre : win rate expectation of A
|
||||||
'''
|
'''
|
||||||
wre = 1 / (1 + math.pow(10, (B.rate-self.rate)/400))
|
wre = 1 / (1 + math.pow(10, (B.rate-A.rate)/400))
|
||||||
return wre
|
return wre
|
||||||
|
|
||||||
def compute_K(self) -> float:
|
def __compute_K(P: Person) -> float:
|
||||||
if self.rate > 2400:
|
if P.rate > 2400:
|
||||||
return 12
|
return 12
|
||||||
elif self.rate > 2000:
|
elif P.rate > 1900:
|
||||||
return 24
|
return 24
|
||||||
else:
|
else:
|
||||||
return 36
|
return 36
|
||||||
|
|
||||||
def set_result(self, wre: float, res: float) -> None:
|
def set_result(A: Person, B: Person, res: float) -> None:
|
||||||
'''set result of this game
|
'''set result of this game
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
wre : win rate expectation
|
A, B : two persons
|
||||||
res : the result, 0 for lose, 1 for win and 0.5 for draw
|
res : the result, 0 for A win, 1 for B win and -1 for draw
|
||||||
'''
|
'''
|
||||||
K = self.compute_K()
|
wre1 = __compute_wre(A, B)
|
||||||
self.rate += K * (res - wre)
|
wre2 = 1 - wre1
|
||||||
|
if res >= 0:
|
||||||
|
A.rate += __compute_K(A) * (1 - res - wre1)
|
||||||
|
B.rate += __compute_K(B) * (res - wre2)
|
||||||
|
48
lib/utils.py
Normal file
48
lib/utils.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
@File : utils.py
|
||||||
|
@Author : liuyihui
|
||||||
|
@Email : liuyihui02@gmail.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
# here put the import lib
|
||||||
|
import elo
|
||||||
|
import random
|
||||||
|
from typing import List
|
||||||
|
from db_init import Person
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from sqlalchemy.orm.session import Session
|
||||||
|
from sqlalchemy.sql.expression import desc, func
|
||||||
|
|
||||||
|
engine = create_engine('sqlite:///data.db', echo=False)
|
||||||
|
session_maker = sessionmaker(bind=engine)
|
||||||
|
|
||||||
|
def get_session() -> Session:
|
||||||
|
return session_maker()
|
||||||
|
|
||||||
|
def get_person(id: int, ses: Session) -> Person:
|
||||||
|
res = ses.query(Person).filter_by(id=id).first()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_enemy(P: Person, ses: Session, delta: float = 0.01) -> Person:
|
||||||
|
min_ = P.rate * (1 - delta)
|
||||||
|
max_ = P.rate * (1 + delta)
|
||||||
|
|
||||||
|
res = ses.query(Person).filter(
|
||||||
|
Person.id != P.id,
|
||||||
|
Person.rate >= min_,
|
||||||
|
Person.rate <= max_
|
||||||
|
).order_by(func.random()).first()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_rank(ses: Session, b: int = 1, len: int = 10) -> List[Person]:
|
||||||
|
res = ses.query(Person).order_by(desc('rate')).offset(b-1).limit(len).all()
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
ses = get_session()
|
||||||
|
A = get_person(1, ses)
|
||||||
|
res = get_enemy(A, ses)
|
||||||
|
print(res)
|
@ -43,7 +43,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="margin: 2% auto;">
|
<div style="margin: 2% auto;">
|
||||||
姓名:<p id="N1"></p><br />
|
姓名:<p id="N1"></p><br />
|
||||||
年龄:<p id="S1"></p><br />
|
|
||||||
代表作:<p id="M1"></p><br />
|
代表作:<p id="M1"></p><br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,7 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="margin: 2% auto;">
|
<div style="margin: 2% auto;">
|
||||||
姓名:<p id="N2"></p><br />
|
姓名:<p id="N2"></p><br />
|
||||||
年龄:<p id="S2"></p><br />
|
|
||||||
代表作:<p id="M2"></p><br />
|
代表作:<p id="M2"></p><br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user