110 lines
2.8 KiB
Python
110 lines
2.8 KiB
Python
#!/usr/bin/env python
|
|
# -*- encoding: utf-8 -*-
|
|
'''
|
|
@File : utils.py
|
|
@Author : liuyihui
|
|
@Email : liuyihui02@gmail.com
|
|
'''
|
|
|
|
# here put the import lib
|
|
import math
|
|
from typing import List
|
|
from . import db_init
|
|
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?check_same_thread=False', echo=False)
|
|
session_maker = sessionmaker(bind=engine)
|
|
Person = db_init.Person
|
|
|
|
def get_session() -> Session:
|
|
'''make a session instance
|
|
|
|
Returns
|
|
-------
|
|
: a session instance
|
|
'''
|
|
return session_maker()
|
|
|
|
def get_counts(ses: Session) -> int:
|
|
res = ses.query(Person).count()
|
|
return res
|
|
|
|
def get_person(ses: Session) -> Person:
|
|
'''get random person
|
|
|
|
Parameters
|
|
----------
|
|
ses : session
|
|
|
|
Returns
|
|
-------
|
|
res : a person
|
|
'''
|
|
res = ses.query(Person).order_by(func.random()).first()
|
|
return res
|
|
|
|
def get_enemy(P: Person, ses: Session, delta: float = 1.623354290020702) -> Person:
|
|
'''get enemy of Person P
|
|
We should know that the rate of one person obeys logistic distribution F(t).
|
|
If rate of P (r for short) is within the interval [r1, r2] with 90% certainly:
|
|
Assuming that X obeys stand logistic distribution, so the possibility that X is in [-2.94443897916644,
|
|
2.94443897916644] equals 0.9. The standard deviation of F is pi/sqrt(3)*gamma where gamma is shape
|
|
parameter. Assuming variance of r equals expectation mu, we have sqrt(mu) = pi/sqrt(3)*gamma. And x =
|
|
(r - mu) / gamma, so r = x * gamma + mu. Instead x with ±2.94443897916644, gamma = sqrt(3*mu)/pi, we get
|
|
r = ±2.94443897916644 * sqrt(3*mu) / pi + mu = 1.623354290020702 * sqrt(mu) + mu.
|
|
|
|
Parameters
|
|
----------
|
|
P : a person
|
|
ses : session
|
|
delta : allowable gap of rate
|
|
|
|
Returns
|
|
-------
|
|
res : a person who will be enemy of Person P
|
|
'''
|
|
delta = delta * math.sqrt(P.rate)
|
|
min_ = P.rate - delta
|
|
max_ = P.rate + 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]:
|
|
'''get rank
|
|
|
|
Parameters
|
|
----------
|
|
ses : session
|
|
b : offset subscript
|
|
len : length of list
|
|
|
|
Returns
|
|
-------
|
|
res : rank list between b and b+len-1
|
|
'''
|
|
res = ses.query(Person).order_by(desc('rate')).offset(b-1).limit(len).all()
|
|
return res
|
|
|
|
def match(ses: Session) -> Person:
|
|
'''select two persons
|
|
|
|
Parameters
|
|
----------
|
|
ses : session
|
|
|
|
Returns
|
|
-------
|
|
: two persons
|
|
'''
|
|
A = get_person(ses)
|
|
B = get_enemy(A, ses)
|
|
return A, B
|