Beispiel #1
0
class Jam(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(128), unique=True)
    title = db.Column(db.String(128), unique=True)
    theme = db.Column(db.String(128))
    announced = db.Column(db.DateTime)  # Date on which the jam was announced
    start_time = db.Column(db.DateTime)  # The jam starts at this moment
    team_limit = db.Column(db.Integer)  # 0 = no limit
    games = db.relationship('Game', backref="jam", lazy="subquery")
    participations = db.relationship("Participation",
                                     backref="jam",
                                     lazy="subquery")
    teams = db.relationship("Team", backref="jam", lazy="subquery")

    description = db.Column(db.Text)
    restrictions = db.Column(db.Text)

    registration_duration = db.Column(db.Integer)  # hours
    packaging_duration = db.Column(db.Integer)  # hours
    rating_duration = db.Column(db.Integer)  # hours
    duration = db.Column(db.Integer)  # hours

    # last notification that was sent, e.g. 0 = announcement, 1 = registration, (see status codes)
    last_notification_sent = db.Column(db.Integer, default=-1)

    def __init__(self, title, start_time, duration=48, team_limit=0, theme=''):
        self.title = title
        self.slug = get_slug(title)
        self.start_time = start_time
        self.duration = duration
        self.registration_duration = 24 * 14
        self.packaging_duration = 24 * 1
        self.rating_duration = 24 * 5
        self.announced = datetime.utcnow()
        self.theme = theme
        self.team_limit = team_limit

    @property
    def participants(self):
        return [r.user for r in self.participations]

    @property
    def end_time(self):
        return self.start_time + timedelta(hours=self.duration)

    @property
    def packaging_deadline(self):
        return self.end_time + timedelta(hours=self.packaging_duration)

    @property
    def rating_end(self):
        return self.packaging_deadline + timedelta(hours=self.rating_duration)

    @property
    def registration_start(self):
        return self.start_time - timedelta(hours=self.registration_duration)

    def __repr__(self):
        return f"<Jam {self.slug}>"

    def get_status(self):
        now = datetime.utcnow()
        if self.registration_start > now:
            return JamStatus(JamStatusCode.ANNOUNCED, self.start_time)
        elif self.start_time > now:
            return JamStatus(JamStatusCode.REGISTRATION, self.start_time)
        elif self.end_time > now:
            return JamStatus(JamStatusCode.RUNNING, self.end_time)
        elif self.packaging_deadline > now:
            return JamStatus(JamStatusCode.PACKAGING, self.packaging_deadline)
        elif self.rating_end > now:
            return JamStatus(JamStatusCode.RATING, self.rating_end)
        else:
            return JamStatus(JamStatusCode.FINISHED, self.end_time)

    def url(self, **kwargs):
        return url_for('jam_info', jam_slug=self.slug, **kwargs)

    def games_filtered_by_package_types(self, filters):
        games = Game.query.filter_by(is_deleted=False).filter_by(
            jam_id=self.id)
        if filters == set():
            games = games
        elif 'packaged' in filters:
            games = games.join(GamePackage)
        else:
            games = games.filter(
                GamePackage.type.in_(filters)).join(GamePackage)
        return games.all()

    def games_by_score(self, filters=set()):
        e = self.games_filtered_by_package_types(filters)
        e.sort(key=Game.score.fget, reverse=True)
        return e

    def games_by_total_ratings(self, filters=set()):
        e = self.games_filtered_by_package_types(filters)
        e.sort(key=Game.number_ratings.fget)
        return e

    @property
    def show_theme(self):
        return self.get_status().code >= JamStatusCode.RUNNING and self.theme

    @property
    def show_ratings(self):
        return self.get_status().code == JamStatusCode.FINISHED

    def get_link(self):
        s = f'<a class="jam" href="{self.url()}">{self.title}</a>'
        if self.show_theme:
            s += f' <span class="theme">{self.theme}</span>'
        return Markup(s)

    def send_all_notifications(self):
        last = -1
        for n in range(self.last_notification_sent + 1,
                       self.get_status().code + 1):
            if self.send_notification(n):
                last = n
        return last

    def send_notification(self, n):
        if not JamStatusCode.ANNOUNCED <= n <= JamStatusCode.FINISHED:
            return False

        kwargs = {}

        if n == JamStatusCode.ANNOUNCED:
            template = "announcement"
            notify = "new_jam"
            subject = f"Jam announced: {self.title}"
        elif n == JamStatusCode.REGISTRATION:
            template = "registration_start"
            notify = "new_jam"
            subject = f"Registrations for {self.title} now open"
        elif n == JamStatusCode.RUNNING:
            template = "start"
            notify = "jam_start"
            subject = f"{self.title} starts now!"
        elif n == JamStatusCode.PACKAGING:
            template = "packaging_start"
            notify = "jam_finish"
            subject = f"{self.title} is over"
        elif n == JamStatusCode.RATING:
            template = "rating_start"
            notify = "jam_finish"
            subject = f"Rating for {self.title} starts now"
        elif n == JamStatusCode.FINISHED:
            template = "finished"
            notify = "jam_finish"
            subject = f"Rating for {self.title} finished - Winners"
            kwargs = {"games": self.games_by_score()[:3]}

        if n >= JamStatusCode.RUNNING and n != JamStatusCode.RATING:
            users = [r.user for r in self.participations]
        else:
            from flamejam.models.user import User
            users = User.query.all()

        # Set this first because we might send for longer than a minute at which point the
        # next tick will come around.
        self.last_notification_sent = n
        db.session.commit()

        subject = app.config["LONG_NAME"] + ": " + subject

        with mail.connect() as conn:
            for user in users:
                if getattr(user, "notify_" + notify):
                    body = render_template("emails/jam/" + template + ".txt",
                                           recipient=user,
                                           jam=self,
                                           **kwargs)
                    sender = app.config['MAIL_DEFAULT_SENDER']
                    recipients = [user.email]
                    message = Message(subject=subject,
                                      sender=sender,
                                      body=body,
                                      recipients=recipients)
                    try:
                        conn.send(message)
                    except SMTPRecipientsRefused:
                        pass
        return True

    @property
    def livestream_teams(self):
        return [t for t in self.teams if t.livestream]
Beispiel #2
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    password = db.Column(db.LargeBinary())
    token = db.Column(db.BigInteger, nullable=True, default=None)
    email = db.Column(db.String(191), unique=True)
    new_email = db.Column(db.String(191), unique=True)
    is_admin = db.Column(db.Boolean, default=False)
    is_verified = db.Column(db.Boolean)
    is_deleted = db.Column(db.Boolean, default=False)
    registered = db.Column(db.DateTime)
    ratings = db.relationship('Rating', backref='user', lazy="dynamic")
    comments = db.relationship('Comment', backref='user', lazy="dynamic")
    invitations = db.relationship("Invitation", backref="user", lazy="dynamic")
    participations = db.relationship("Participation", backref=db.backref("user", lazy="joined"), lazy="subquery")

    ability_programmer = db.Column(db.Boolean)
    ability_gamedesigner = db.Column(db.Boolean)
    ability_2dartist = db.Column(db.Boolean)
    ability_3dartist = db.Column(db.Boolean)
    ability_composer = db.Column(db.Boolean)
    ability_sounddesigner = db.Column(db.Boolean)
    abilities_extra = db.Column(db.String(128))
    location = db.Column(db.String(128))
    location_coords = db.Column(db.String(128))
    location_display = db.Column(db.String(128))
    location_flag = db.Column(db.String(16), default="unknown")
    real_name = db.Column(db.String(128))
    about = db.Column(db.Text)
    website = db.Column(db.String(128))
    avatar = db.Column(db.String(128))

    pm_mode = db.Column(db.Enum("email", "form", "disabled"), default="form")

    notify_new_jam = db.Column(db.Boolean, default=True)
    notify_jam_start = db.Column(db.Boolean, default=True)
    notify_jam_finish = db.Column(db.Boolean, default=True)
    notify_game_comment = db.Column(db.Boolean, default=True)
    notify_team_invitation = db.Column(db.Boolean, default=True)
    notify_newsletter = db.Column(db.Boolean, default=True)

    def __init__(self, username, password, email, is_admin=False, is_verified=False):
        self.username = username
        self.password = hash_password(password)
        self.email = email
        self.new_email = email
        self.is_admin = is_admin
        self.is_verified = is_verified
        self.registered = datetime.utcnow()

    @property
    def is_active(self):
        return self.is_verified

    @property
    def is_anonymous(self):
        return False

    @property
    def is_authenticated(self):
        return True

    def __repr__(self):
        return '<User %r>' % self.username

    def get_id(self):
        return self.id

    def getVerificationHash(self):
        # combine a few properties, hash it
        # take first 16 chars for simplicity
        # make it email specific
        hash = scrypt.hash(str(self.username) + str(self.new_email), app.config['SECRET_KEY'])
        return hash.encode('hex')[:16]

    def getResetToken(self):
        # combine a few properties, hash it
        # take first 16 chars for simplicity
        hash = scrypt.hash(str(self.token), app.config['SECRET_KEY'])
        return hash.encode('hex')[:16]

    def ratedGame(self, game):
        return self.ratings.filter_by(game=game).first() != None

    def getRatingCount(self, jam):
        i = 0
        for r in self.ratings:
            if r.game.jam == jam:
                i += 1
        return i

    @property
    def games(self):
        g = []
        for p in self.participations:
            if p.team:
                for game in p.team.games:
                    if not game.is_deleted:
                        g.append(game)

        import operator
        g.sort(key=operator.attrgetter("created"))

        return g

    def url(self, **values):
        return url_for('show_user', username=self.username, **values)

    def getAvatar(self, size=32):
        if self.avatar:
            return self.avatar.replace("%s", str(size))
        return "//gravatar.com/avatar/{0}?s={1}&d=identicon".format(md5(self.email.lower()).hexdigest(), size)

    def setLocation(self, location):
        if not location:
            self.location = ""
            self.location_display = ""
            self.location_coords = ""
            self.location_flag = "unknown"
            return True

        new_loc, new_coords, new_flag = findLocation(location)
        if not new_loc:
            return False
        self.location = location
        self.location_display = new_loc
        self.location_coords = new_coords
        self.location_flag = new_flag
        return True

    def getLocation(self):
        return Markup('<span class="location"><span class="flag %s"></span> <span class="city">%s</span></span>' % (self.location_flag, self.location_display or "n/a"))

    def getLink(self, class_ = "", real = True, avatar = True):
        if self.is_deleted:
            return Markup('<span class="user deleted">[DELETED]</span>')

        s = 16
        if self.is_admin:
            class_ += " admin"

        link = ''
        link += '<a class="user {0}" href="{1}">'.format(class_, self.url())
        if avatar:
            link += '<img width="{0}" height="{0}" src="{1}" class="icon"/> '.format(s, self.getAvatar(s))
        link += '<span class="name"><span class="username">{0}</span>'.format(self.username)
        link += u' <span class="real">({0})</span>'.format(self.real_name) if self.real_name and real else ''
        link += '</span></a>'

        return Markup(link)

    @property
    def abilities(self):
        a = []
        if self.ability_programmer:
            a.append("Programming")
        if self.ability_gamedesigner:
            a.append("Game Design")
        if self.ability_2dartist:
            a.append("Graphics / 2D Art")
        if self.ability_3dartist:
            a.append("Modelling / 3D Art")
        if self.ability_composer:
            a.append("Composing")
        if self.ability_sounddesigner:
            a.append("Sound Design")
        return a

    def abilityString(self):
        a = ", ".join(self.abilities)
        if self.abilities_extra:
            a += '<div class="ability-extra">' + self.abilities_extra + '</div>'
        return a

    def getParticipation(self, jam):
        return Participation.query.filter_by(user_id = self.id, jam_id = jam.id).first()

    def getTeam(self, jam):
        p = self.getParticipation(jam)
        return p.team if p and p.team else None

    def inTeam(self, team):
        return self in team.members

    def canRate(self, game):
        return not self.inTeam(game.team)

    def canEdit(self, game):
        return self.inTeam(game.team)

    def joinJam(self, jam, generateTeam = True):
        p = Participation(self, jam)
        db.session.add(p)
        db.session.commit() # need to commit so the team does not register us automatically

        if generateTeam:
            self.generateTeam(jam)
        else:
            db.session.commit()

    def generateTeam(self, jam):
        t = Team(self, jam)
        db.session.add(t)
        db.session.commit()

    def leaveJam(self, jam):
        # leave team
        if self.getTeam(jam):
            self.getTeam(jam).userLeave(self) #  will destroy the team if then empty

        # delete registration
        if self.getParticipation(jam):
            db.session.delete(self.getParticipation(jam))

    def numberOfGames(self):
        return len(self.games)

    @property
    def openInvitations(self):
        invitations = []
        for invitation in self.invitations:
            if invitation.canAccept():
                invitations.append(invitation)
        return invitations
Beispiel #3
0
class Team(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    jam_id = db.Column(db.Integer, db.ForeignKey("jam.id"))
    name = db.Column(db.String(80))

    description = db.Column(db.Text)
    livestreams = db.Column(db.Text)  # list of livestreams, one URL per file
    irc = db.Column(db.String(128))

    participations = db.relationship("Participation",
                                     backref="team",
                                     lazy="subquery")
    invitations = db.relationship("Invitation",
                                  backref="team",
                                  lazy="subquery")
    games = db.relationship("Game", backref="team", lazy="subquery")

    def __init__(self, user, jam):
        self.jam = jam
        self.user_join(user)
        self.name = user.username + "'s team"

    @property
    def members(self):
        return [r.user for r in self.participations]

    @property
    def game(self):
        return self.games[0] if self.games else None

    @property
    def is_single_team(self):
        return len(self.participations) == 1

    def url(self, **kwargs):
        return url_for("jam_team",
                       jam_slug=self.jam.slug,
                       team_id=self.id,
                       **kwargs)

    def user_join(self, user):
        r = user.get_participation(self.jam)
        if not r:
            # register user, but do not create automatic team, we don't need
            # that anyway
            user.join_jam(self.jam, False)
        elif r in self.participations:
            return  # user is already in this team
        elif r.team and r.team != self:
            r.team.user_leave(user)

        r.team = self
        db.session.commit()

    def user_leave(self, user):
        r = user.get_participation(self.jam)

        if r.team != self:
            return  # not in this team, nevermind ;)

        if self.is_single_team:
            # only user in team, we can destroy this team
            self.destroy()

        r.team = None
        db.session.commit()

    def destroy(self):
        # also destroy all the games, invitations
        for game in self.games:
            game.destroy()
        for invitation in self.invitations:
            db.session.delete(invitation)
        db.session.delete(self)

    @property
    def number_members_and_invitations(self):
        return len(self.members) + len(self.invitations)

    def can_invite(self, user):
        return user in self.members and (
            self.jam.team_limit == 0
            or self.jam.team_limit > self.number_members_and_invitations)

    def get_invitation(self, user):
        return Invitation.query.filter_by(user_id=user.id,
                                          team_id=self.id).first()

    def invite_user(self, user,
                    sender):  # sender: which user sent the invitation
        if not user.notify_team_invitation:
            return None

        if self.get_invitation(user):
            i = self.get_invitation(user)  # already invited
        else:
            i = Invitation(self, user)
            db.session.add(i)
            db.session.commit()
            body = render_template("emails/invitation.txt",
                                   team=self,
                                   sender=sender,
                                   recipient=user,
                                   invitation=i)
            mail.send_message(subject=app.config["LONG_NAME"] +
                              ": You have been invited to " + self.name,
                              recipients=[user.email],
                              body=body)
        return i
Beispiel #4
0
class Participant(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    password = db.Column(db.String(128))
    token = db.Column(db.Integer, nullable=True, default=None)
    email = db.Column(db.String(256), unique=True)
    is_admin = db.Column(db.Boolean, default=False)
    is_verified = db.Column(db.Boolean)
    receive_emails = db.Column(db.Boolean)
    registered = db.Column(db.DateTime)
    entries = db.relationship('Entry', backref='participant', lazy='dynamic')
    team_entries = db.relationship("Entry",
                                   secondary=team_members,
                                   backref="team")
    ratings = db.relationship('Rating', backref='participant', lazy='dynamic')
    comments = db.relationship('Comment',
                               backref='participant',
                               lazy='dynamic')
    jams = db.relationship('Jam', backref='author', lazy='dynamic')
    rating_skips = db.relationship('RatingSkip',
                                   backref='participant',
                                   lazy='dynamic')
    ratings = db.relationship('Rating', backref='participant', lazy='dynamic')

    def __init__(self,
                 username,
                 password,
                 email,
                 is_admin=False,
                 is_verified=False,
                 receive_emails=True):
        self.username = username
        self.password = sha512(
            (password + app.config['SECRET_KEY']).encode('utf-8')).hexdigest()
        self.email = email
        self.is_admin = is_admin
        self.is_verified = is_verified
        self.registered = datetime.utcnow()
        self.receive_emails = receive_emails

    def getVerificationHash(self):
        # combine a few properties, hash md5
        # take first 8 chars for simplicity
        return md5(self.username + self.password +
                   app.config['SECRET_KEY']).hexdigest()[:8]

    def getResetToken(self):
        # combine a few properties, hash md5
        # take first 8 chars for simplicity
        return md5(str(self.token) + app.config['SECRET_KEY']).hexdigest()[:8]

    def skippedEntry(self, entry):
        return self.rating_skips.filter_by(entry=entry).first() != None

    def ratedEntry(self, entry):
        return self.ratings.filter_by(entry=entry).first() != None

    def getRatingCount(self, jam):
        i = 0
        for r in self.ratings:
            if r.entry.jam == jam:
                i += 1
        return i

    def getTotalEntryCount(self):
        return len(self.entries.all()) + len(self.team_entries)

    def getSkippedCount(self, jam):
        return len(
            self.rating_skips.filter(RatingSkip.participant_id == self.id
                                     and Entry.jam_id == jam.id).all())

    def __repr__(self):
        return '<User %r>' % self.username

    def url(self, **values):
        return url_for('show_participant', username=self.username, **values)

    def getAvatar(self, size=32):
        return "http://www.gravatar.com/avatar/{0}?s={1}&d=retro".format(
            md5(self.email.lower()).hexdigest(), size)

    def getLink(self, class_=""):
        s = 14
        if self.is_admin:
            class_ += " admin"
        return Markup(
            '<a class="user {4}" href="{0}"><img width="{2}" height="{2}" src="{3}" class="icon"/> {1}</a>'
            .format(self.url(), self.username, s, self.getAvatar(s), class_))

    def canRate(self, entry):
        return entry.participant != self and not self in entry.team

    def canEdit(self, entry):
        return entry.participant == self

    def getEntryInJam(self, jam):
        for entry in self.entries:
            if entry.jam == jam:
                return entry
        return None

    def getTeamEntryInJam(self, jam):
        for entry in self.team_entries:
            if entry.jam == jam:
                return entry
        return None
Beispiel #5
0
class Entry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128))
    slug = db.Column(db.String(128))
    description = db.Column(db.Text)
    posted = db.Column(db.DateTime)
    jam_id = db.Column(db.Integer, db.ForeignKey('jam.id'))
    participant_id = db.Column(db.Integer, db.ForeignKey('participant.id'))
    rating_skips = db.relationship('RatingSkip',
                                   backref='entry',
                                   lazy='dynamic')
    ratings = db.relationship('Rating', backref='entry', lazy='dynamic')
    comments = db.relationship('Comment', backref='entry', lazy='dynamic')
    packages = db.relationship('EntryPackage', backref='entry', lazy='dynamic')
    screenshots = db.relationship('EntryScreenshot',
                                  backref='entry',
                                  lazy='dynamic')

    def __init__(self, title, description, jam, participant):
        self.title = title
        self.slug = get_slug(title)
        self.description = description
        self.jam = jam
        self.participant = participant
        self.posted = datetime.utcnow()

    def __repr__(self):
        return '<Entry %r>' % self.title

    def url(self, action="", **values):
        return url_for("show_entry",
                       jam_slug=self.jam.slug,
                       entry_slug=self.slug,
                       action=action,
                       **values)

    def getAverageRating(self):
        categories = [
            "gameplay", "graphics", "audio", "innovation", "story",
            "technical", "controls", "overall"
        ]
        r = {"average": 0}

        for c in categories:
            r[c] = 0

        ratings = len(self.ratings.all())
        if ratings > 0:
            for rating in self.ratings:
                for c in categories:
                    r[c] += getattr(rating, "score_" + c)
                r["average"] += rating.getAverage()

            for c in categories:
                r[c] *= 1.0 / ratings
            r["average"] *= 1.0 / ratings
        return r

    def getTotalScore(self):
        s = 0
        c = 0
        av = self.getAverageRating()
        for x in av:
            s += av[x]
            c += 1
        return s * 1.0 / c

    def getRank(self):
        jam_entries = list(self.jam.entries.all())
        jam_entries.sort(cmp=entryCompare)
        return jam_entries.index(self) + 1
Beispiel #6
0
class Jam(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String(128), unique=True)
    title = db.Column(db.String(128), unique=True)
    theme = db.Column(db.String(128))
    announced = db.Column(db.DateTime)  # Date on which the jam was announced
    start_time = db.Column(db.DateTime)  # The jam starts at this moment
    end_time = db.Column(db.DateTime)  # The jamming phase ends at this moment
    packaging_deadline = db.Column(
        db.DateTime)  # Packaging ends at this moment
    rating_end = db.Column(db.DateTime)  # Rating period ends and jam is over
    team_jam = db.Column(db.Boolean)
    entries = db.relationship('Entry', backref='jam', lazy='dynamic')
    author_id = db.Column(db.Integer, db.ForeignKey('participant.id'))

    def __init__(self,
                 title,
                 author,
                 start_time,
                 end_time=None,
                 packaging_deadline=None,
                 voting_end=None,
                 team_jam=False,
                 theme=''):
        self.title = title
        self.slug = get_slug(title)
        self.start_time = start_time
        self.theme = theme
        self.author = author
        self.team_jam = team_jam

        if end_time is None:
            self.end_time = start_time + timedelta(days=2)
        else:
            self.end_time = end_time

        if packaging_deadline is None:
            self.packaging_deadline = start_time + timedelta(days=3)
        else:
            self.packaging_deadline = packaging_deadline

        if self.rating_end is None:
            self.rating_end = start_time + timedelta(days=7)
        else:
            self.rating_end = rating_end

        self.announced = datetime.utcnow()

    def __repr__(self):
        return '<Jam %r>' % self.slug

    def getStatus(self):
        now = datetime.utcnow()
        if self.start_time > now:
            return JamStatus(JamStatusCode.ANNOUNCED, self.start_time)
        elif self.end_time > now:
            return JamStatus(JamStatusCode.RUNNING, self.end_time)
        elif self.packaging_deadline > now:
            return JamStatus(JamStatusCode.PACKAGING, self.packaging_deadline)
        elif self.rating_end > now:
            return JamStatus(JamStatusCode.RATING, self.rating_end)
        else:
            return JamStatus(JamStatusCode.FINISHED, self.end_time)

    def url(self, **values):
        return url_for('show_jam', jam_slug=self.slug, **values)

    def getTopEntries(self):
        e = list(self.entries.all())
        e.sort(cmp=entryCompare)
        return e

    def getShuffledEntries(self):
        e = list(self.entries.all())
        random.shuffle(e)
        return e
Beispiel #7
0
class Game(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128))
    slug = db.Column(db.String(128))
    created = db.Column(db.DateTime)
    description = db.Column(db.Text)
    technology = db.Column(db.Text)
    help = db.Column(db.Text)
    is_deleted = db.Column(db.Boolean, default=False)
    has_cheated = db.Column(db.Boolean, default=False)

    jam_id = db.Column(db.Integer, db.ForeignKey('jam.id'))
    team_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    ratings = db.relationship('Rating', backref='game', lazy="subquery")
    comments = db.relationship('Comment', backref='game', lazy="subquery")
    packages = db.relationship('GamePackage', backref='game', lazy="subquery")
    screenshots = db.relationship('GameScreenshot',
                                  backref='game',
                                  lazy="subquery")

    def __init__(self, team, title):
        self.team = team
        self.jam = team.jam
        self.title = title
        self.slug = get_slug(title)
        self.created = datetime.utcnow()

    def __repr__(self):
        return f"<Game {self.title}>"

    def destroy(self):
        # destroy all ratings, comments, packages, screenshots
        for rating in self.ratings:
            db.session.delete(rating)
        for comment in self.comments:
            db.session.delete(comment)
        for package in self.packages:
            db.session.delete(package)
        for screenshot in self.screenshots:
            db.session.delete(screenshot)
        db.session.delete(self)

    def url(self, **kwargs):
        return url_for("show_game",
                       jam_slug=self.jam.slug,
                       game_id=self.id,
                       **kwargs)

    @property
    def screenshots_ordered(self):
        return sorted(self.screenshots, key=lambda s: s.index)

    @property
    def score(self):
        if self.has_cheated:
            return -10

        return average(
            [r.score for r in self.ratings if not r.user.is_deleted]) or 0

    def feedback_average(self, category):
        if category in (None, "overall"):
            return self.score
        return average_non_zero([r.get(category) for r in self.ratings])

    @property
    def rank(self):
        jam_games = list(self.jam.games.all())
        jam_games.sort(key="score", reverse=True)
        return jam_games.index(self) + 1

    @property
    def number_ratings(self):
        return len(self.ratings)

    @property
    def rating_categories(self):
        return [
            c for c in RATING_CATEGORIES
            if getattr(self, "score_" + c + "_enabled")
        ]

    def get_rating_by_user(self, user):
        return Rating.query.filter_by(user_id=user.id).first()
Beispiel #8
0
class Game(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128))
    slug = db.Column(db.String(128))
    created = db.Column(db.DateTime)
    description = db.Column(db.Text)
    technology = db.Column(db.Text)
    help = db.Column(db.Text)
    is_deleted = db.Column(db.Boolean, default=False)
    has_cheated = db.Column(db.Boolean, default=False)

    jam_id = db.Column(db.Integer, db.ForeignKey('jam.id'))
    team_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    ratings = db.relationship('Rating', backref='game', lazy="subquery")
    comments = db.relationship('Comment', backref='game', lazy="subquery")
    packages = db.relationship('GamePackage', backref='game', lazy="subquery")
    screenshots = db.relationship('GameScreenshot', backref='game', lazy="subquery")
    votes = db.relationship('Vote', backref='game', lazy="subquery")

    # score_CATEGORY_enabled = db.Column(db.Boolean, default = True)

    def __init__(self, team, title):
        self.team = team
        self.jam = team.jam
        self.title = title
        self.slug = get_slug(title)
        self.created = datetime.utcnow()

    def __repr__(self):
        return '<Game %r>' % self.title

    def destroy(self):
        # destroy all ratings, comments, packages, screenshots
        for rating in self.ratings:
            db.session.delete(rating)
        for comment in self.comments:
            db.session.delete(comment)
        for package in self.packages:
            db.session.delete(package)
        for screenshot in self.screenshots:
            db.session.delete(screenshot)
        for vote in self.votes:
            db.session.delete(vote)
        db.session.delete(self)

    def url(self, **values):
        return url_for("show_game", jam_slug=self.jam.slug, game_id=self.id, **values)

    @property
    def screenshotsOrdered(self):
        return sorted(self.screenshots, lambda s1, s2: int(s1.index - s2.index))

    @property
    def firstScreenshot(self):
        return self.screenshots.first()

    @property
    def score(self):
        if self.has_cheated:
            return -10

        return average([r.score for r in self.ratings if not r.user.is_deleted]) or 0

    def feedbackAverage(self, category):
        if category in (None, "overall"):
            return self.score
        return average_non_zero([r.get(category) for r in self.ratings])

    @property
    def rank(self):
        db.engine.execute("SET @rank=0;")
        rank = db.engine.execute(
            "SELECT rank FROM (SELECT @rank:=@rank+1 AS rank, title, gameId, points FROM (SELECT v.game_id as gameId, g.title as title, count(*) as points FROM vote v LEFT JOIN game g ON g.id = v.game_id where v.jam_id = " + str(
                self.jam_id) + " GROUP BY v.game_id ORDER BY points DESC) t1) t2 WHERE gameId = " + str(self.id)).first()
        return rank.rank

    @property
    def numberRatings(self):
        return len(self.ratings)

    @property
    def numberVotes(self):
        return len(self.votes)

    def getVoteByUser(self, user):
        return Vote.query.filter_by(user_id=user.id).first()

    def getVoteCountByUser(self, user):
        return Vote.query.filter_by(user_id=user.id, jam_id=self.jam_id).count()

    @property
    def ratingCategories(self):
        return [c for c in RATING_CATEGORIES if getattr(self, "score_" + c + "_enabled")]

    def getRatingByUser(self, user):
        return Rating.query.filter_by(user_id=user.id).first()