コード例 #1
0
ファイル: rating.py プロジェクト: imfht/flaskapps
class Rating(db.Model):
    """The rating of a category is set to 0 to disable this category. It is
    then not counted into the average score.
    """

    id = db.Column(db.Integer, primary_key=True)
    score = db.Column(db.SmallInteger)
    text = db.Column(db.Text)
    posted = db.Column(db.DateTime)
    game_id = db.Column(db.Integer, db.ForeignKey('game.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    def __init__(self, game, user, text, score):
        self.game = game
        self.user = user
        self.text = text
        self.posted = datetime.utcnow()
        self.score = score

    def __repr__(self):
        return f"<Rating {self.id}:{self.score}>"

    def set(self, category, value):
        if category in (None, "overall"):
            self.score = value
        else:
            setattr(self, "score_" + category, value)

    def get(self, category):
        return self.score if category in (None, "overall") else getattr(
            self, "score_" + category)
コード例 #2
0
ファイル: models.py プロジェクト: thinker007/flamejam
class RatingSkip(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    reason = db.Column(db.Enum("platform", "uninteresting", "crash"))
    entry_id = db.Column(db.Integer, db.ForeignKey("entry.id"))
    participant_id = db.Column(db.Integer, db.ForeignKey("participant.id"))

    def __init__(self, participant, entry, reason):
        self.participant = participant
        self.entry = entry
        self.reason = reason

    def __repr__(self):
        return "<RatingSkip %r>" % self.id
コード例 #3
0
ファイル: participation.py プロジェクト: dreis2211/gamejam
class Participation(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    team_id = db.Column(db.Integer, db.ForeignKey("team.id"))
    jam_id = db.Column(db.Integer, db.ForeignKey("jam.id"))
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    show_in_finder = db.Column(db.Boolean, default = True)
    registered = db.Column(db.DateTime)

    def __init__(self, user, jam, show_in_finder = True):
        self.user = user
        self.jam = jam
        self.show_in_finder = show_in_finder
        self.registered = datetime.utcnow()
コード例 #4
0
ファイル: models.py プロジェクト: thinker007/flamejam
class Comment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text)
    posted = db.Column(db.DateTime)
    entry_id = db.Column(db.Integer, db.ForeignKey('entry.id'))
    participant_id = db.Column(db.Integer, db.ForeignKey('participant.id'))

    def __init__(self, text, entry, participant):
        self.text = text
        self.entry = entry
        self.participant = participant
        self.posted = datetime.utcnow()

    def __repr__(self):
        return '<Comment %r>' % self.id
コード例 #5
0
class Comment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text)
    posted = db.Column(db.DateTime)
    game_id = db.Column(db.Integer, db.ForeignKey('game.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    def __init__(self, text, game, user):
        self.text = text
        self.game = game
        self.user = user
        self.posted = datetime.utcnow()

    def __repr__(self):
        return f'<Comment {self.id}>'
コード例 #6
0
ファイル: models.py プロジェクト: thinker007/flamejam
class EntryPackage(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(256))
    entry_id = db.Column(db.Integer, db.ForeignKey("entry.id"))
    type = db.Column(
        db.Enum(
            "web",  # Flash, html5, js...
            "linux",  # Linux binaries (e.g. *.tar.gz)
            "linux32",  # Linux32 binaries (e.g. *.tar.gz)
            "linux64",  # Linux64 binaries (e.g. *.tar.gz)
            "windows",  # Windows binaries (e.g. *.zip, *.exe)
            "windows64",  # Windows64 binaries (e.g. *.zip, *.exe)
            "mac",  # MacOS application packages
            "combi",  # Linux + Windows + Source (and more, optional)
            "love",  # Löve packages
            "blender",  # Blender save file (*.blend)
            "source",  # Source package (e.g. *.zip or *.tar.gz)
            "git",  # Version control repository: GIT
            "svn",  # Version control repository: SVN
            "hg",  # Version control repository: HG
            "unknown"))

    def __init__(self, entry, url, type="unknown"):
        self.url = url
        self.type = type
        self.entry = entry

    def __repr__(self):
        return "<EntryPackage %r>" % self.id

    def typeString(self):
        return entry_package_type_string(self.type)
コード例 #7
0
class GameScreenshot(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(255))
    caption = db.Column(db.Text)
    index = db.Column(db.Integer)  # 0..n-1
    game_id = db.Column(db.Integer, db.ForeignKey("game.id"))

    def __init__(self, url, caption, game):
        self.game = game
        self.url = url
        self.caption = caption
        self.index = len(self.game.screenshots) - 1

    def __repr__(self):
        return "<GameScreenshot %r>" % self.id

    def move(self, x):
        all = self.game.screenshotsOrdered

        old = self.index
        new = self.index + x

        if new >= len(all):
            new = len(all) - 1
        if new < 0:
            new = 0

        if new != self.index:
            other = all[new]
            self.index = new
            other.index = old
コード例 #8
0
class Vote(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    game_id = db.Column(db.Integer, db.ForeignKey('game.id'))
    jam_id = db.Column(db.Integer, db.ForeignKey('jam.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    voted_at = db.Column(db.DateTime)

    def __init__(self, game, user):
        self.game = game
        self.jam = game.jam
        self.user = user
        self.voted_at = datetime.utcnow()

        self.game_id = game.id
        self.jam_id = game.jam_id
        self.user_id = user.id
コード例 #9
0
ファイル: jamphoto.py プロジェクト: dreis2211/gamejam
class JamPhoto(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    jam_id = db.Column(db.Integer, db.ForeignKey('jam.id'))
    photo = db.Column(LONGBLOB)

    def __init__(self, jam_id, photo):
        self.jam_id = jam_id
        self.photo = photo
コード例 #10
0
ファイル: models.py プロジェクト: thinker007/flamejam
class EntryScreenshot(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(256))
    caption = db.Column(db.Text)
    entry_id = db.Column(db.Integer, db.ForeignKey("entry.id"))

    def __init__(self, url, caption, entry):
        self.entry = entry
        self.url = url
        self.caption = caption

    def __repr__(self):
        return "<EntryScreenshot %r>" % self.id
コード例 #11
0
ファイル: models.py プロジェクト: thinker007/flamejam
class Rating(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    score_gameplay = db.Column(db.SmallInteger)
    score_graphics = db.Column(db.SmallInteger)
    score_audio = db.Column(db.SmallInteger)
    score_innovation = db.Column(db.SmallInteger)
    score_story = db.Column(db.SmallInteger)
    score_technical = db.Column(db.SmallInteger)
    score_controls = db.Column(db.SmallInteger)
    score_overall = db.Column(db.SmallInteger)
    text = db.Column(db.Text)
    posted = db.Column(db.DateTime)
    entry_id = db.Column(db.Integer, db.ForeignKey('entry.id'))
    participant_id = db.Column(db.Integer, db.ForeignKey('participant.id'))

    def __init__(self, score_gameplay, score_graphics, score_audio,
                 score_innovation, score_story, score_technical,
                 score_controls, score_overall, text, entry, participant):
        self.score_gameplay = score_gameplay
        self.score_graphics = score_graphics
        self.score_audio = score_audio
        self.score_innovation = score_innovation
        self.score_story = score_story
        self.score_technical = score_technical
        self.score_controls = score_controls
        self.score_overall = score_overall
        self.text = text
        self.entry = entry
        self.participant = participant
        self.posted = datetime.utcnow()

    def __repr__(self):
        return '<Rating %r>' % self.id

    def getAverage(self):
        return (self.score_gameplay + self.score_graphics + self.score_audio +
                self.score_innovation + self.score_story + self.score_technical
                + self.score_controls + self.score_overall) * 1.0 / 8.0
コード例 #12
0
ファイル: invitation.py プロジェクト: dreis2211/gamejam
class Invitation(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    team_id = db.Column(db.Integer, db.ForeignKey("team.id"))
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))

    def __init__(self, team, user):
        self.team = team
        self.user = user

    def url(self, **values):
        return url_for("invitation", id=self.id, _external=True, **values)

    def canAccept(self):
        return self.team.jam.getStatus().code <= JamStatusCode.PACKAGING

    def accept(self):
        self.team.userJoin(self.user)
        db.session.delete(self)
        db.session.commit()

    def decline(self):
        db.session.delete(self)
        db.session.commit()
コード例 #13
0
class GamescomApplication(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    year = db.Column(db.Integer)
    title = db.Column(db.String(128))
    city = db.Column(db.String(128))
    country = db.Column(db.String(128))
    zip_code = db.Column(db.String(128))
    street = db.Column(db.String(128))
    job_title = db.Column(db.String(128))
    experience = db.Column(db.String(128))
    reason = db.Column(db.String(255))
    travel_funding_amount = db.Column(db.Integer)
    travel_funding_reason = db.Column(db.String(255))

    def __init__(self, user):
        self.user = user
        self.user_id = user.id
コード例 #14
0
ファイル: game.py プロジェクト: dreis2211/gamejam
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()
コード例 #15
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()
コード例 #16
0
ファイル: team.py プロジェクト: imfht/flaskapps
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
コード例 #17
0
class GamePackage(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(255))
    game_id = db.Column(db.Integer, db.ForeignKey("game.id"))
    type = db.Column(
        db.Enum(
            "web",  # Flash, html5, js...
            "linux",  # Linux binaries (e.g. *.tar.gz)
            "linux32",  # Linux32 binaries (e.g. *.tar.gz)
            "linux64",  # Linux64 binaries (e.g. *.tar.gz)
            "windows",  # Windows binaries (e.g. *.zip, *.exe)
            "windows64",  # Windows64 binaries (e.g. *.zip, *.exe)
            "mac",  # MacOS application packages
            "combi",  # Linux + Windows + Source (and more, optional)
            "love",  # Löve packages
            "blender",  # Blender save file (*.blend)
            "source",  # Source package (e.g. *.zip or *.tar.gz)
            "git",  # Version control repository: GIT
            "svn",  # Version control repository: SVN
            "hg",  # Version control repository: HG
            "unknown"))

    def __init__(self, game, url, type="unknown"):
        self.url = url
        self.type = type
        self.game = game

    def getLink(self):
        return Markup('<a href="%s" target="_blank">%s</a>' %
                      (self.url, GamePackage.typeString(self.type)))

    def getLinkShort(self):
        return Markup('<a href="%s">%s</a>' %
                      (self.url, GamePackage.typeStringShort(self.type)))

    def __repr__(self):
        return "<GamePackage %r>" % self.id

    @staticmethod
    def typeString(type):
        if type in PACKAGE_TYPES:
            return PACKAGE_TYPES[type][0]
        return "Unknown"

    @staticmethod
    def typeStringShort(type):
        if type in PACKAGE_TYPES:
            return PACKAGE_TYPES[type][1]
        return "Unknown"

    @staticmethod
    def packageTypes():
        return PACKAGE_TYPES

    @staticmethod
    def compare(left, right):
        x = right.getTotalScore() - left.getTotalScore()
        if x > 0:
            return 1
        elif x < 0:
            return -1
        else:
            return 0
コード例 #18
0
ファイル: models.py プロジェクト: thinker007/flamejam
from hashlib import sha512, md5
from flamejam import app, db, filters
from flask import url_for, Markup
import re
import random

# rating:
# Participant <one2many> RatingSkip <many2one> Entry
# Participant <one2many> Rating <many2one> Entry

# Teams:
# Participant <many2many> Entry

team_members = db.Table(
    'team_members',
    db.Column('entry_id', db.Integer, db.ForeignKey('entry.id')),
    db.Column('participant_id', db.Integer, db.ForeignKey('participant.id')),
)


def get_slug(s):
    s = s.lower()
    s = re.sub(r"[\s_+]+", "-", s)
    s = re.sub("[^a-z0-9\-]", "", s)
    return s


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))
コード例 #19
0
ファイル: models.py プロジェクト: thinker007/flamejam
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
コード例 #20
0
ファイル: models.py プロジェクト: thinker007/flamejam
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