File indexing completed on 2024-04-14 03:59:12

0001 # -*- coding: utf-8 -*-
0002 
0003 """
0004 Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0005 
0006 SPDX-License-Identifier: GPL-2.0
0007 
0008 """
0009 
0010 import weakref
0011 from random import Random
0012 
0013 from util import callers
0014 from common import Debug
0015 
0016 class CountRandomCalls:
0017 
0018     """a helper class for logging count of random calls"""
0019 
0020     def __init__(self, rnd, what):
0021         self.rnd = rnd
0022         self.what = what
0023         self.oldCount = CountingRandom.count
0024 
0025     def __enter__(self):
0026         return self
0027 
0028     def __exit__(self, exc_type, exc_value, trback):
0029         if Debug.random:
0030             self.rnd.game.debug(
0031                 '{} out of {} calls to random by {} from {}'.format(
0032                     CountingRandom.count - self.oldCount,
0033                     CountingRandom.count,
0034                     self.what,
0035                     callers()))
0036 
0037 
0038 class CountingRandom(Random):
0039 
0040     """counts how often random() is called and prints debug info"""
0041 
0042     count = 0
0043 
0044     def __init__(self, game, value=None):
0045         self._game = weakref.ref(game)
0046         Random.__init__(self, value)
0047         CountingRandom.count = 0
0048 
0049     @property
0050     def game(self):
0051         """hide the fact that game is a weakref"""
0052         return self._game()
0053 
0054     def random(self):
0055         """the central randomizator"""
0056         CountingRandom.count += 1
0057         return Random.random(self)
0058 
0059     def seed(self, a=None, version=2):
0060         CountingRandom.count = 0
0061         Random.seed(self, a, version)
0062         if Debug.random:
0063             self.game.debug('Random gets seed %s' % a)
0064 
0065     def randrange(self, start, stop=None, step=1):
0066         with CountRandomCalls(self, 'randrange({},{},step={})'.format(
0067             start, stop, step)):
0068             return Random.randrange(self, start, stop, step)
0069 
0070     def choice(self, seq):
0071         """Choose a random element from a non-empty sequence."""
0072         if len(seq) == 1:
0073             return seq[0]
0074         with CountRandomCalls(self, 'choice({})'.format(seq)):
0075             return Random.choice(self, seq)
0076 
0077     def sample(self, population, k, *, counts=None):
0078         """add debug output to sample. Chooses k unique random elements"""
0079         with CountRandomCalls(self, 'sample({}, {})'.format(population, k)):
0080             return Random.sample(self, population, k, counts=counts)
0081 
0082     def shuffle(self, x):
0083         """add debug output to shuffle. Shuffles list x in place."""
0084         with CountRandomCalls(self, 'shuffle({})'.format(x)):
0085             Random.shuffle(self, x)