示例#1
0
文件: models.py 项目: rangsutu88/Tktr
class Ticket(Persistent):
    id_code = None
    owner = None
    payment = None
    issue_date = None
    creation_date = None
    # __parent__ points at the pool if un-issued, else at owner
    guest_info = None
    change_enabled = False  # Whether or not the guest details can be changed for this ticket
    tick_type = None
    addons = None
    checked_in = None
    checkin_data = None
    notes = None

    def __init__(self):
        coding = Coding()
        self.__name__ = self.id_code = coding.generateUniqueCode()
        self.owner = None
        self.payment = None
        self.issue_date = None
        self.creation_date = datetime.now()
        self.guest_info = None
        self.change_enabled = False
        self.tick_type = None
        self.addons = PersistentMapping()
        self.checked_in = False
        self.checkin_data = None
        self.notes = ""

    def csv(self, admin=False):
        address = self.owner.profile.address
        str_address = "None"
        if address != None:
            str_address = '"%s, %s, %s, %s, %s, %s"' % (
                address.line_one, address.line_two, address.city,
                address.county, address.country, address.postal_code)
        addons_str = "None"
        if self.addons != None and len(self.addons) > 0:
            addon_names = [x.name for x in self.addons.values()]
            addons_str = " + ".join(addon_names)
        if admin:
            return ",".join([
                self.id_code, self.payment.ref_code, self.owner.profile.title,
                self.owner.profile.fullname, self.owner.profile.email,
                self.guest_info.title, self.guest_info.fullname,
                self.guest_info.email, self.tick_type.name, addons_str,
                "%.02f" % (self.total_cost / 100.0),
                self.issue_date.strftime("%d/%m/%Y"), str_address
            ]) + "\n"
        else:
            return ",".join([
                self.id_code, self.payment.ref_code, self.owner.profile.title,
                self.owner.profile.fullname, "HIDDEN", self.guest_info.title,
                self.guest_info.fullname, "HIDDEN", self.tick_type.name,
                addons_str,
                "%.02f" % (self.total_cost / 100.0),
                self.issue_date.strftime("%d/%m/%Y"), "HIDDEN"
            ]) + "\n"

    # Release all add-ons that this ticket holds
    def release_addons(self):
        if self.addons == None:
            self.addons = PersistentMapping()
            return
        to_remove = []
        for addon_key in self.addons:
            addon = self.addons[addon_key]
            addon.allocated.remove(self)
            to_remove.append(addon_key)
        for addon_key in to_remove:
            self.addons.pop(addon_key, None)

    @property
    def addon_cost(self):
        total = 0
        if self.addons != None:
            for addon in self.addons.values():
                total += addon.cost
        return total

    @property
    def total_cost(self):
        return (self.tick_type.cost + self.addon_cost)

    @property
    def checkin_status(self):
        return (hasattr(self, "checked_in") and self.checked_in == True)

    @property
    def locked_down(self):
        locked = self.tick_type.locked_down
        if not locked and self.addons:
            for addon in self.addons.values():
                if addon.locked_down:
                    locked = True
                    break
        return locked
示例#2
0
    def testTheWorld(self):
        # Test constructors
        u = PersistentMapping()
        u0 = PersistentMapping(l0)
        u1 = PersistentMapping(l1)
        u2 = PersistentMapping(l2)

        uu = PersistentMapping(u)
        uu0 = PersistentMapping(u0)
        uu1 = PersistentMapping(u1)
        uu2 = PersistentMapping(u2)

        class OtherMapping:
            def __init__(self, initmapping):
                self.__data = initmapping

            def items(self):
                return self.__data.items()

        v0 = PersistentMapping(OtherMapping(u0))
        vv = PersistentMapping([(0, 0), (1, 1)])

        # Test __repr__
        eq = self.assertEqual

        eq(str(u0), str(l0), "str(u0) == str(l0)")
        eq(repr(u1), repr(l1), "repr(u1) == repr(l1)")
        eq( ` u2 `, ` l2 `, "`u2` == `l2`")

        # Test __cmp__ and __len__

        def mycmp(a, b):
            r = cmp(a, b)
            if r < 0: return -1
            if r > 0: return 1
            return r

        all = [l0, l1, l2, u, u0, u1, u2, uu, uu0, uu1, uu2]
        for a in all:
            for b in all:
                eq(mycmp(a, b), mycmp(len(a), len(b)),
                   "mycmp(a, b) == mycmp(len(a), len(b))")

        # Test __getitem__

        for i in range(len(u2)):
            eq(u2[i], i, "u2[i] == i")

        # Test get

        for i in range(len(u2)):
            eq(u2.get(i), i, "u2.get(i) == i")
            eq(u2.get(i, 5), i, "u2.get(i, 5) == i")

        for i in min(u2) - 1, max(u2) + 1:
            eq(u2.get(i), None, "u2.get(i) == None")
            eq(u2.get(i, 5), 5, "u2.get(i, 5) == 5")

        # Test __setitem__

        uu2[0] = 0
        uu2[1] = 100
        uu2[2] = 200

        # Test __delitem__

        del uu2[1]
        del uu2[0]
        try:
            del uu2[0]
        except KeyError:
            pass
        else:
            raise TestFailed("uu2[0] shouldn't be deletable")

        # Test __contains__
        for i in u2:
            self.failUnless(i in u2, "i in u2")
        for i in min(u2) - 1, max(u2) + 1:
            self.failUnless(i not in u2, "i not in u2")

        # Test update

        l = {"a": "b"}
        u = PersistentMapping(l)
        u.update(u2)
        for i in u:
            self.failUnless(i in l or i in u2, "i in l or i in u2")
        for i in l:
            self.failUnless(i in u, "i in u")
        for i in u2:
            self.failUnless(i in u, "i in u")

        # Test setdefault

        x = u2.setdefault(0, 5)
        eq(x, 0, "u2.setdefault(0, 5) == 0")

        x = u2.setdefault(5, 5)
        eq(x, 5, "u2.setdefault(5, 5) == 5")
        self.failUnless(5 in u2, "5 in u2")

        # Test pop

        x = u2.pop(1)
        eq(x, 1, "u2.pop(1) == 1")
        self.failUnless(1 not in u2, "1 not in u2")

        try:
            u2.pop(1)
        except KeyError:
            pass
        else:
            raise TestFailed("1 should not be poppable from u2")

        x = u2.pop(1, 7)
        eq(x, 7, "u2.pop(1, 7) == 7")

        # Test popitem

        items = u2.items()
        key, value = u2.popitem()
        self.failUnless((key, value) in items, "key, value in items")
        self.failUnless(key not in u2, "key not in u2")

        # Test clear

        u2.clear()
        eq(u2, {}, "u2 == {}")
示例#3
0
class Game(Persistent):
    """
    A Game aggregates the players and matches that are part of a competition. For example, a Game could be 'Football'
    or 'Hockey'
    """
    def __init__(self, name):
        self.name = name
        # Player name -> Player
        self.players = PersistentMapping()
        # List of all matches for this game
        self.matches = PersistentList()
        # Whether to use average instead of sum-of-skill for this game
        self.use_average_team_skill = True

    def delete_match(self, match):
        if not match in self.matches:
            return

        self.matches.remove(match)

        players = match.teams[0] + match.teams[1]
        for p in players:
            if match in p.matches:
                p.matches.remove(match)

        self.recalculate_ratings()

        for p in list(self.players.keys()):
            if not self.players[p].matches:
                self.players.pop(p)

    def add_match(self, teams, score):
        players_a = [self.get_player(name) for name in teams[0]]
        players_b = [self.get_player(name) for name in teams[1]]

        # Add Match to the Database
        match = Match(self, [players_a, players_b], score)
        self.matches.append(match)

        self.update_player_ratings(match)
        match.update_rating_delta()

    def update_player_ratings(self, match):
        ratings_a = [p.get_rating() for p in match.teams[0]]
        ratings_b = [p.get_rating() for p in match.teams[1]]

        # Sort by score and get rank indices
        rank = list(zip(match.score, range(len(match.score))))
        rank.sort(key=lambda r: r[0], reverse=True)
        rank_indices = list(zip(*rank))[1]

        # Check for Draw
        # TODO: make this generic for more than 2 teams
        if match.score[0] == match.score[1]:
            rank_indices = [0, 0]

        # Calculate new Ratings using trueskill algorithm
        new_ratings = trueskill.rate([ratings_a, ratings_b],
                                     ranks=rank_indices,
                                     weights=self.team_weights(
                                         ratings_a, ratings_b))

        for r, p in zip(new_ratings[0], match.teams[0]):
            p.set_rating(r)
            p.add_match(match)

        for r, p in zip(new_ratings[1], match.teams[1]):
            p.set_rating(r)
            p.add_match(match)

    def recalculate_ratings(self):
        for player in self.players.values():
            player.reset_rating()
            player.matches.clear()
            player.history.clear()

        for match in self.matches:
            match.init_stats()
            self.update_player_ratings(match)
            match.update_rating_delta()

    def get_player(self, name):
        if not name in self.players:
            self.players[name] = Player(name)

        return self.players[name]

    # Calcualte player weights for a match based on whether average or additive ratings
    # are used for this game
    def team_weights(self, team1, team2):
        ratings = [team1, team2]
        weights = [[1 for _ in r] for r in ratings]
        if self.use_average_team_skill:
            # Adjust weights by team-size. This effectively causes the TrueSkill algorithm to
            # look at the average instead of the sum of skills
            min_team_size = min(map(len, ratings))
            weights = [[min_team_size / float(len(r)) for _ in r]
                       for r in ratings]
        return weights

    def win_probability(self, team1, team2):
        """"
        Calculate the win probability of team1 over team2 given the skill ratings of
        all the players in the teams.
        """
        def skill_sum(team, weights):
            return sum([v.skill() * w for (v, w) in zip(team, weights)])

        weights = self.team_weights(team1, team2)
        delta_mu = skill_sum(team1, weights[0]) - skill_sum(team2, weights[1])
        sum_sigma = sum((r.confidence() * w)**2 for (
            r,
            w) in zip(itertools.chain(team1, team2), itertools.chain(
                *weights)))
        size = len(team1) + len(team2)
        denom = math.sqrt(size * (trueskill.BETA * trueskill.BETA) + sum_sigma)
        ts = trueskill.global_env()
        return ts.cdf(delta_mu / denom)

    def draw_probability(self, team1, team2):
        r1 = [p.get_rating() for p in team1]
        r2 = [p.get_rating() for p in team2]
        return trueskill.quality([r1, r2],
                                 weights=self.team_weights(team1, team2))
示例#4
0
class Box(Persistent):
    implements(IDepositBox)

    def __init__(self, max_age=config.MAX_AGE, purge_days=config.PURGE_DAYS):
        self.data = PersistentMapping()
        self._last_purge = int(time.time())
        self.max_age = max_age
        self.purge_days = purge_days

    def _generate_new_id(self):
        """Generate new id.
        """
        new_id = id_generator()
        while new_id in self.data.keys():
            new_id = id_generator()
        return new_id

    def put(self, value, token=None):
        """Put value in box, with optional token, and return generated id.

        Calling this method also does a purge once a day (well, when
        the last purge was at least 24 hours ago).  The frequency can
        be controlled with the purge_days attribute.
        """
        cutoff = int(time.time()) - (self.purge_days * 86400)
        if self._last_purge < cutoff:
            self.purge()

        if value is None:
            raise ValueError
        id = self._generate_new_id()
        self.data[id] = BoxItem(token, value, confirmed=False)
        return id

    def edit(self, secret, value, token=None):
        """Edit value in the box, when secret and optional token match.
        """
        if value is None:
            raise ValueError
        stored = self.get(secret, token=token)
        if value == stored:
            # No change
            return
        self.data[secret] = BoxItem(token, value, confirmed=True)

    def get(self, secret, token=None):
        stored = self.data.get(secret)
        if stored is None:
            return None
        if stored.token != token:
            # raise Exception
            return None
        if not stored.confirmed:
            # Purge this item when it is expired:
            cutoff = int(time.time()) - self.max_age * 86400
            if stored.timestamp < cutoff:
                del self.data[secret]
                return None
            if token:
                # When there is a token, the item must be confirmed
                # before we return the value.  Main use case: email
                # confirmation.
                return None
        return stored.value

    def confirm(self, secret, token=None):
        """Confirm the item/token and return whether this succeeded or not.
        """
        stored = self.data.get(secret)
        if stored is None:
            return None
        if stored.token != token:
            # raise Exception?
            return None
        if not stored.confirmed:
            # First check if the confirmation comes too late.
            cutoff = int(time.time()) - self.max_age * 86400
            if stored.timestamp < cutoff:
                del self.data[secret]
                # Report back that we have failed, in case anyone
                # wants to know.
                return False
        stored.confirmed = True
        return True

    def pop(self, secret, token=None):
        stored = self.get(secret, token=token)
        if stored is None:
            return None
        self.data.pop(secret)
        return stored

    def get_all_confirmed(self):
        for key, stored in self.data.items():
            if stored.confirmed:
                yield stored.value

    def purge(self):
        """Purge items that have expired.

        Confirmed items are not purged.
        """
        cutoff = int(time.time()) - self.max_age * 86400
        logger.info("Started purging data.")
        for key, stored in self.data.items():
            if not stored.confirmed and stored.timestamp < cutoff:
                logger.info("Purged data with secret %r", key)
                del self.data[key]
        self._last_purge = int(time.time())
        logger.info("Finished purging data.")