Source code for tahrir.utils.rarities
import json
import os
import sys
from collections import OrderedDict
from flask import Flask
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tahrir_api.dbapi import TahrirDatabase
from tqdm import tqdm
RARITIES = ["X", "S", "A", "B", "C", "D"]
[docs]
def generate_rarities(sessmake):
accodict = {}
with sessmake() as sessobjc:
database = TahrirDatabase(session=sessobjc, autocommit=False)
accolist = database.get_all_badges().all()
userpoll = database.get_all_persons().count()
pbar = tqdm(
accolist,
total=len(accolist),
colour="#008080",
leave=False,
bar_format="{desc} {percentage:4.2f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}]", # noqa: E501
)
for unit in pbar:
pbar.set_description(f"Processing {unit.name[:20]:<20}")
giftlist = database.get_assertions_by_badge(unit.id)
accodict[unit.id] = {"poll": len(giftlist), "rate": len(giftlist) / userpoll * 100}
"""
The count of badges is equally (read equivalently) divided into the count of rarities
to ensure that all rarities have a similar count of badges. In case the floor
division ends up leaving a remainder behind, that remainder is further shared among
all the rarities to ensure fairness.
For e.g., at the time of writing this code, there is a total of 628 badges and I created
6 rarity levels, starting from X (most rare) to D (least rare). The dictionary of
badges is sorted with respect to the assertion count and then, equal segments of sizes
equalling ~ (628 // 6) are created.
As 628 does not divide neatly by 6, the size of each rarity becomes 104 (i.e. 628 // 6)
before the remainder 4 (i.e. 628 % 6) is also spread through all the rarities from X
onwards until we run out of it. This ends up in a division where X, S, A and B rarities
have 105 badges and C and D rarities have 104 badges.
"""
accodict = OrderedDict(sorted(accodict.items(), key=lambda item: item[1]["poll"]))
rarities = {name: [] for name in RARITIES}
size = len(accodict.keys()) // len(RARITIES)
left = len(accodict.keys()) % len(RARITIES)
jump = 0
for iter, rare in enumerate(rarities.keys()):
stop = jump + size + (1 if iter < left else 0)
for iden, data in list(accodict.items())[jump:stop]:
data["rare"] = rare
rarities[rare].append(iden)
jump = stop
jsondata = {
"rarity": rarities,
"badges": accodict,
}
with open("rarities.json", "w") as json_file:
json.dump(jsondata, json_file, indent=4, sort_keys=False)
print("Rarities saved to 'rarities.json' - Move this file into the tahrir/static directory")
[docs]
def main():
app = Flask(__name__)
if "FLASK_CONFIG" in os.environ:
app.config.from_envvar("FLASK_CONFIG")
database_uri = app.config.get("SQLALCHEMY_DATABASE_URI")
try:
sessmake = sessionmaker(bind=create_engine(database_uri))
generate_rarities(sessmake)
except Exception as expt:
print(f"Rarities generation failed: {expt}")
sys.exit(1)