#!/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