def percentage(self):
        """
        Calculate what percentage of the badge has been completed
        """

        # load metadata for badge
        toc = loader.toc()
        psets = loader.psets()
        metadata = loader.badges()[self.id]

        # iterate over each chapter required for the badge
        total = 0
        earned = 0
        for chapter in metadata['chapters']:
            # check which sections in the chapter have been read
            for section in toc[chapter]['sections']:
                if chapter in self.reads and section['id'] in self.reads[chapter]:
                    earned += settings.POINTS['section']
                total += settings.POINTS['section']

            # add on points for pset
            earned += self.points[chapter]
            total += psets['points'][chapter]

        return float(earned) / float(total) * 100
    def milestones(self):
        """
        Determine which milestones have been reached
        """

        # load metadata for badge
        toc = loader.toc()
        psets = loader.psets()
        metadata = loader.badges()[self.id]
        milestones = {}

        # iterate over each chapter required for the badge
        for chapter in metadata['chapters']:
            # pset milestone reached if all points have been earned
            milestone = {
                'chapter': True,
                'pset': self.points[chapter] == psets['points'][chapter]
            }

            # chapter milestone not reached if some section has not been read
            for section in toc[chapter]['sections']:
                if not chapter in self.reads or not section['id'] in self.reads[chapter]:
                    milestone['chapter'] = False
                    break

            # save milestone
            milestones[chapter] = milestone

        return milestones
def chapter(chapter, section=None):
    """
    View for reading a single chapter
    """

    # load chapters and table of contents
    chapters = loader.chapters()
    toc = loader.toc()
    info = chapters[chapter]
    title = 'Chapter ' + str(info['sequence'] + 1)
    subtitle = info['title']

    return render_template('chapter.html', chapter_id=chapter, chapter=info, subtitle=subtitle, title=title, toc=toc)
def contents():
    """
    View for the book's table of contents
    """

    # get total points for all problem sets
    psets = loader.psets()
    total_points = psets['points']

    # get all sections the user has read
    reads = g.user.get_reads()

    # get the user's points
    points = g.user.get_points()

    toc = loader.toc()
    return render_template('contents.html', toc=toc, reads=reads, points=points, total_points=total_points)
def pset(chapter, question=0):
    """
    Display the problem set for a chapter
    """

    # make sure chapter is valid
    questions = loader.psets()['questions']
    if not chapter in questions:
        abort(404)

    # temporary metadata
    toc = loader.toc()
    metadata = toc[chapter]
    title = 'Problem Set ' + str(metadata['sequence'] + 1)

    # remove answers from each question
    pset = questions[chapter]
    for i in pset[:]:
        if 'answer' in i:
            del i['answer']

    return render_template('pset.html', pset=pset, chapter=chapter, metadata=metadata, title=title,
        subtitle=metadata['title'])
def progress():
    """
    View for checking progress on site
    """

    # load info for progress
    toc = loader.toc()
    milestones = {}
    percentages = {}
    reads = g.user.get_reads()
    points = g.user.get_points()
    badge_progress = {}

    # determine which badges have been earned
    for k, v in g.all_badges.iteritems():
        if v['type'] == 'chapter':
            badge = badges.ChapterBadge(k, reads, points)
            badge_progress[k] = {
                'milestones': badge.milestones(),
                'percentage': badge.percentage(),
                'earned': badge.earned()
            }

    return render_template('progress.html', badge_progress=badge_progress, toc=toc)