<commit_before>"""
Pull tract information from database,
compute new congressional districts based on criteria in request,
and update the database.
"""

from gerrypy.models.mymodel import Tract, Edge
import networkx as nx
from gerrypy.scripts.assigndistrict import assign_district

def fill_graph(request):
    """Build state graph from tract and edge databases."""
    graph = nx.Graph()
    tracts = request.dbsession.query(Tract).all()
    edges = request.dbsession.query(Edge).all()
    for tract in tracts:
        graph.add_node(tract)
    for edge in edges:
        source = request.dbsession.query(Tract).get(edge.tract_source)
        target = request.dbsession.query(Tract).get(edge.tract_target)
        graph.add_edge(source, target)
    return graph

class OccupiedDist(object):
    """A stucture to contain and separate tracts in a State object.

    add_node(self, node): adds node to nodes and updates district
    properties accordingly

    rem_node(self, node): removes node from nodes and updates district
    properties accordingly
    """

    def __init__(self, districtID, state_graph, tracts=None):
        """."""
        self.nodes = nx.Graph()
        self.perimeter = []
        self.population = 0
        self.area = 0
        self.districtID = districtID
        if tracts:
            try:
                for tract in tracts:
                    self.add_node(tract, state_graph)
            except TypeError:
                raise TypeError('Tracts must be iterable.')

    def add_node(self, node, state_graph):
        """Add node to nodes and updates district properties."""
        node.districtid = self.districtID
        self.nodes.add_node(node)
        for edge in state_graph.neighbors(node):
            if edge in self.nodes.nodes():
                self.nodes.add_edge(edge, node)
        self.population += node.tract_pop
        self.area += node.shape_area
        if node in self.perimeter:
            self.perimeter.remove(node)
        neighbors = state_graph.neighbors(node)
        for neighbor in neighbors:
            if neighbor not in self.nodes.nodes() and neighbor not in self.perimeter:
                self.perimeter.append(neighbor)

    def rem_node(self, node, state_graph):
        """Remove node from nodes and updates district properties."""
        self.population -= node.tract_pop
        self.nodes.remove_node(node)
        self.area -= node.shape_area
        neighbors = state_graph.neighbors(node)
        to_perimeter = False
        for neighbor in neighbors:
            takeout = True
            if neighbor in self.perimeter:
                neighborneighbors = state_graph.neighbors(neighbor)
                for neighborneighbor in neighborneighbors:
                    if neighborneighbor in self.nodes.nodes():
                        takeout = False
                if takeout:
                    self.perimeter.remove(neighbor)
            elif neighbor in self.nodes.nodes():
                to_perimeter = True
        if to_perimeter:
            self.perimeter.append(node)

class UnoccupiedDist(OccupiedDist):
    """A structure to contain tracts that haven't been claimed by a district.

    add_node(self, node): adds node to nodes and updates district
    properties accordingly

    rem_node(self, node): removes node from nodes and updates district
    properties accordingly
    """

    def __init__(self, districtID, state_graph, tracts=None):
        """."""
        self.nodes = nx.Graph()
        self.perimeter = []
        self.population = 0
        self.area = 0
        self.districtID = districtID
        if tracts:
            try:
                for tract in tracts:
                    self.add_node(tract, state_graph)
            except TypeError:
                raise TypeError('Tracts must be iterable.')

    def add_node(self, node, state_graph):
        """Add node to nodes and updates district properties accordingly."""
        node.districtid = None
        self.nodes.add_node(node)
        for neighbor in state_graph.neighbors(node):
            if neighbor in self.nodes:
                self.nodes.add_edge(neighbor, node)
        self.population += node.tract_pop
        self.area += node.shape_area
        neighbors = state_graph.neighbors(node)
        to_add = False
        for neighbor in neighbors:
            takeout = True
            if neighbor in self.perimeter:
                neighborneighbors = state_graph.neighbors(neighbor)
                for neighborneighbor in neighborneighbors:
                    if neighborneighbor not in self.nodes:
                        takeout = False
                if takeout:
                    self.perimeter.remove(neighbor)
            if neighbor not in self.nodes:
                to_add = True
        if to_add:
            self.perimeter.append(node)

    def rem_node(self, node, state_graph):
        """Remove node from nodes and updates district properties accordingly."""
        self.population -= node.tract_pop
        self.area -= node.shape_area
        if node in self.perimeter:
            self.perimeter.remove(node)
        neighbors = self.nodes.neighbors(node) #state_graph.neighbors(node)
        for neighbor in neighbors:
            if neighbor not in self.perimeter:
                self.perimeter.append(neighbor)
        self.nodes.remove_node(node)

class State(object):
    """Manages how tracts are distributed into districts in a particular state.

    build_district(self, start, population):
    creates a new district stemming from the start node with a given population

    fill_state(self, request): continues to build districts until all unoccupied tracts are claimed
    """

    def __init__(self, request, num_dst):
        """Build unoccupied district(s) for entire state."""
        self.unoccupied = []
        self.districts = []
        self.population = 0
        self.area = 0
        self.num_dst = num_dst
        self.request = request
        self.state_graph = fill_graph(self.request)
        landmass = nx.connected_components(self.state_graph)
        for island in landmass:
            unoc = UnoccupiedDist(None, self.state_graph, tracts=island)
            for tract in unoc.nodes.nodes():
                if tract.isborder == 1:
                    unoc.perimeter.append(tract)
            self.population += unoc.population
            self.unoccupied.append(unoc)
            self.area += unoc.area
        self.target_pop = self.population // num_dst

    def fill_state(self, criteria):
        """Build districts until all unoccupied tracts are claimed."""
        for num in range(self.num_dst):
            rem_pop = 0
            for unoc in self.unoccupied:
                rem_pop += unoc.population
            rem_dist = self.num_dst - len(self.districts)
            tgt_population = rem_pop / rem_dist
            self.build_district(tgt_population, num + 1, criteria)
        assign_district(self.request, self.state_graph)
        if self.unoccupied:
            return False
        return True

    def build_district(self, tgt_population, dist_num, criteria):
        """Create a new district stemming from the start node with a given population."""
        dst = OccupiedDist(dist_num, self.state_graph)
        self.districts.append(dst)
        start = self.find_start()
        self.swap(dst, start)  # if state is full, this wont work
        while True:
            new_tract = self.select_next(dst, criteria)
            if new_tract is None:
                for unoc in self.unoccupied:
                    if not len(unoc.nodes.nodes()):
                        self.unoccupied.remove(unoc)
                break
            high_pop = (new_tract.tract_pop + dst.population)
            if abs(high_pop - tgt_population) > abs(dst.population - tgt_population):
                break
            else:
                self.swap(dst, new_tract)
                neighbors = self.state_graph.neighbors(new_tract)
                unassigned_neighbors = [neighbor for neighbor in neighbors if neighbor in self.unoccupied[0].nodes]
                if len(unassigned_neighbors) > 1:
                    for i in range(len(unassigned_neighbors)):
                        if not nx.has_path(
                            self.unoccupied[0].nodes,
                            unassigned_neighbors[i],
                            unassigned_neighbors[i - 1]
                        ):
                            unoc_neighbors = [x for x in nx.connected_components(self.unoccupied[0].nodes)]
                            biggest = max(unoc_neighbors, key=lambda x: len(x))
                            unoc_neighbors.remove(biggest)

                            for neigh in unoc_neighbors:
                                for tract in neigh:
                                    self.swap(dst, tract)
                            break

    def swap(self, dst, new_tract):
        """Exchange tract from unoccupied district to district."""
        self.unoccupied[0].rem_node(new_tract, self.state_graph)
        dst.add_node(new_tract, self.state_graph)

    def select_next(self, dst, criteria):
        """Choose the next best tract to add to growing district."""
        best_rating = 0
        best = None
        for perimeter_tract in dst.perimeter:
            if perimeter_tract.districtid is None:
                count = 0
                for neighbor in self.state_graph.neighbors(perimeter_tract):
                    if neighbor.districtid == dst.districtID:
                        count += 1
                counties = set()
                for node in dst.nodes:
                    counties.add(node.county)
                same_county = 0
                if perimeter_tract.county in counties:
                    same_county = 1
                rating = count * int(criteria['compactness']) + same_county * int(criteria['county'])
                if rating > best_rating:
                    best_rating = rating
                    best = perimeter_tract
        return best

    def find_start(self):
        """
        Choose best starting tract for a new district.
        Based on number of bordering districts.
        """
        best_set = set()
        best = None
        for tract in self.unoccupied[0].perimeter:
            unique_dists = set()
            for neighbor in self.state_graph.neighbors(tract):
                for dst in self.districts:
                    if neighbor in dst.nodes.nodes():
                        unique_dists.add(dst)
            if len(unique_dists) > len(best_set) or len(unique_dists) == 0:
                best_set = unique_dists
                best = tract
        return best
<commit_msg>fishscales comments and small changes<commit_after>"""
Pull tract information from database,
compute new congressional districts based on criteria in request,
and update the database.
"""

from gerrypy.models.mymodel import Tract, Edge
import networkx as nx
from gerrypy.scripts.assigndistrict import assign_district

def fill_graph(request):
    """Build state graph from tract and edge databases."""
    graph = nx.Graph()
    tracts = request.dbsession.query(Tract).all()
    edges = request.dbsession.query(Edge).all()
    for tract in tracts:
        graph.add_node(tract)
    for edge in edges:
        source = request.dbsession.query(Tract).get(edge.tract_source)
        target = request.dbsession.query(Tract).get(edge.tract_target)
        graph.add_edge(source, target)
    return graph

class OccupiedDist(object):
    """A stucture to contain and separate tracts in a State object.

    add_node(self, node): adds node to nodes and updates district
    properties accordingly

    rem_node(self, node): removes node from nodes and updates district
    properties accordingly
    """

    def __init__(self, districtID, state_graph, tracts=None):
        """."""
        self.nodes = nx.Graph()
        self.perimeter = []
        self.population = 0
        self.area = 0
        self.districtID = districtID
        if tracts:
            try:
                for tract in tracts:
                    self.add_node(tract, state_graph)
            except TypeError:
                raise TypeError('Tracts must be iterable.')

    def add_node(self, node, state_graph):
        """Add node to nodes and updates district properties."""
        node.districtid = self.districtID
        self.nodes.add_node(node)
        neighbors = state_graph.neighbors(node)
        if node in self.perimeter:
            self.perimeter.remove(node)
        for neighbor in neighbors:  # After node is added, make the edge connections within the occupied district.
            if neighbor in self.nodes.nodes():
                self.nodes.add_edge(neighbor, node)
            if neighbor not in self.nodes.nodes() and neighbor not in self.perimeter:
                self.perimeter.append(neighbor)
        self.population += node.tract_pop
        self.area += node.shape_area

    def rem_node(self, node, state_graph):
        """Remove node from nodes and updates district properties."""
        self.population -= node.tract_pop
        self.nodes.remove_node(node)
        self.area -= node.shape_area
        neighbors = state_graph.neighbors(node)
        to_perimeter = False
        for neighbor in neighbors:  # Decide whether to remove nodes from the district perimeter.
            takeout = True
            if neighbor in self.perimeter:  # if its a perimeter node,
                neighborneighbors = state_graph.neighbors(neighbor)
                for neighborneighbor in neighborneighbors:  # check its neighbors
                    if neighborneighbor in self.nodes.nodes():  # if it has a neighbor in the district
                        takeout = False  # it should remain in the perimeter list.
                if takeout:  # If it should be removed,
                    self.perimeter.remove(neighbor)  # Remove it!
            elif neighbor in self.nodes.nodes():  # If the removed node neighbors the district (which it should)
                to_perimeter = True  # mark it to be added to the perimeter
        if to_perimeter:  # If its marked,
            self.perimeter.append(node)  # add it to the perimeter

class UnoccupiedDist(OccupiedDist):
    """A structure to contain tracts that haven't been claimed by a district.

    add_node(self, node): adds node to nodes and updates district
    properties accordingly

    rem_node(self, node): removes node from nodes and updates district
    properties accordingly
    """

    def __init__(self, districtID, state_graph, tracts=None):
        """."""
        self.nodes = nx.Graph()
        self.perimeter = []
        self.population = 0
        self.area = 0
        self.districtID = districtID
        if tracts:
            try:
                for tract in tracts:
                    self.add_node(tract, state_graph)
            except TypeError:
                raise TypeError('Tracts must be iterable.')

    def add_node(self, node, state_graph):
        """Add node to nodes and updates district properties accordingly."""
        node.districtid = None
        self.nodes.add_node(node)
        for neighbor in state_graph.neighbors(node):
            if neighbor in self.nodes:
                self.nodes.add_edge(neighbor, node)
        self.population += node.tract_pop
        self.area += node.shape_area
        neighbors = state_graph.neighbors(node)
        to_add = False
        for neighbor in neighbors:  # Handling which nodes to add or remove from the perimeter.
            takeout = True
            if neighbor in self.perimeter:
                neighborneighbors = state_graph.neighbors(neighbor)
                for neighborneighbor in neighborneighbors:
                    if neighborneighbor not in self.nodes:
                        takeout = False
                if takeout:
                    self.perimeter.remove(neighbor)
            if neighbor not in self.nodes:
                to_add = True
        if to_add:
            self.perimeter.append(node)

    def rem_node(self, node, state_graph):
        """Remove node from nodes and updates district properties accordingly."""
        self.population -= node.tract_pop
        self.area -= node.shape_area
        if node in self.perimeter:
            self.perimeter.remove(node)
        neighbors = self.nodes.neighbors(node)
        for neighbor in neighbors:
            if neighbor not in self.perimeter:
                self.perimeter.append(neighbor)
        self.nodes.remove_node(node)

class State(object):
    """Manages how tracts are distributed into districts in a particular state.

    build_district(self, start, population):
    creates a new district stemming from the start node with a given population

    fill_state(self, request): continues to build districts until all unoccupied tracts are claimed
    """

    def __init__(self, request, num_dst):
        """Build unoccupied district(s) for entire state."""
        self.unoccupied = []
        self.districts = []
        self.population = 0
        self.area = 0
        self.num_dst = num_dst # The Number of districts alotted for that state (7 for Colorado)
        self.request = request
        self.state_graph = fill_graph(self.request)
        landmass = nx.connected_components(self.state_graph)  # Returns all of the connected/contiguous areas of land for a state.
        for island in landmass:
            unoc = UnoccupiedDist(None, self.state_graph, tracts=island)  # needs the state graph for its edges
            for tract in unoc.nodes.nodes():
                if tract.isborder == 1:  # This is a hardcoded field for Colorado.  A challenge of adding more states is finding these automatically.
                    unoc.perimeter.append(tract)  # begin with all border tracts in the perimeter.
            self.population += unoc.population
            self.unoccupied.append(unoc)
            self.area += unoc.area

    def fill_state(self, criteria):
        """Build districts until all unoccupied tracts are claimed."""
        for num in range(self.num_dst):
            rem_pop = 0
            for unoc in self.unoccupied:
                rem_pop += unoc.population
            rem_dist = self.num_dst - len(self.districts)
            tgt_population = rem_pop / rem_dist  # Average available population is the target population.  It helps ensure the State gets totally filled.
            self.build_district(tgt_population, num + 1, criteria)
        assign_district(self.request, self.state_graph)

    def build_district(self, tgt_population, dist_num, criteria):
        """Create a new district stemming from the start node with a given population."""
        dst = OccupiedDist(dist_num, self.state_graph)
        self.districts.append(dst)
        start = self.find_start()
        self.swap(dst, start)  # if state is full, this wont work
        while True:
            new_tract = self.select_next(dst, criteria)
            if new_tract is None:  # If there are no more nodes in unoccupied, this will be None
                for unoc in self.unoccupied:  # This ends the building process
                    if not len(unoc.nodes.nodes()):
                        self.unoccupied.remove(unoc)
                break
            high_pop = (new_tract.tract_pop + dst.population)  # Population including the next tract.
            if abs(high_pop - tgt_population) > abs(dst.population - tgt_population):    # If the population including the next district is further from the goal,
                break  # We stop building that district
            else:
                self.swap(dst, new_tract)  # Swap removes the tract from its unoccupied district and adds it to the occupied district.
                neighbors = self.state_graph.neighbors(new_tract)
                unassigned_neighbors = [neighbor for neighbor in neighbors if neighbor in self.unoccupied[0].nodes]  # Grab the new nodes unassigned neighbors
                if len(unassigned_neighbors) > 1:  # If there is more than one, than a split is possible.
                    for i in range(len(unassigned_neighbors)):
                        if not nx.has_path(    # We check each node and its previous neighbor to ensure they're connected. (thanks, nx)
                            self.unoccupied[0].nodes,
                            unassigned_neighbors[i],
                            unassigned_neighbors[i - 1]
                        ):  # If there is a split in the unoccupied district...
                            unoc_neighbors = [x for x in nx.connected_components(self.unoccupied[0].nodes)]  # Identify each of the distinct unoccupied districts.
                            biggest = max(unoc_neighbors, key=lambda x: len(x))
                            unoc_neighbors.remove(biggest)    # Ignore the largest (This should be highest pop, fixed in different version)
                            # All unoccupied districts will be bordering, because as soon as there is a split, we do this.
                            for neigh in unoc_neighbors:  # Consume all of the rest (usually one small one)
                                for tract in neigh:  # This sometimes gives us a district that is too large, and is the major focus of improving the algorithm.
                                    self.swap(dst, tract)
                            break

    def swap(self, dst, new_tract):
        """Exchange tract from unoccupied district to district."""
        self.unoccupied[0].rem_node(new_tract, self.state_graph)
        dst.add_node(new_tract, self.state_graph)

    def select_next(self, dst, criteria):
        """Choose the next best tract to add to growing district."""
        best_rating = 0
        best = None  # We're building a score for each node based on our criteria, and saving the best.
        for perimeter_tract in dst.perimeter:  # dst.perimeter is every node bordering that district.
            if perimeter_tract.districtid is None:  # Grab those without a district assigned
                count = 0    # Check how many tracts that tract borders that are ALREADY in the district.  More borders gets more points
                for neighbor in self.state_graph.neighbors(perimeter_tract):
                    if neighbor.districtid == dst.districtID:
                        count += 1
                counties = set()    # If the tracts county is in the district already, it gets a point.
                for node in dst.nodes:
                    counties.add(node.county)
                same_county = 0
                if perimeter_tract.county in counties:
                    same_county = 1
                rating = count * int(criteria['compactness']) + same_county * int(criteria['county'])  # Calculate score based on criteria.
                if rating > best_rating:
                    best_rating = rating
                    best = perimeter_tract
        return best

    def find_start(self):
        """
        Choose best starting tract for a new district.
        Based on number of bordering districts.
        """
        best_set = set()
        best = None
        for tract in self.unoccupied[0].perimeter:
            unique_dists = set()
            for neighbor in self.state_graph.neighbors(tract):
                for dst in self.districts:
                    if neighbor in dst.nodes.nodes():
                        unique_dists.add(dst)
            if len(unique_dists) > len(best_set) or len(unique_dists) == 0:
                best_set = unique_dists
                best = tract
        return best
<|endoftext|>


<commit_before>''' Convert text into tf-idf.
usage: python data_loader.py TEXT_FILE

File should have one document per row. E.g. this file:

apple banana
banana cherry

results in

1:0.579739 0:0.814802
2:0.814802 1:0.579739

with a vocabulary of

[(u'apple', 0), (u'banana', 1), (u'cherry', 2)]

'''

import io
import operator
import sys

from sklearn.cluster import MiniBatchKMeans
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline

def text2tfidf(data_generator):
    '''Transform text data into tf-idf vectors. This can be used in a
    streaming fashion, so that each line is represented sparsely as its read.

    data_generator .... generator of strings. This can simply be a list of
    strings, or a file object.

    >>> vocab, data = text2tfidf(['apple banana', 'banana cherry'])
    >>> data = data.toarray()
    >>> print data[0]
    [ 0.81480247  0.57973867  0.        ]
    >>> print data[1]
    [ 0.          0.57973867  0.81480247]
    >>> print sorted(vocab.iteritems(), key=operator.itemgetter(1))
    [(u'apple', 0), (u'banana', 1), (u'cherry', 2)]
    '''
    counter = CountVectorizer(min_df=0.)
    data = counter.fit_transform(data_generator)
    tfidf = TfidfTransformer()
    data = tfidf.fit_transform(data)
    return counter.vocabulary_, data

def print_sparse_matrix(data):
    'Print a sparse matrix in format <index>:<value>'
    for ri in range(data.get_shape()[0]):
        row = data.getrow(ri)
        print ' '.join(['%d:%g' % (i, d)
                        for (i, d) in zip(row.indices, row.data)])

if (__name__ == '__main__'):
    if len(sys.argv) == 1:
        print 'python data_loader.py TEXT_FILE'
    vocab, data = text2tfidf(io.open(sys.argv[1], mode='rt', encoding='utf8'))
    print_sparse_matrix(data)
<commit_msg>remove unused imports<commit_after>''' Convert text into tf-idf.
usage: python data_loader.py TEXT_FILE

File should have one document per row. E.g. this file:

apple banana
banana cherry

results in

1:0.579739 0:0.814802
2:0.814802 1:0.579739

with a vocabulary of

[(u'apple', 0), (u'banana', 1), (u'cherry', 2)]

'''

import io
import operator
import sys

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer

def text2tfidf(data_generator):
    '''Transform text data into tf-idf vectors. This can be used in a
    streaming fashion, so that each line is represented sparsely as its read.

    data_generator .... generator of strings. This can simply be a list of
    strings, or a file object.

    >>> vocab, data = text2tfidf(['apple banana', 'banana cherry'])
    >>> data = data.toarray()
    >>> print data[0]
    [ 0.81480247  0.57973867  0.        ]
    >>> print data[1]
    [ 0.          0.57973867  0.81480247]
    >>> print sorted(vocab.iteritems(), key=operator.itemgetter(1))
    [(u'apple', 0), (u'banana', 1), (u'cherry', 2)]
    '''
    counter = CountVectorizer(min_df=0.)
    data = counter.fit_transform(data_generator)
    tfidf = TfidfTransformer()
    data = tfidf.fit_transform(data)
    return counter.vocabulary_, data

def print_sparse_matrix(data):
    'Print a sparse matrix in format <index>:<value>'
    for ri in range(data.get_shape()[0]):
        row = data.getrow(ri)
        print ' '.join(['%d:%g' % (i, d)
                        for (i, d) in zip(row.indices, row.data)])

if (__name__ == '__main__'):
    if len(sys.argv) == 1:
        print 'python data_loader.py TEXT_FILE'
    vocab, data = text2tfidf(io.open(sys.argv[1], mode='rt', encoding='utf8'))
    print_sparse_matrix(data)
<|endoftext|>


<commit_before>from datetime import datetime

from django.conf import settings
from django.shortcuts import render, redirect
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from vumi.persist.redis_manager import RedisManager

from go.base.utils import make_read_only_form, conversation_or_404
from go.vumitools.exceptions import ConversationSendError
from go.conversation.forms import ConversationForm, ConversationGroupForm

from vxpolls.content import forms
from vxpolls.manager import PollManager

redis = RedisManager.from_config(settings.VXPOLLS_REDIS_CONFIG)

def link_poll_to_conversation(poll_name, poll_id, conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    polls = vxpolls_metadata.setdefault('polls', {})
    polls.update({
        poll_name: poll_id,
    })
    conversation.set_metadata(metadata)
    conversation.save()

def unlink_poll_from_conversation(poll_name, conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    polls = vxpolls_metadata.setdefault('polls', {})
    del polls[poll_name]
    conversation.set_metadata(metadata)
    conversation.save()

def get_polls_for_conversation(conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    return vxpolls_metadata.get('polls', {})

def generate_poll_id(conversation, suffix):
    return 'poll-%s_%s' % (conversation.key, suffix)

def get_poll_config(poll_id):
    pm = PollManager(redis, settings.VXPOLLS_PREFIX)
    config = pm.get_config(poll_id)
    config.update({
        'poll_id': poll_id,
    })
    return pm, config

@login_required
def new(request):
    if request.POST:
        form = ConversationForm(request.user_api, request.POST)
        if form.is_valid():
            conversation_data = {}
            copy_keys = [
                'subject',
                'message',
                'delivery_class',
            ]

            for key in copy_keys:
                conversation_data[key] = form.cleaned_data[key]

            tag_info = form.cleaned_data['delivery_tag_pool'].partition(':')
            conversation_data['delivery_tag_pool'] = tag_info[0]
            if tag_info[2]:
                conversation_data['delivery_tag'] = tag_info[2]

            start_date = form.cleaned_data['start_date'] or datetime.utcnow()
            start_time = (form.cleaned_data['start_time'] or
                            datetime.utcnow().time())
            conversation_data['start_timestamp'] = datetime(
                start_date.year, start_date.month, start_date.day,
                start_time.hour, start_time.minute, start_time.second,
                start_time.microsecond)

            conversation = request.user_api.new_conversation(
                u'multi_survey', **conversation_data)
            messages.add_message(request, messages.INFO,
                'Survey Created')
            return redirect(reverse('multi_survey:surveys',
                kwargs={'conversation_key': conversation.key}))

    else:
        form = ConversationForm(request.user_api, initial={
            'start_date': datetime.utcnow().date(),
            'start_time': datetime.utcnow().time().replace(second=0,
                                                            microsecond=0),
        })
    return render(request, 'multi_surveys/new.html', {
        'form': form,
    })

@login_required
def surveys(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    polls = get_polls_for_conversation(conversation)

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))

    return render(request, 'multi_surveys/surveys.html', {
        'survey_form': survey_form,
        'conversation': conversation,
        'polls': polls,
    })

@login_required
def new_survey(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    initial_config = {
        'poll_name': '',
    }
    if request.method == 'POST':
        pm = PollManager(redis, settings.VXPOLLS_PREFIX)
        post_data = request.POST.copy()
        form = forms.make_form(data=post_data, initial=initial_config)
        form.fields['poll_name'].required = True
        if form.is_valid():
            poll_name = form.cleaned_data['poll_name']
            poll_id = generate_poll_id(conversation, poll_name)
            link_poll_to_conversation(poll_name, poll_id, conversation)
            pm.set(poll_id, form.export())
            if request.POST.get('_save_contents'):
                return redirect(reverse('multi_survey:survey', kwargs={
                    'conversation_key': conversation.key,
                    'poll_name': poll_name,
                }))
            else:
                return redirect(reverse('multi_survey:surveys', kwargs={
                    'conversation_key': conversation.key,
                }))
    else:
        form = forms.make_form(data=initial_config, initial=initial_config)
        form.fields['poll_name'].required = True

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    return render(request, 'multi_surveys/contents.html', {
        'form': form,
        'survey_form': survey_form,
    })

@login_required
def survey(request, conversation_key, poll_name):
    conversation = conversation_or_404(request.user_api, conversation_key)
    poll_id = generate_poll_id(conversation, poll_name)
    pm, config = get_poll_config(poll_id)
    if request.method == 'POST':

        if request.POST.get('_delete_survey'):
            unlink_poll_from_conversation(poll_name, conversation)
            return redirect(reverse('multi_survey:surveys', kwargs={
                'conversation_key': conversation.key,
            }))

        post_data = request.POST.copy()
        post_data.update({
            'poll_id': poll_id,
        })
        form = forms.make_form(data=post_data, initial=config)
        if form.is_valid():
            pm.set(poll_id, form.export())
            link_poll_to_conversation(poll_name, poll_id, conversation)
            if request.POST.get('_save_contents'):
                return redirect(reverse('multi_survey:survey', kwargs={
                    'conversation_key': conversation.key,
                    'poll_name': poll_name,
                }))
            else:
                return redirect(reverse('multi_survey:surveys', kwargs={
                    'conversation_key': conversation.key,
                }))
    else:
        form = forms.make_form(data=config, initial=config)

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    return render(request, 'multi_surveys/contents.html', {
        'form': form,
        'survey_form': survey_form,
    })

@login_required
def people(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    groups = request.user_api.list_groups()

    poll_id = "poll-%s" % (conversation.key,)
    pm, config = get_poll_config(poll_id)

    if request.method == 'POST':
        if conversation.is_client_initiated():
            try:
                conversation.start()
            except ConversationSendError as error:
                if str(error) == 'No spare messaging tags.':
                    error = 'You have maxed out your available ' \
                            '%(delivery_class)s addresses. ' \
                            'End one or more running %(delivery_class)s ' \
                            'conversations to free one up.' % {
                                'delivery_class': conversation.delivery_class,
                            }
                messages.add_message(request, messages.ERROR, str(error))
                return redirect(reverse('multi_survey:people', kwargs={
                    'conversation_key': conversation.key}))

            addresses = [tag[1] for tag in conversation.get_tags()]
            messages.add_message(request, messages.INFO,
                'Survey started on %s' % (', '.join(addresses),))
            return redirect(reverse('multi_survey:show', kwargs={
                'conversation_key': conversation.key}))
        else:
            group_form = ConversationGroupForm(
                request.POST, groups=request.user_api.list_groups())

            if group_form.is_valid():
                for group in group_form.cleaned_data['groups']:
                    conversation.groups.add_key(group)
                conversation.save()
                messages.add_message(request, messages.INFO,
                    'The selected groups have been added to the survey')
                return redirect(reverse('multi_survey:start', kwargs={
                                    'conversation_key': conversation.key}))

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    content_form = forms.make_form(data=config, initial=config, extra=0)
    read_only_content_form = make_read_only_form(content_form)
    return render(request, 'multi_surveys/people.html', {
        'conversation': conversation,
        'survey_form': survey_form,
        'content_form': read_only_content_form,
        'groups': groups,
        'polls': get_polls_for_conversation(conversation),
    })

@login_required
def start(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    if request.method == 'POST':
        try:
            conversation.start()
        except ConversationSendError as error:
            messages.add_message(request, messages.ERROR, str(error))
            return redirect(reverse('multi_survey:start', kwargs={
                'conversation_key': conversation.key}))
        messages.add_message(request, messages.INFO, 'Survey started')
        return redirect(reverse('multi_survey:show', kwargs={
            'conversation_key': conversation.key}))
    return render(request, 'multi_surveys/start.html', {
        'conversation': conversation,
    })

@login_required
def end(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    if request.method == 'POST':
        conversation.end_conversation()
        messages.add_message(request, messages.INFO, 'Survey ended')
    return redirect(reverse('multi_survey:show', kwargs={
        'conversation_key': conversation.key}))

@login_required
def show(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    return render(request, 'multi_surveys/show.html', {
        'conversation': conversation,
    })
<commit_msg>some progress<commit_after>from datetime import datetime

from django.conf import settings
from django.shortcuts import render, redirect
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from vumi.persist.redis_manager import RedisManager

from go.base.utils import make_read_only_form, conversation_or_404
from go.vumitools.exceptions import ConversationSendError
from go.conversation.forms import ConversationForm, ConversationGroupForm
from go.apps.surveys import forms as sforms

from vxpolls.content import forms
from vxpolls.manager import PollManager

redis = RedisManager.from_config(settings.VXPOLLS_REDIS_CONFIG)

def link_poll_to_conversation(poll_name, poll_id, conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    polls = vxpolls_metadata.setdefault('polls', {})
    polls.update({
        poll_name: poll_id,
    })
    conversation.set_metadata(metadata)
    conversation.save()

def unlink_poll_from_conversation(poll_name, conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    polls = vxpolls_metadata.setdefault('polls', {})
    del polls[poll_name]
    conversation.set_metadata(metadata)
    conversation.save()

def get_polls_for_conversation(conversation):
    metadata = conversation.get_metadata(default={})
    vxpolls_metadata = metadata.setdefault('vxpolls', {})
    return vxpolls_metadata.get('polls', {})

def generate_poll_id(conversation, suffix):
    return 'poll-%s_%s' % (conversation.key, suffix)

def get_poll_config(poll_id):
    pm = PollManager(redis, settings.VXPOLLS_PREFIX)
    config = pm.get_config(poll_id)
    config.update({
        'poll_id': poll_id,
    })
    return pm, config

@login_required
def new(request):
    if request.POST:
        form = ConversationForm(request.user_api, request.POST)
        if form.is_valid():
            conversation_data = {}
            copy_keys = [
                'subject',
                'message',
                'delivery_class',
            ]

            for key in copy_keys:
                conversation_data[key] = form.cleaned_data[key]

            tag_info = form.cleaned_data['delivery_tag_pool'].partition(':')
            conversation_data['delivery_tag_pool'] = tag_info[0]
            if tag_info[2]:
                conversation_data['delivery_tag'] = tag_info[2]

            start_date = form.cleaned_data['start_date'] or datetime.utcnow()
            start_time = (form.cleaned_data['start_time'] or
                            datetime.utcnow().time())
            conversation_data['start_timestamp'] = datetime(
                start_date.year, start_date.month, start_date.day,
                start_time.hour, start_time.minute, start_time.second,
                start_time.microsecond)

            conversation = request.user_api.new_conversation(
                u'multi_survey', **conversation_data)
            messages.add_message(request, messages.INFO,
                'Survey Created')
            return redirect(reverse('multi_survey:surveys',
                kwargs={'conversation_key': conversation.key}))

    else:
        form = ConversationForm(request.user_api, initial={
            'start_date': datetime.utcnow().date(),
            'start_time': datetime.utcnow().time().replace(second=0,
                                                            microsecond=0),
        })
    return render(request, 'multi_surveys/new.html', {
        'form': form,
    })

@login_required
def surveys(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    polls = get_polls_for_conversation(conversation)

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))

    return render(request, 'multi_surveys/surveys.html', {
        'survey_form': survey_form,
        'conversation': conversation,
        'polls': polls,
    })

@login_required
def new_survey(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    initial_config = {
        'poll_name': '',
    }
    if request.method == 'POST':
        pm = PollManager(redis, settings.VXPOLLS_PREFIX)
        post_data = request.POST.copy()
        form = forms.make_form(data=post_data, initial=initial_config)
        form.fields['poll_name'].required = True
        if form.is_valid():
            poll_name = form.cleaned_data['poll_name']
            poll_id = generate_poll_id(conversation, poll_name)
            link_poll_to_conversation(poll_name, poll_id, conversation)
            pm.set(poll_id, form.export())
            if request.POST.get('_save_contents'):
                return redirect(reverse('multi_survey:survey', kwargs={
                    'conversation_key': conversation.key,
                    'poll_name': poll_name,
                }))
            else:
                return redirect(reverse('multi_survey:surveys', kwargs={
                    'conversation_key': conversation.key,
                }))
    else:
        form = forms.make_form(data=initial_config, initial=initial_config)
        form.fields['poll_name'].required = True

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    return render(request, 'multi_surveys/contents.html', {
        'form': form,
        'survey_form': survey_form,
    })

@login_required
def survey(request, conversation_key, poll_name):
    conversation = conversation_or_404(request.user_api, conversation_key)
    poll_id = generate_poll_id(conversation, poll_name)
    pm, config = get_poll_config(poll_id)
    questions_data = config.get('questions', [])
    completed_response_data = config.get('survey_completed_responses', [])

    if request.method == 'POST':
        if request.POST.get('_delete_survey'):
            unlink_poll_from_conversation(poll_name, conversation)
            return redirect(reverse('multi_survey:surveys', kwargs={
                'conversation_key': conversation.key,
            }))

        post_data = request.POST.copy()
        post_data.update({
            'poll_id': poll_id,
        })
        form = forms.make_form(data=post_data, initial=config)

        questions_formset = forms.make_form_set(data=post_data)
        completed_response_formset = forms.make_completed_response_form_set(
            data=post_data)
        #poll_form = forms.SurveyPollForm(data=post_data)
        if form.is_valid():
            pm.set(poll_id, form.export())
            link_poll_to_conversation(poll_name, poll_id, conversation)
            if request.POST.get('_save_contents'):
                for k, v in post_data.items():
                    print k, v
                return redirect(reverse('multi_survey:survey', kwargs={
                    'conversation_key': conversation.key,
                    'poll_name': poll_name,
                }))
            else:
                return redirect(reverse('multi_survey:surveys', kwargs={
                    'conversation_key': conversation.key,
                }))
    else:
        form = forms.make_form(data=config, initial=config)
        questions_formset = forms.make_form_set(initial=questions_data)
        completed_response_formset = forms.make_completed_response_form_set(
            initial=completed_response_data)

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    return render(request, 'multi_surveys/contents.html', {
        'form': form,
        'questions_formset': questions_formset,
        'completed_response_formset': completed_response_formset,
        'survey_form': survey_form,
    })

@login_required
def people(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    groups = request.user_api.list_groups()

    poll_id = "poll-%s" % (conversation.key,)
    pm, config = get_poll_config(poll_id)

    if request.method == 'POST':
        if conversation.is_client_initiated():
            try:
                conversation.start()
            except ConversationSendError as error:
                if str(error) == 'No spare messaging tags.':
                    error = 'You have maxed out your available ' \
                            '%(delivery_class)s addresses. ' \
                            'End one or more running %(delivery_class)s ' \
                            'conversations to free one up.' % {
                                'delivery_class': conversation.delivery_class,
                            }
                messages.add_message(request, messages.ERROR, str(error))
                return redirect(reverse('multi_survey:people', kwargs={
                    'conversation_key': conversation.key}))

            addresses = [tag[1] for tag in conversation.get_tags()]
            messages.add_message(request, messages.INFO,
                'Survey started on %s' % (', '.join(addresses),))
            return redirect(reverse('multi_survey:show', kwargs={
                'conversation_key': conversation.key}))
        else:
            group_form = ConversationGroupForm(
                request.POST, groups=request.user_api.list_groups())

            if group_form.is_valid():
                for group in group_form.cleaned_data['groups']:
                    conversation.groups.add_key(group)
                conversation.save()
                messages.add_message(request, messages.INFO,
                    'The selected groups have been added to the survey')
                return redirect(reverse('multi_survey:start', kwargs={
                                    'conversation_key': conversation.key}))

    survey_form = make_read_only_form(ConversationForm(request.user_api,
        instance=conversation, initial={
            'start_date': conversation.start_timestamp.date(),
            'start_time': conversation.start_timestamp.time(),
        }))
    content_form = forms.make_form(data=config, initial=config, extra=0)
    read_only_content_form = make_read_only_form(content_form)
    return render(request, 'multi_surveys/people.html', {
        'conversation': conversation,
        'survey_form': survey_form,
        'content_form': read_only_content_form,
        'groups': groups,
        'polls': get_polls_for_conversation(conversation),
    })

@login_required
def start(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    if request.method == 'POST':
        try:
            conversation.start()
        except ConversationSendError as error:
            messages.add_message(request, messages.ERROR, str(error))
            return redirect(reverse('multi_survey:start', kwargs={
                'conversation_key': conversation.key}))
        messages.add_message(request, messages.INFO, 'Survey started')
        return redirect(reverse('multi_survey:show', kwargs={
            'conversation_key': conversation.key}))
    return render(request, 'multi_surveys/start.html', {
        'conversation': conversation,
    })

@login_required
def end(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    if request.method == 'POST':
        conversation.end_conversation()
        messages.add_message(request, messages.INFO, 'Survey ended')
    return redirect(reverse('multi_survey:show', kwargs={
        'conversation_key': conversation.key}))

@login_required
def show(request, conversation_key):
    conversation = conversation_or_404(request.user_api, conversation_key)
    return render(request, 'multi_surveys/show.html', {
        'conversation': conversation,
    })
<|endoftext|>


<commit_before># Copyright (c) 2013 Rackspace Hosting, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""flavors: JSON schema for zaqar-queues flavors resources."""

# NOTE(flaper87): capabilities can be anything. These will be unique to
# each storage driver, so we don't perform any further validation at
# the transport layer.
patch_capabilities = {
    'type': 'object',
    'properties': {
        'capabilities': {
            'type': 'object'
        }
    }
}

# NOTE(gengchc): Add pool_list in flavor creation for removing pool_group
patch_pool_list = {
    'type': 'object',
    'properties': {
        'pool_list': {
            'type': 'array'
        },
        'additionalProperties': False
    }
}

create = {
    'type': 'object',
    'properties': {
        'capabilities': patch_capabilities['properties']['capabilities']
    },
    # NOTE(flaper87): capabilities need not be present. Storage drivers
    # must provide reasonable defaults.
    # NOTE(wanghao): remove the whole folder when we remove the 1.1 API
    # totally.
    'additionalProperties': False
}
<commit_msg>Quick fix for v1.1 api schema<commit_after># Copyright (c) 2013 Rackspace Hosting, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""flavors: JSON schema for zaqar-queues flavors resources."""

# NOTE(flaper87): capabilities can be anything. These will be unique to
# each storage driver, so we don't perform any further validation at
# the transport layer.
patch_capabilities = {
    'type': 'object',
    'properties': {
        'capabilities': {
            'type': 'object'
        }
    }
}

create = {
    'type': 'object',
    'properties': {
        'capabilities': patch_capabilities['properties']['capabilities']
    },
    # NOTE(flaper87): capabilities need not be present. Storage drivers
    # must provide reasonable defaults.
    # NOTE(wanghao): remove the whole folder when we remove the 1.1 API
    # totally.
    'additionalProperties': True
}
<|endoftext|>


<commit_before>
from argparse import ArgumentParser
from typing import Any

from django.conf import settings
from django.contrib.auth import get_backends
from django.core.management.base import BaseCommand
from django_auth_ldap.backend import LDAPBackend, _LDAPUser

# Quick tool to test whether you're correctly authenticating to LDAP
def query_ldap(**options: str) -> None:
    email = options['email']
    for backend in get_backends():
        if isinstance(backend, LDAPBackend):
            ldap_attrs = _LDAPUser(backend, backend.django_to_ldap_username(email)).attrs
            if ldap_attrs is None:
                print("No such user found")
            else:
                for django_field, ldap_field in settings.AUTH_LDAP_USER_ATTR_MAP.items():
                    print("%s: %s" % (django_field, ldap_attrs[ldap_field]))

class Command(BaseCommand):
    def add_arguments(self, parser: ArgumentParser) -> None:
        parser.add_argument('email', metavar='<email>', type=str,
                            help="email of user to query")

    def handle(self, *args: Any, **options: str) -> None:
        query_ldap(**options)
<commit_msg>query_ldap: Print the email address for configuration (C).<commit_after>
from argparse import ArgumentParser
from typing import Any

from django.conf import settings
from django.contrib.auth import get_backends
from django.core.management.base import BaseCommand
from django_auth_ldap.backend import LDAPBackend, _LDAPUser

# Quick tool to test whether you're correctly authenticating to LDAP
def query_ldap(**options: str) -> None:
    email = options['email']
    for backend in get_backends():
        if isinstance(backend, LDAPBackend):
            ldap_attrs = _LDAPUser(backend, backend.django_to_ldap_username(email)).attrs
            if ldap_attrs is None:
                print("No such user found")
            else:
                for django_field, ldap_field in settings.AUTH_LDAP_USER_ATTR_MAP.items():
                    print("%s: %s" % (django_field, ldap_attrs[ldap_field]))
                if settings.LDAP_EMAIL_ATTR is not None:
                    print("%s: %s" % ('email', ldap_attrs[settings.LDAP_EMAIL_ATTR]))

class Command(BaseCommand):
    def add_arguments(self, parser: ArgumentParser) -> None:
        parser.add_argument('email', metavar='<email>', type=str,
                            help="email of user to query")

    def handle(self, *args: Any, **options: str) -> None:
        query_ldap(**options)
<|endoftext|>


<commit_before>import setup
from selenium.webdriver.common.by import By

try:

  # Sign in as an admin
  driver = setup.MakeDriver(user="zella")

  ######################  Testing Admin Guns Page  ######################

  # Admin adds gun
  driver.Click([[By.NAME, 'drawerAdmin Guns']])
  driver.Click([[By.ID, 'add']])
  driver.SendKeys(
        [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
        '3.14')

  driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])

  # View added gun
  driver.ExpectContains([[By.NAME, 'gun-row-3.14']], "3.14")

  # Assign player a gun
  driver.Click([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'pencil']])
  driver.SendKeys(
        [[By.NAME, 'gun-row-3.14'], [By.TAG_NAME, 'input']],
        'Jack Slayer the Bean Slasher')
  driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'setButton']])

  # Show that player shows up as having the gun
  driver.ExpectContains([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'player-label']], "Jack Slayer the Bean Slasher")

  #Add another gun, assign to another player
  driver.Click([[By.ID, 'add']])
  driver.SendKeys(
        [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
        'pancake')
  driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.CLASS_NAME, 'pencil']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.TAG_NAME, 'input']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.NAME, '2: Moldavi the Moldavish']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.ID, 'setButton']])

  # Search by label
  driver.Click([[By.NAME, 'header-Label'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Label'], [By.TAG_NAME, 'input']],
        'pan')
  driver.ExpectContains([[By.ID, 'table']], "Moldavi")
  driver.ExpectContains([[By.ID, 'table']], "Jack", False)
  driver.Backspace([[By.NAME, 'header-Label'], [By.TAG_NAME, 'input']], 3)

  # Search by player
  driver.Click([[By.NAME, 'header-Player'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Player'], [By.TAG_NAME, 'input']],
        'Jack')
  driver.ExpectContains([[By.ID, 'table']], "Jack")
  driver.ExpectContains([[By.ID, 'table']], "Moldavi", False)
  driver.Backspace([[By.NAME, 'header-Player'], [By.TAG_NAME, 'input']], 4)

  # THEORETICALLY WORKS, BUT NO PROMISES SINCE ITS CURRENTLY BROKEN SO I CAN'T TEST
  # Uncomment this block later
  # Change the weapon ID, and show that it shows up
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'menu']])
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.NAME, 'menu-item-Edit']])
  # driver.SendKeys(
  #       [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
  #       '42')
  # driver.Click([[By.ID, 'gunForm'], [By.ID, 'done']])
  # ## driver.ExpectContains([[By.NAME, 'gun-row-42']], "42")

  # TODO - when implemented, have a player see that they've been assigned a gun

  #####################  Testing Admin Players Page  ######################

  # Admin - set got equipment for Jack
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Got Equipment']]) # Doesn't update like it's supposed to - remote server
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "Yes") #Crashes here remote server

  # Check Jack's profile, make sure the change showed up
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'name']])
  driver.ExpectContains([[By.NAME, 'got-equipment']], "Yes")

  # If you set the equipment of someone who already has it, nothing should happen
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Got Equipment']])
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "Yes")

  # Unset Jack's equipment
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Unset Got Equipment']])
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "No")

  # Check Jack's profile, make sure the change showed up
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'name']])
  driver.ExpectContains([[By.NAME, 'got-equipment']], "No")

  # Go back to the Admin Guns page
  driver.Click([[By.NAME, 'drawerAdmin Players']])

  # Search by number
  driver.Click([[By.NAME, 'header-#'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-#'], [By.TAG_NAME, 'input']],
        '3')
  driver.ExpectContains([[By.NAME, 'player-table']], "Jack") # Jack should show up
  driver.ExpectContains([[By.NAME, 'player-table']], "Deckerd", False) # Deckerd shouldn't show up
  driver.Backspace([[By.NAME, 'header-#'], [By.TAG_NAME, 'input']])

  # # Search by name
  driver.Click([[By.NAME, 'header-Name'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Name'], [By.TAG_NAME, 'input']],
        'Deckerd')
  driver.ExpectContains([[By.NAME, 'player-table']], "Deckerd") # Deckerd should show up
  driver.ExpectContains([[By.NAME, 'player-table']], "Jack", False) # Jack shouldn't show up
  driver.Backspace([[By.NAME, 'header-Name'], [By.TAG_NAME, 'input']], 7)

  # TODO - search by equipment once this works

  # TODO - add a note
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Notes']])

  # TODO - once we can add notes, search by notes
  # driver.Quit()

  driver = WholeDriver(
    user="zella")

  # Admin adds gun
  # driver.Click([[By.NAME, 'drawerAdmin Guns']])
  # driver.Click([[By.ID, 'add']])
  # driver.SendKeys(
  #       [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
  #       '3.14')
  # # TODO - Add cancel in here
  # driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])

  # # View added gun
  # driver.ExpectContains([[By.NAME, 'gun-row-3.14']], "3.14")

  # # Assign player a gun
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'pencil']])
  # # TODO - check that the dropdowns show up
  # driver.SendKeys(
  #       [[By.NAME, 'gun-row-3.14'], [By.TAG_NAME, 'input']],
  #       'Jack Slayer the Bean Slasher')
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'setButton']])

  # # Show that player shows up as having the gun
  # driver.ExpectContains([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'player-label']], "Jack Slayer the Bean Slasher")

  # Add another gun, assign to another player
  # driver.Click([[By.ID, 'add']])
  # driver.SendKeys(
  #       [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
  #       ' ') # (I'm guessing) the lowest ID (alpabetically I could choose)
  # driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])
  # driver.Click([[By.NAME, 'gun-row- '], [By.CLASS_NAME, 'pencil']])
  # driver.SendKeys(
  #       [[By.NAME, 'gun-row- '], [By.TAG_NAME, 'input']],
  #       'Moldavi the Moldavish') #TODO - select by clicking the dropdown instead
  # driver.Click([[By.NAME, 'gun-row- '], [By.ID, 'setButton']])

  # Sort by label - show that they swap
  # Sort by player - show that they swap
  # Change the weapon ID, and show that that shows up
  #####driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'menu']])
  # driver.SendKeys(
  #       [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
  #       '42')
  # driver.ExpectContains([[By.NAME, 'gun-row-42']], "42")

  # TODO - when implemented, have a player see that they've been assigned a gun

  # Admin - set got equipment for Jack
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-player-4'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  driver.Click([[By.NAME, 'player-row-player-4'], [By.NAME, 'menu-item-Set Got Equipment']])
  driver.ExpectContains([[By.NAME, 'player-row-player-4'], [By.ID, 'gotEquipment']], "Yes")

  # Check Jack's profile, make sure the change showed up
  driver.Click([[By.NAME, 'player-row-player-4'], [By.ID, 'name']])
  driver.ExpectContains([[By.ID, 'got-equipment']], "Yes")

  # If you set the equipment of someone who already has it, nothing should happen
  # driver.Click([[By.NAME, 'drawerAdmin Players']])
  # driver.Click([[By.NAME, 'player-row-4'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  # driver.Click([[By.NAME, 'player-row-4'], [By.NAME, 'menu-item-Set Got Equipment']])
  # driver.ExpectContains([[By.NAME, 'player-row-4'], [By.ID, 'gotEquipment']], "Yes")

  # Unset Jack's equipment

  # Admin - set not got equipment
  # Stack by equipment - show swap
  # Search by equipment - show only one
  # Add note
  # Search by note
  # Stack by note

finally:
  # driver.Quit()
>>>>>>> master
  pass
<commit_msg>whoops, one last merge conflict<commit_after>import setup
from selenium.webdriver.common.by import By

try:

  # Sign in as an admin
  driver = setup.MakeDriver(user="zella")

  ######################  Testing Admin Guns Page  ######################

  # Admin adds gun
  driver.Click([[By.NAME, 'drawerAdmin Guns']])
  driver.Click([[By.ID, 'add']])
  driver.SendKeys(
        [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
        '3.14')

  driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])

  # View added gun
  driver.ExpectContains([[By.NAME, 'gun-row-3.14']], "3.14")

  # Assign player a gun
  driver.Click([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'pencil']])
  driver.SendKeys(
        [[By.NAME, 'gun-row-3.14'], [By.TAG_NAME, 'input']],
        'Jack Slayer the Bean Slasher')
  driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'setButton']])

  # Show that player shows up as having the gun
  driver.ExpectContains([[By.NAME, 'gun-row-3.14'], [By.CLASS_NAME, 'player-label']], "Jack Slayer the Bean Slasher")

  #Add another gun, assign to another player
  driver.Click([[By.ID, 'add']])
  driver.SendKeys(
        [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
        'pancake')
  driver.Click([[By.ID, 'gunForm'],[By.ID, 'done']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.CLASS_NAME, 'pencil']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.TAG_NAME, 'input']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.NAME, '2: Moldavi the Moldavish']])
  driver.Click([[By.NAME, 'gun-row-pancake'], [By.ID, 'setButton']])

  # Search by label
  driver.Click([[By.NAME, 'header-Label'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Label'], [By.TAG_NAME, 'input']],
        'pan')
  driver.ExpectContains([[By.ID, 'table']], "Moldavi")
  driver.ExpectContains([[By.ID, 'table']], "Jack", False)
  driver.Backspace([[By.NAME, 'header-Label'], [By.TAG_NAME, 'input']], 3)

  # Search by player
  driver.Click([[By.NAME, 'header-Player'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Player'], [By.TAG_NAME, 'input']],
        'Jack')
  driver.ExpectContains([[By.ID, 'table']], "Jack")
  driver.ExpectContains([[By.ID, 'table']], "Moldavi", False)
  driver.Backspace([[By.NAME, 'header-Player'], [By.TAG_NAME, 'input']], 4)

  # THEORETICALLY WORKS, BUT NO PROMISES SINCE ITS CURRENTLY BROKEN SO I CAN'T TEST
  # Uncomment this block later
  # Change the weapon ID, and show that it shows up
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.ID, 'menu']])
  # driver.Click([[By.NAME, 'gun-row-3.14'], [By.NAME, 'menu-item-Edit']])
  # driver.SendKeys(
  #       [[By.ID, 'form-section-create-gun'], [By.TAG_NAME, 'input']],
  #       '42')
  # driver.Click([[By.ID, 'gunForm'], [By.ID, 'done']])
  # ## driver.ExpectContains([[By.NAME, 'gun-row-42']], "42")

  # TODO - when implemented, have a player see that they've been assigned a gun

  #####################  Testing Admin Players Page  ######################

  # Admin - set got equipment for Jack
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Got Equipment']]) # Doesn't update like it's supposed to - remote server
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "Yes") #Crashes here remote server

  # Check Jack's profile, make sure the change showed up
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'name']])
  driver.ExpectContains([[By.NAME, 'got-equipment']], "Yes")

  # If you set the equipment of someone who already has it, nothing should happen
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']]) # This is Jack (non-admin, human)
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Got Equipment']])
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "Yes")

  # Unset Jack's equipment
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Unset Got Equipment']])
  driver.ExpectContains([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'gotEquipment']], "No")

  # Check Jack's profile, make sure the change showed up
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'name']])
  driver.ExpectContains([[By.NAME, 'got-equipment']], "No")

  # Go back to the Admin Guns page
  driver.Click([[By.NAME, 'drawerAdmin Players']])

  # Search by number
  driver.Click([[By.NAME, 'header-#'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-#'], [By.TAG_NAME, 'input']],
        '3')
  driver.ExpectContains([[By.NAME, 'player-table']], "Jack") # Jack should show up
  driver.ExpectContains([[By.NAME, 'player-table']], "Deckerd", False) # Deckerd shouldn't show up
  driver.Backspace([[By.NAME, 'header-#'], [By.TAG_NAME, 'input']])

  # # Search by name
  driver.Click([[By.NAME, 'header-Name'], [By.NAME, 'icon-search']])
  driver.SendKeys(
        [[By.NAME, 'header-Name'], [By.TAG_NAME, 'input']],
        'Deckerd')
  driver.ExpectContains([[By.NAME, 'player-table']], "Deckerd") # Deckerd should show up
  driver.ExpectContains([[By.NAME, 'player-table']], "Jack", False) # Jack shouldn't show up
  driver.Backspace([[By.NAME, 'header-Name'], [By.TAG_NAME, 'input']], 7)

  # TODO - search by equipment once this works

  # TODO - add a note
  driver.Click([[By.NAME, 'drawerAdmin Players']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.ID, 'menu']])
  driver.Click([[By.NAME, 'player-row-Jack Slayer the Bean Slasher'], [By.NAME, 'menu-item-Set Notes']])

  # TODO - once we can add notes, search by notes
  # driver.Quit()

finally:
  pass
<|endoftext|>


<commit_before>"""
Author: Remy D <remyd@civx.us>
        Ralph Bean <rbean@redhat.com>
        Sam Lucidi <mansam@csh.rit.edu>
License: Apache 2.0

"""

from __future__ import division

import os
import glob
import yaml
import hashlib
from datetime import datetime, timedelta

# flask dependencies
from flask import Flask
from flask import jsonify
from flask.ext.mako import MakoTemplates, render_template
from werkzeug.exceptions import NotFound

# hflossk
from hflossk.util import count_posts
from hflossk.blueprints import homework, lectures, quizzes

app = Flask(__name__)
app.template_folder = "templates"
mako = MakoTemplates(app)
base_dir = os.path.split(__file__)[0]

# Automatically include site config
@app.context_processor
def inject_yaml():
    with open(os.path.join(base_dir, 'site.yaml')) as site_yaml:
        site_config = yaml.load(site_yaml)
    return site_config

app.config['MAKO_TRANSLATE_EXCEPTIONS'] = False
config = inject_yaml()
COURSE_START = datetime.combine(config['course']['start'], datetime.min.time())
COURSE_END = datetime.combine(config['course']['end'], datetime.max.time())

def gravatar(email):
    """
    Get a gravatar for an email address.

    I wish I could use libravatar here, but honestly, the students
    will be better off using gravatar at this point (due to github
    integration :/)

    """

    email = email.encode('utf8').lower()
    slug = hashlib.md5(email).hexdigest()
    libravatarURL = "https://seccdn.libravatar.org/avatar/"
    gravatarURL = "https://secure.gravatar.com/avatar/"
    return libravatarURL + slug +"?d=" + gravatarURL + slug

@app.route('/', defaults=dict(page='home'))
@app.route('/<page>')
def simple_page(page):
    """
    Render a simple page. Looks for a .mak template file
    with the name of the page parameter that was passed in.
    By default, this just shows the homepage.

    """

    return render_template('{}.mak'.format(page), name='mako')

@app.route('/syllabus')
def syllabus():
    """
    Render the syllabus page.

    """

    with open(os.path.join(base_dir, 'schedule.yaml')) as schedule_yaml:
        schedule = yaml.load(schedule_yaml)
    return render_template('syllabus.mak', schedule=schedule, name='mako')

@app.route('/blog/<username>')
def blog_posts(username):
    """
    Count number of posts on a student's
    blog.

    """

    student_data = None
    yaml_dir = 'scripts/people/'

    fname = os.path.join(yaml_dir, username + ".yaml")
    with open(fname) as student:
        contents = yaml.load(student)
        if not isinstance(contents, list):
            raise ValueError("%s's yaml file is broken." % fname)
        student_data = contents[0]

    num_posts = 0
    if 'feed' in student_data:
        print("Checking %s's blog feed." % username)
        num_posts = count_posts(student_data['feed'], COURSE_START)
    else:
        print("No feed listed for %s!" % username)
        raise NotFound()

    return jsonify(number=num_posts)

@app.route('/blogs/<year>/<term>/<username>')
@app.route('/participants/<year>/<term>/<username>')
@app.route('/checkblogs/<year>/<term>/<username>')
def participant_page(year, term, username):
    print year
    print term
    print username
    """
    Render a page that shows some stats about the selected participant
    """

    participant_data = {}
    yaml_dir = 'scripts/people/'
    participant_yaml = yaml_dir + year + '/' + term + '/' + username + '.yaml'
    with open(participant_yaml) as participant_data:
        participant_data = yaml.load(participant_data)

    return render_template(
        'participant.mak', name='make',
        participant_data=participant_data[0],
        gravatar=gravatar
    )

@app.route('/blogs')
@app.route('/participants')
@app.route('/checkblogs')
def participants():
    """
    Render the participants page,
    which shows a directory of all
    the students with their forge
    links, blog posts, assignment
    links, and etc.

    """

    yaml_dir = 'scripts/people/'

    student_data = []
    for dirpath, dirnames, files in os.walk(yaml_dir):
        for fname in files:
            if fname.endswith('.yaml'):
                with open(dirpath + '/' + fname) as students:
                    contents = yaml.load(students)

                    if not isinstance(contents, list):
                        raise ValueError("%r is borked" % fname)

                    student_data.extend(contents)

    assignments = ['litreview1']
    target_number = int((datetime.today() - COURSE_START).total_seconds() /
                        timedelta(weeks=1).total_seconds() + 1 + len(assignments))

    return render_template(
        'blogs.mak', name='mako',
        student_data=student_data,
        gravatar=gravatar,
        target_number=target_number
    )

@app.route('/oer')
@app.route('/resources')
def resources():
    resources = dict()
    resources['Decks'] = os.listdir(os.path.join(base_dir, 'static', 'decks'))
    resources['Books'] = os.listdir(os.path.join(base_dir, 'static', 'books'))
    resources['Challenges'] = os.listdir(os.path.join(base_dir, 'static', 'challenges'))
    resources['Videos'] = os.listdir(os.path.join(base_dir, 'static', 'videos'))

    return render_template('resources.mak', name='mako', resources=resources)

app.register_blueprint(homework, url_prefix='/assignments')
app.register_blueprint(homework, url_prefix='/hw')
app.register_blueprint(lectures, url_prefix='/lectures')
app.register_blueprint(quizzes, url_prefix='/quizzes')
app.register_blueprint(quizzes, url_prefix='/quiz')
<commit_msg>Participants now can pull from selected years and terms<commit_after>"""
Author: Remy D <remyd@civx.us>
        Ralph Bean <rbean@redhat.com>
        Sam Lucidi <mansam@csh.rit.edu>
License: Apache 2.0

"""

from __future__ import division

import os
import glob
import yaml
import hashlib
from datetime import datetime, timedelta, date

# flask dependencies
from flask import Flask
from flask import jsonify
from flask.ext.mako import MakoTemplates, render_template
from werkzeug.exceptions import NotFound

# hflossk
from hflossk.util import count_posts
from hflossk.blueprints import homework, lectures, quizzes

app = Flask(__name__)
app.template_folder = "templates"
mako = MakoTemplates(app)
base_dir = os.path.split(__file__)[0]

# Automatically include site config
@app.context_processor
def inject_yaml():
    with open(os.path.join(base_dir, 'site.yaml')) as site_yaml:
        site_config = yaml.load(site_yaml)
    return site_config

app.config['MAKO_TRANSLATE_EXCEPTIONS'] = False
config = inject_yaml()
COURSE_START = datetime.combine(config['course']['start'], datetime.min.time())
COURSE_END = datetime.combine(config['course']['end'], datetime.max.time())

def gravatar(email):
    """
    Get a gravatar for an email address.

    I wish I could use libravatar here, but honestly, the students
    will be better off using gravatar at this point (due to github
    integration :/)

    """

    email = email.encode('utf8').lower()
    slug = hashlib.md5(email).hexdigest()
    libravatarURL = "https://seccdn.libravatar.org/avatar/"
    gravatarURL = "https://secure.gravatar.com/avatar/"
    return libravatarURL + slug +"?d=" + gravatarURL + slug

@app.route('/', defaults=dict(page='home'))
@app.route('/<page>')
def simple_page(page):
    """
    Render a simple page. Looks for a .mak template file
    with the name of the page parameter that was passed in.
    By default, this just shows the homepage.

    """

    return render_template('{}.mak'.format(page), name='mako')

@app.route('/syllabus')
def syllabus():
    """
    Render the syllabus page.

    """

    with open(os.path.join(base_dir, 'schedule.yaml')) as schedule_yaml:
        schedule = yaml.load(schedule_yaml)
    return render_template('syllabus.mak', schedule=schedule, name='mako')

@app.route('/blog/<username>')
def blog_posts(username):
    """
    Count number of posts on a student's
    blog.

    """

    student_data = None

    fname = username
    with open(fname) as student:
        contents = yaml.load(student)
        if not isinstance(contents, list):
            raise ValueError("%s's yaml file is broken." % fname)
        student_data = contents[0]

    num_posts = 0
    if 'feed' in student_data:
        print("Checking %s's blog feed." % username)
        num_posts = count_posts(student_data['feed'], COURSE_START)
    else:
        print("No feed listed for %s!" % username)
        raise NotFound()

    return jsonify(number=num_posts)

@app.route('/blogs/<year>/<term>/<username>')
@app.route('/participants/<year>/<term>/<username>')
@app.route('/checkblogs/<year>/<term>/<username>')
def participant_page(year, term, username):
    print year
    print term
    print username
    """
    Render a page that shows some stats about the selected participant
    """

    participant_data = {}
    yaml_dir = 'scripts/people/'
    participant_yaml = yaml_dir + year + '/' + term + '/' + username + '.yaml'
    with open(participant_yaml) as participant_data:
        participant_data = yaml.load(participant_data)

    return render_template(
        'participant.mak', name='make',
        participant_data=participant_data[0],
        gravatar=gravatar
    )

@app.route('/blogs')
@app.route('/participants')
@app.route('/checkblogs')
def participants():
    year = str(date.today().year)
    print year
    return participants_year(year)

@app.route('/blogs/<year>')
@app.route('/participants/<year>')
@app.route('/checkblogs/<year>')
def participants_year(year): return participants(year + '/')

@app.route('/blogs/<year>/<term>')
@app.route('/participants/<year>/<term>')
@app.route('/checkblogs/<year>/<term>')
def participants_year_term(year, term): return participants(year + '/' + term + '/')

def participants(root_dir):
    """
    Render the participants page,
    which shows a directory of all
    the students with their forge
    links, blog posts, assignment
    links, and etc.

    """

    yaml_dir = 'scripts/people/' + root_dir

    student_data = []
    for dirpath, dirnames, files in os.walk(yaml_dir):
        for fname in files:
            if fname.endswith('.yaml'):
                with open(dirpath + '/' + fname) as students:
                    contents = yaml.load(students)
                    contents[0]['yaml'] = dirpath + '/' + fname

                    if not isinstance(contents, list):
                        raise ValueError("%r is borked" % fname)

                    student_data.extend(contents)

    assignments = ['litreview1']
    target_number = int((datetime.today() - COURSE_START).total_seconds() /
                        timedelta(weeks=1).total_seconds() + 1 + len(assignments))

    return render_template(
        'blogs.mak', name='mako',
        student_data=student_data,
        gravatar=gravatar,
        target_number=target_number
    )

@app.route('/oer')
@app.route('/resources')
def resources():
    resources = dict()
    resources['Decks'] = os.listdir(os.path.join(base_dir, 'static', 'decks'))
    resources['Books'] = os.listdir(os.path.join(base_dir, 'static', 'books'))
    resources['Challenges'] = os.listdir(os.path.join(base_dir, 'static', 'challenges'))
    resources['Videos'] = os.listdir(os.path.join(base_dir, 'static', 'videos'))

    return render_template('resources.mak', name='mako', resources=resources)

app.register_blueprint(homework, url_prefix='/assignments')
app.register_blueprint(homework, url_prefix='/hw')
app.register_blueprint(lectures, url_prefix='/lectures')
app.register_blueprint(quizzes, url_prefix='/quizzes')
app.register_blueprint(quizzes, url_prefix='/quiz')
<|endoftext|>