Best Python code snippet using pytest-benchmark
pbkdf2.py
Source:pbkdf2.py  
1"""passlib.handlers.pbkdf - PBKDF2 based hashes"""2#=============================================================================3# imports4#=============================================================================5# core6from binascii import hexlify, unhexlify7from base64 import b64encode, b64decode8import logging; log = logging.getLogger(__name__)9# site10# pkg11from passlib.utils import to_unicode12from passlib.utils.binary import ab64_decode, ab64_encode13from passlib.utils.compat import str_to_bascii, u, uascii_to_str, unicode14from passlib.crypto.digest import pbkdf2_hmac15import passlib.utils.handlers as uh16# local17__all__ = [18    "pbkdf2_sha1",19    "pbkdf2_sha256",20    "pbkdf2_sha512",21    "cta_pbkdf2_sha1",22    "dlitz_pbkdf2_sha1",23    "grub_pbkdf2_sha512",24]25#=============================================================================26#27#=============================================================================28class Pbkdf2DigestHandler(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):29    """base class for various pbkdf2_{digest} algorithms"""30    #===================================================================31    # class attrs32    #===================================================================33    #--GenericHandler--34    setting_kwds = ("salt", "salt_size", "rounds")35    checksum_chars = uh.HASH64_CHARS36    #--HasSalt--37    default_salt_size = 1638    max_salt_size = 102439    #--HasRounds--40    default_rounds = None # set by subclass41    min_rounds = 142    max_rounds = 0xffffffff # setting at 32-bit limit for now43    rounds_cost = "linear"44    #--this class--45    _digest = None # name of subclass-specified hash46    # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide sanity check.47    #       the underlying pbkdf2 specifies no bounds for either.48    # NOTE: defaults chosen to be at least as large as pbkdf2 rfc recommends...49    #       >8 bytes of entropy in salt, >1000 rounds50    #       increased due to time since rfc established51    #===================================================================52    # methods53    #===================================================================54    @classmethod55    def from_string(cls, hash):56        rounds, salt, chk = uh.parse_mc3(hash, cls.ident, handler=cls)57        salt = ab64_decode(salt.encode("ascii"))58        if chk:59            chk = ab64_decode(chk.encode("ascii"))60        return cls(rounds=rounds, salt=salt, checksum=chk)61    def to_string(self):62        salt = ab64_encode(self.salt).decode("ascii")63        chk = ab64_encode(self.checksum).decode("ascii")64        return uh.render_mc3(self.ident, self.rounds, salt, chk)65    def _calc_checksum(self, secret):66        # NOTE: pbkdf2_hmac() will encode secret & salt using UTF867        return pbkdf2_hmac(self._digest, secret, self.salt, self.rounds, self.checksum_size)68def create_pbkdf2_hash(hash_name, digest_size, rounds=12000, ident=None, module=__name__):69    """create new Pbkdf2DigestHandler subclass for a specific hash"""70    name = 'pbkdf2_' + hash_name71    if ident is None:72        ident = u("$pbkdf2-%s$") % (hash_name,)73    base = Pbkdf2DigestHandler74    return type(name, (base,), dict(75        __module__=module, # so ABCMeta won't clobber it.76        name=name,77        ident=ident,78        _digest = hash_name,79        default_rounds=rounds,80        checksum_size=digest_size,81        encoded_checksum_size=(digest_size*4+2)//3,82        __doc__="""This class implements a generic ``PBKDF2-HMAC-%(digest)s``-based password hash, and follows the :ref:`password-hash-api`.83    It supports a variable-length salt, and a variable number of rounds.84    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:85    :type salt: bytes86    :param salt:87        Optional salt bytes.88        If specified, the length must be between 0-1024 bytes.89        If not specified, a %(dsc)d byte salt will be autogenerated (this is recommended).90    :type salt_size: int91    :param salt_size:92        Optional number of bytes to use when autogenerating new salts.93        Defaults to %(dsc)d bytes, but can be any value between 0 and 1024.94    :type rounds: int95    :param rounds:96        Optional number of rounds to use.97        Defaults to %(dr)d, but must be within ``range(1,1<<32)``.98    :type relaxed: bool99    :param relaxed:100        By default, providing an invalid value for one of the other101        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,102        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`103        will be issued instead. Correctable errors include ``rounds``104        that are too small or too large, and ``salt`` strings that are too long.105        .. versionadded:: 1.6106    """ % dict(digest=hash_name.upper(), dsc=base.default_salt_size, dr=rounds)107    ))108#------------------------------------------------------------------------109# derived handlers110#------------------------------------------------------------------------111pbkdf2_sha1 = create_pbkdf2_hash("sha1", 20, 131000, ident=u("$pbkdf2$"))112pbkdf2_sha256 = create_pbkdf2_hash("sha256", 32, 29000)113pbkdf2_sha512 = create_pbkdf2_hash("sha512", 64, 25000)114ldap_pbkdf2_sha1 = uh.PrefixWrapper("ldap_pbkdf2_sha1", pbkdf2_sha1, "{PBKDF2}", "$pbkdf2$", ident=True)115ldap_pbkdf2_sha256 = uh.PrefixWrapper("ldap_pbkdf2_sha256", pbkdf2_sha256, "{PBKDF2-SHA256}", "$pbkdf2-sha256$", ident=True)116ldap_pbkdf2_sha512 = uh.PrefixWrapper("ldap_pbkdf2_sha512", pbkdf2_sha512, "{PBKDF2-SHA512}", "$pbkdf2-sha512$", ident=True)117#=============================================================================118# cryptacular's pbkdf2 hash119#=============================================================================120# bytes used by cta hash for base64 values 63 & 64121CTA_ALTCHARS = b"-_"122class cta_pbkdf2_sha1(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):123    """This class implements Cryptacular's PBKDF2-based crypt algorithm, and follows the :ref:`password-hash-api`.124    It supports a variable-length salt, and a variable number of rounds.125    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:126    :type salt: bytes127    :param salt:128        Optional salt bytes.129        If specified, it may be any length.130        If not specified, a one will be autogenerated (this is recommended).131    :type salt_size: int132    :param salt_size:133        Optional number of bytes to use when autogenerating new salts.134        Defaults to 16 bytes, but can be any value between 0 and 1024.135    :type rounds: int136    :param rounds:137        Optional number of rounds to use.138        Defaults to 60000, must be within ``range(1,1<<32)``.139    :type relaxed: bool140    :param relaxed:141        By default, providing an invalid value for one of the other142        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,143        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`144        will be issued instead. Correctable errors include ``rounds``145        that are too small or too large, and ``salt`` strings that are too long.146        .. versionadded:: 1.6147    """148    #===================================================================149    # class attrs150    #===================================================================151    #--GenericHandler--152    name = "cta_pbkdf2_sha1"153    setting_kwds = ("salt", "salt_size", "rounds")154    ident = u("$p5k2$")155    checksum_size = 20156    # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a157    #       sanity check. underlying algorithm (and reference implementation)158    #       allows effectively unbounded values for both of these parameters.159    #--HasSalt--160    default_salt_size = 16161    max_salt_size = 1024162    #--HasRounds--163    default_rounds = pbkdf2_sha1.default_rounds164    min_rounds = 1165    max_rounds = 0xffffffff # setting at 32-bit limit for now166    rounds_cost = "linear"167    #===================================================================168    # formatting169    #===================================================================170    # hash       $p5k2$1000$ZxK4ZBJCfQg=$jJZVscWtO--p1-xIZl6jhO2LKR0=171    # ident      $p5k2$172    # rounds     1000173    # salt       ZxK4ZBJCfQg=174    # chk        jJZVscWtO--p1-xIZl6jhO2LKR0=175    # NOTE: rounds in hex176    @classmethod177    def from_string(cls, hash):178        # NOTE: passlib deviation - forbidding zero-padded rounds179        rounds, salt, chk = uh.parse_mc3(hash, cls.ident, rounds_base=16, handler=cls)180        salt = b64decode(salt.encode("ascii"), CTA_ALTCHARS)181        if chk:182            chk = b64decode(chk.encode("ascii"), CTA_ALTCHARS)183        return cls(rounds=rounds, salt=salt, checksum=chk)184    def to_string(self):185        salt = b64encode(self.salt, CTA_ALTCHARS).decode("ascii")186        chk = b64encode(self.checksum, CTA_ALTCHARS).decode("ascii")187        return uh.render_mc3(self.ident, self.rounds, salt, chk, rounds_base=16)188    #===================================================================189    # backend190    #===================================================================191    def _calc_checksum(self, secret):192        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8193        return pbkdf2_hmac("sha1", secret, self.salt, self.rounds, 20)194    #===================================================================195    # eoc196    #===================================================================197#=============================================================================198# dlitz's pbkdf2 hash199#=============================================================================200class dlitz_pbkdf2_sha1(uh.HasRounds, uh.HasSalt, uh.GenericHandler):201    """This class implements Dwayne Litzenberger's PBKDF2-based crypt algorithm, and follows the :ref:`password-hash-api`.202    It supports a variable-length salt, and a variable number of rounds.203    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:204    :type salt: str205    :param salt:206        Optional salt string.207        If specified, it may be any length, but must use the characters in the regexp range ``[./0-9A-Za-z]``.208        If not specified, a 16 character salt will be autogenerated (this is recommended).209    :type salt_size: int210    :param salt_size:211        Optional number of bytes to use when autogenerating new salts.212        Defaults to 16 bytes, but can be any value between 0 and 1024.213    :type rounds: int214    :param rounds:215        Optional number of rounds to use.216        Defaults to 60000, must be within ``range(1,1<<32)``.217    :type relaxed: bool218    :param relaxed:219        By default, providing an invalid value for one of the other220        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,221        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`222        will be issued instead. Correctable errors include ``rounds``223        that are too small or too large, and ``salt`` strings that are too long.224        .. versionadded:: 1.6225    """226    #===================================================================227    # class attrs228    #===================================================================229    #--GenericHandler--230    name = "dlitz_pbkdf2_sha1"231    setting_kwds = ("salt", "salt_size", "rounds")232    ident = u("$p5k2$")233    _stub_checksum = u("0" * 48 + "=")234    # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a235    #       sanity check. underlying algorithm (and reference implementation)236    #       allows effectively unbounded values for both of these parameters.237    #--HasSalt--238    default_salt_size = 16239    max_salt_size = 1024240    salt_chars = uh.HASH64_CHARS241    #--HasRounds--242    # NOTE: for security, the default here is set to match pbkdf2_sha1,243    #       even though this hash's extra block makes it twice as slow.244    default_rounds = pbkdf2_sha1.default_rounds245    min_rounds = 1246    max_rounds = 0xffffffff # setting at 32-bit limit for now247    rounds_cost = "linear"248    #===================================================================249    # formatting250    #===================================================================251    # hash       $p5k2$c$u9HvcT4d$Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g252    # ident      $p5k2$253    # rounds     c254    # salt       u9HvcT4d255    # chk        Sd1gwSVCLZYAuqZ25piRnbBEoAesaa/g256    # rounds in lowercase hex, no zero padding257    @classmethod258    def from_string(cls, hash):259        rounds, salt, chk = uh.parse_mc3(hash, cls.ident, rounds_base=16,260                                         default_rounds=400, handler=cls)261        return cls(rounds=rounds, salt=salt, checksum=chk)262    def to_string(self):263        rounds = self.rounds264        if rounds == 400:265            rounds = None # omit rounds measurement if == 400266        return uh.render_mc3(self.ident, rounds, self.salt, self.checksum, rounds_base=16)267    def _get_config(self):268        rounds = self.rounds269        if rounds == 400:270            rounds = None # omit rounds measurement if == 400271        return uh.render_mc3(self.ident, rounds, self.salt, None, rounds_base=16)272    #===================================================================273    # backend274    #===================================================================275    def _calc_checksum(self, secret):276        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8277        salt = self._get_config()278        result = pbkdf2_hmac("sha1", secret, salt, self.rounds, 24)279        return ab64_encode(result).decode("ascii")280    #===================================================================281    # eoc282    #===================================================================283#=============================================================================284# crowd285#=============================================================================286class atlassian_pbkdf2_sha1(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):287    """This class implements the PBKDF2 hash used by Atlassian.288    It supports a fixed-length salt, and a fixed number of rounds.289    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:290    :type salt: bytes291    :param salt:292        Optional salt bytes.293        If specified, the length must be exactly 16 bytes.294        If not specified, a salt will be autogenerated (this is recommended).295    :type relaxed: bool296    :param relaxed:297        By default, providing an invalid value for one of the other298        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,299        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`300        will be issued instead. Correctable errors include301        ``salt`` strings that are too long.302        .. versionadded:: 1.6303    """304    #--GenericHandler--305    name = "atlassian_pbkdf2_sha1"306    setting_kwds =("salt",)307    ident = u("{PKCS5S2}")308    checksum_size = 32309    #--HasRawSalt--310    min_salt_size = max_salt_size = 16311    @classmethod312    def from_string(cls, hash):313        hash = to_unicode(hash, "ascii", "hash")314        ident = cls.ident315        if not hash.startswith(ident):316            raise uh.exc.InvalidHashError(cls)317        data = b64decode(hash[len(ident):].encode("ascii"))318        salt, chk = data[:16], data[16:]319        return cls(salt=salt, checksum=chk)320    def to_string(self):321        data = self.salt + self.checksum322        hash = self.ident + b64encode(data).decode("ascii")323        return uascii_to_str(hash)324    def _calc_checksum(self, secret):325        # TODO: find out what crowd's policy is re: unicode326        # crowd seems to use a fixed number of rounds.327        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8328        return pbkdf2_hmac("sha1", secret, self.salt, 10000, 32)329#=============================================================================330# grub331#=============================================================================332class grub_pbkdf2_sha512(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):333    """This class implements Grub's pbkdf2-hmac-sha512 hash, and follows the :ref:`password-hash-api`.334    It supports a variable-length salt, and a variable number of rounds.335    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:336    :type salt: bytes337    :param salt:338        Optional salt bytes.339        If specified, the length must be between 0-1024 bytes.340        If not specified, a 64 byte salt will be autogenerated (this is recommended).341    :type salt_size: int342    :param salt_size:343        Optional number of bytes to use when autogenerating new salts.344        Defaults to 64 bytes, but can be any value between 0 and 1024.345    :type rounds: int346    :param rounds:347        Optional number of rounds to use.348        Defaults to 19000, but must be within ``range(1,1<<32)``.349    :type relaxed: bool350    :param relaxed:351        By default, providing an invalid value for one of the other352        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,353        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`354        will be issued instead. Correctable errors include ``rounds``355        that are too small or too large, and ``salt`` strings that are too long.356        .. versionadded:: 1.6357    """358    name = "grub_pbkdf2_sha512"359    setting_kwds = ("salt", "salt_size", "rounds")360    ident = u("grub.pbkdf2.sha512.")361    checksum_size = 64362    # NOTE: max_salt_size and max_rounds are arbitrarily chosen to provide a363    #       sanity check. the underlying pbkdf2 specifies no bounds for either,364    #       and it's not clear what grub specifies.365    default_salt_size = 64366    max_salt_size = 1024367    default_rounds = pbkdf2_sha512.default_rounds368    min_rounds = 1369    max_rounds = 0xffffffff # setting at 32-bit limit for now370    rounds_cost = "linear"371    @classmethod372    def from_string(cls, hash):373        rounds, salt, chk = uh.parse_mc3(hash, cls.ident, sep=u("."),374                                         handler=cls)375        salt = unhexlify(salt.encode("ascii"))376        if chk:377            chk = unhexlify(chk.encode("ascii"))378        return cls(rounds=rounds, salt=salt, checksum=chk)379    def to_string(self):380        salt = hexlify(self.salt).decode("ascii").upper()381        chk = hexlify(self.checksum).decode("ascii").upper()382        return uh.render_mc3(self.ident, self.rounds, salt, chk, sep=u("."))383    def _calc_checksum(self, secret):384        # TODO: find out what grub's policy is re: unicode385        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8386        return pbkdf2_hmac("sha512", secret, self.salt, self.rounds, 64)387#=============================================================================388# eof...kellycoinflip.py
Source:kellycoinflip.py  
1import gym2from gym import spaces3from gym.utils import seeding4from gym.spaces import prng5# for Generalized Kelly coinflip game distributions:6from scipy.stats import genpareto7import numpy as np8import numpy.random9def flip(edge, np_random):10    return np_random.uniform() < edge11class KellyCoinflipEnv(gym.Env):12    """The Kelly coinflip game is a simple gambling introduced by Haghani & Dewey 2016's 'Rational Decision-Making Under Uncertainty: Observed Betting Patterns on a Biased Coin' (https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2856963), to test human decision-making in a setting like that of the stock market: positive expected value but highly stochastic; they found many subjects performed badly, often going broke, even though optimal play would reach the maximum with ~95% probability. In the coinflip game, the player starts with $25.00 to gamble over 300 rounds; each round, they can bet anywhere up to their net worth (in penny increments), and then a coin is flipped; with P=0.6, the player wins twice what they bet, otherwise, they lose it. $250 is the maximum players are allowed to have. At the end of the 300 rounds, they keep whatever they have. The human subjects earned an average of $91; a simple use of the Kelly criterion (https://en.wikipedia.org/wiki/Kelly_criterion), giving a strategy of betting 20% until the cap is hit, would earn $240; a decision tree analysis shows that optimal play earns $246 (https://www.gwern.net/Coin-flip). The game short-circuits when either wealth = $0 (since one can never recover) or wealth = cap (trivial optimal play: one simply bets nothing thereafter). In this implementation, we default to the paper settings of $25, 60% odds, wealth cap of $250, and 300 rounds. To specify the action space in advance, we multiply the wealth cap (in dollars) by 100 (to allow for all penny bets); should one attempt to bet more money than one has, it is rounded down to one's net worth. (Alternately, a mistaken bet could end the episode immediately; it's not clear to me which version would be better.) For a harder version which randomizes the 3 key parameters, see the Generalized Kelly coinflip game."""13    metadata = {'render.modes': ['human']}14    def __init__(self, initialWealth=25, edge=0.6, maxWealth=250, maxRounds=300):15        self.action_space = spaces.Discrete(maxWealth*100) # betting in penny increments16        self.observation_space = spaces.Tuple((17            spaces.Box(0, maxWealth, [1]), # (w,b)18            spaces.Discrete(maxRounds+1)))19        self.reward_range = (0, maxWealth)20        self.edge = edge21        self.wealth = initialWealth22        self.initialWealth = initialWealth23        self.maxRounds = maxRounds24        self.maxWealth = maxWealth25        self._seed()26        self._reset()27    def _seed(self, seed=None):28        self.np_random, seed = seeding.np_random(seed)29        return [seed]30    def _step(self, action):31        action = action/100 # convert from pennies to dollars32        if action > self.wealth: # treat attempts to bet more than possess as == betting everything33          action = self.wealth34        if self.wealth <= 0:35            done = True36            reward = 037        else:38          if self.rounds == 0:39            done = True40            reward = self.wealth41          else:42            self.rounds = self.rounds - 143            done = False44            reward = 045            coinflip = flip(self.edge, self.np_random)46            if coinflip:47              self.wealth = min(self.maxWealth, self.wealth + action)48            else:49                self.wealth = self.wealth - action50        return self._get_obs(), reward, done, {}51    def _get_obs(self):52        return (np.array([self.wealth]), self.rounds)53    def _reset(self):54        self.rounds = self.maxRounds55        self.wealth = self.initialWealth56        return self._get_obs()57    def _render(self, mode='human', close=True):58        if close: return59        print("Current wealth: ", self.wealth, "; Rounds left: ", self.rounds)60class KellyCoinflipGeneralizedEnv(gym.Env):61    """The Generalized Kelly coinflip game is an extension by ArthurB & Gwern Branwen which expands the Kelly coinflip game MDP into a POMDP, where the 3 key parameters (edge, maximum wealth, and number of rounds) are unknown random variables drawn from 3 distributions: a Beta(7,3) for the coinflip edge 0-1, a N(300,25) the total number of rounds, and a Pareto(5,200) for the wealth cap. These distributions are chosen to be conjugate & easily updatable, to allow for inference (other choices like the geometric for number of rounds wouldn't make observations informative), and to loosely reflect what a human might expect in the original Kelly coinflip game given that the number of rounds wasn't strictly fixed and they weren't told the wealth cap until they neared it. With these particular distributions, the entire history of the game can be summarized into a few sufficient statistics of rounds-elapsed/wins/losses/max-wealth-ever-reached, from which the Bayes-optimal decision can (in theory) be made; to avoid all agents having to tediously track those sufficient statistics manually in the same way, the observation space is augmented from wealth/rounds-left (rounds-left is deleted because it is a hidden variable) to current-wealth/rounds-elapsed/wins/losses/maximum-observed-wealth. The simple Kelly coinflip game can easily be solved by calculating decision trees, but the Generalized Kelly coinflip game may be intractable (although the analysis for the edge case alone suggests that the Bayes-optimal value may be very close to what one would calculate using a decision tree for any specific case), and represents a good challenge for RL agents."""62    metadata = {'render.modes': ['human']}63    def __init__(self, initialWealth=25, edgePriorAlpha=7, edgePriorBeta=3, maxWealthAlpha=5, maxWealthM=200, maxRoundsMean=300, maxRoundsSD=25, reseed=True):64        # store the hyperparameters for passing back into __init__() during resets so the same hyperparameters govern the next game's parameters, as the user expects: TODO: this is boilerplate, is there any more elegant way to do this?65        self.initialWealth=initialWealth66        self.edgePriorAlpha=edgePriorAlpha67        self.edgePriorBeta=edgePriorBeta68        self.maxWealthAlpha=maxWealthAlpha69        self.maxWealthM=maxWealthM70        self.maxRoundsMean=maxRoundsMean71        self.maxRoundsSD=maxRoundsSD72        # draw this game's set of parameters:73        edge = prng.np_random.beta(edgePriorAlpha, edgePriorBeta)74        maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=prng.np_random))75        maxRounds = round(prng.np_random.normal(maxRoundsMean, maxRoundsSD))76        # add an additional global variable which is the sufficient statistic for the Pareto distribution on wealth cap;77        # alpha doesn't update, but x_m does, and simply is the highest wealth count we've seen to date:78        self.maxEverWealth = initialWealth79        # for the coinflip edge, it is total wins/losses:80        self.wins = 081        self.losses = 082        # for the number of rounds, we need to remember how many rounds we've played:83        self.roundsElapsed = 084        # the rest proceeds as before:85        self.action_space = spaces.Discrete(maxWealth*100)86        self.observation_space = spaces.Tuple((87            spaces.Box(0, maxWealth, shape=[1]), # current wealth88            spaces.Discrete(maxRounds+1), # rounds elapsed89            spaces.Discrete(maxRounds+1), # wins90            spaces.Discrete(maxRounds+1), # losses91            spaces.Box(0, maxWealth, [1]))) # maximum observed wealth92        self.reward_range = (0, maxWealth)93        self.edge = edge94        self.wealth = initialWealth95        self.initialWealth = initialWealth96        self.maxRounds = maxRounds97        self.rounds = self.maxRounds98        self.maxWealth = maxWealth99        if reseed or not hasattr(self, 'np_random') : self._seed()100    def _seed(self, seed=None):101        self.np_random, seed = seeding.np_random(seed)102        return [seed]103    def _step(self, action):104        action = action/100105        if action > self.wealth:106          action = self.wealth107        if self.wealth <= 0:108            done = True109            reward = 0110        else:111          if self.rounds == 0:112            done = True113            reward = self.wealth114          else:115            self.rounds = self.rounds - 1116            done = False117            reward = 0118            coinflip = flip(self.edge, self.np_random)119            self.roundsElapsed = self.roundsElapsed+1120            if coinflip:121              self.wealth = min(self.maxWealth, self.wealth + action)122              self.maxEverWealth = max(self.wealth, self.maxEverWealth)123              self.wins = self.wins+1124            else:125                self.wealth = self.wealth - action126                self.losses = self.losses+1127        return self._get_obs(), reward, done, {}128    def _get_obs(self):129        return (np.array([self.wealth]), self.roundsElapsed, self.wins, self.losses, np.array([self.maxEverWealth]))130    def _reset(self):131        # re-init everything to draw new parameters etc, but preserve the RNG for reproducibility and pass in the same hyperparameters as originally specified:132        self.__init__(initialWealth=self.initialWealth, edgePriorAlpha=self.edgePriorAlpha, edgePriorBeta=self.edgePriorBeta, maxWealthAlpha=self.maxWealthAlpha, maxWealthM=self.maxWealthM, maxRoundsMean=self.maxRoundsMean, maxRoundsSD=self.maxRoundsSD, reseed=False)133        return self._get_obs()134    def _render(self, mode='human', close=True):135        if close: return136        print("Current wealth: ", self.wealth, "; Rounds left: ", self.rounds, "; True edge: ", self.edge,137              "; True max wealth: ", self.maxWealth, "; True stopping time: ", self.maxRounds, "; Rounds left: ",...tournament_model.py
Source:tournament_model.py  
...18        self.time_control = time_control19        self.description = description20        self.id = ''21    def create_tournament(self):22        self.rounds_ids = self.generate_rounds()23        tournament_id = self.t_table.insert(24            {"name": self.name,25             "location": self.location,26             "date_start": self.date_start,27             "date_end": self.date_end,28             "num_of_rounds": self.num_of_rounds,29             "rounds": self.rounds_ids,30             "players": self.players,31             "time_control": self.time_control,32             "description": self.description33             })34        return self.t_table.update(35            {'id': tournament_id}, doc_ids=[tournament_id])[0]36    def save_tournament(self):37        if self.id == '':38            result = self.create_tournament()39        else:40            result = self.t_table.update(41                {"name": self.name,42                 "location": self.location,43                 "date_start": self.date_start,44                 "date_end": self.date_end,45                 "num_of_rounds": self.num_of_rounds,46                 "rounds": self.rounds,47                 "players": self.players,48                 "time_control": self.time_control,49                 "description": self.description,50                 "id": self.id51                 }, doc_ids=[self.id])[0]52        return result53    @staticmethod54    def get_tournament_from_id(id_num):55        tournament = Tournament()56        data = tournament.t_table.get(doc_id=int(id_num))57        tournament.name = data["name"]58        tournament.location = data["location"]59        tournament.date_start = data["date_start"]60        tournament.date_end = data["date_end"]61        tournament.num_of_rounds = data["num_of_rounds"]62        tournament.time_control = data["time_control"]63        tournament.description = data["description"]64        tournament.players = []65        tournament.rounds = []66        tournament.id = id_num67        for player_id in data["players"]:68            player = Player.get_player_from_id(player_id)69            tournament.players.append(player)70        for round_id in data["rounds"]:71            round_ = Round.get_round_from_id(round_id)72            tournament.rounds.append(round_)73        return tournament74    def generate_rounds(self):75        rounds_ids = []76        for i in range(self.num_of_rounds):77            r = Round()78            r.generate_matches()79            round_id = r.create_round(i+1)80            rounds_ids.append(round_id)81        return rounds_ids82    def add_player(self, player):83        self.players.append(player)84    def matches(self):85        matches = []86        for round_ in self.rounds:87            matches.extend(round_.matches)88        return matches...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
