def view_state(request, state_id): if not request.user.is_superuser: return forbidden() state = get_object_or_404(State, id=state_id) config = Configuration.objects.get(pk=1) schema = config.schema() deform_templates = resource_filename('deform', 'templates') search_path = (settings.DEFORM_TEMPLATE_OVERRIDES, deform_templates) renderer = deform.ZPTRendererFactory(search_path) form = deform.Form(schema, buttons=('submit',), renderer=renderer) readonly = get_readonly_from_state(state) available_sections = get_available_sections(state) # Deform's form.render API allows you to pass a readonly=True flag # to have deform render a readonly representation of the data; # but, the default readonly templates aren't form-like, they're just # unstyled lists which look really ugly in our layout. # So, instead, the mvsim django template receives the readonly flag, # and, if it's set, removes Deform's javascript and injects some JS # to disable all the form fields on page load. The result is prettier. if request.method == "GET": return view_form(request, state, form, readonly, available_sections) if readonly: return forbidden() controls = parse_qsl(request.body, keep_blank_values=True) try: appstruct = form.validate(controls) except deform.ValidationFailure as e: course = None if state.game: course = state.game.course rv = { 'form': e.render(), 'readonly': readonly, 'state': state, 'course': course, 'available_sections': available_sections} return rv new_state = json.dumps(appstruct) state.state = new_state state.save() url = "%s?msg=saved" % state.view_state_url() return redirect(url)
def edit_game(request, game_id): game = get_object_or_404(Game, pk=game_id) if not game.viewable(request.user): return forbidden() game.name = request.GET.get('name', smart_text(game)) game.save() return HttpResponse("ok")
def edit_state(request, state_id): if not request.user.is_superuser: return forbidden() state = get_object_or_404(State, id=state_id) if 'visible' in request.POST: state.visible = request.POST.get('visible') == "True" state.save() posted_sections = request.POST.getlist('associated_sections') associated_sections = list(state.coursesection_set.all()) # Add new sections for section_id in posted_sections: section = get_object_or_404(CourseSection, id=section_id) if section not in associated_sections: section.starting_states.add(state) section.save() # Remove sections as needed for section in associated_sections: if str(section.id) not in posted_sections: section.starting_states.remove(state) section.save() return redirect(state.view_state_url())
def admin_course_sections(request): if not request.user.is_superuser: return forbidden() sections = CourseSection.objects.all() states = State.objects.all().exclude(name="").order_by("name") return dict(sections=sections, all_states=states)
def delete_game(request, game_id): statsd.incr("event.delete_game") game = get_object_or_404(Game, pk=game_id) section = game.course_section() if not game.viewable(request.user): return forbidden() game.delete() return redirect("/section/%d/games/" % section.id)
def history(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() display_vars = build_template_context(request, game) return display_vars
def show_turn(request, game_id): game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() if not game.in_progress(): return redirect(game.game_over_url()) display_vars = build_template_context(request, game) return display_vars
def show_turn(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() if not game.in_progress(): return redirect(game.game_over_url()) display_vars = build_template_context(request, game) return display_vars
def admin_course_section(request, section_id): if not request.user.is_superuser: return forbidden() section = get_object_or_404(CourseSection, id=section_id) states = State.objects.all().exclude(name="") users = [] for u in section.users.all(): users.append(u.get_full_name() if u.get_full_name() else u.username) return dict(section=section, all_states=states, users=sorted(users))
def view_turn_history(request, game_id, turn_number): game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() turn_number = int(turn_number) if turn_number == 1: return view_turn_history_first_turn(request, game_id) display_vars = build_template_context(request, game, turn_number) return display_vars
def view_turn_history(request, game_id, turn_number): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() turn_number = int(turn_number) if turn_number == 1: return view_turn_history_first_turn(request, game_id) turn = game.get_state(int(turn_number)) display_vars = build_template_context(request, game, turn_number) return display_vars
def graph(request, game_id): game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() turns = [game.deserialize(state) for state in game.state_set.order_by("created")] params = {} primary_layers = [] primary_xaxis = None secondary_xaxis = None layer_names = {} kw = request.GET for key in kw: if key == "primary_xaxis": primary_xaxis = kw['primary_xaxis'] continue if key == "secondary_xaxis": secondary_xaxis = kw['secondary_xaxis'] continue if key.endswith("_label"): layer = key[:-1 * len("_label")] name = kw[key] layer_names[layer] = name continue if key == "primary": primary_layers = extract_primary_layers(kw, key, primary_layers) continue params = extract_params(kw, key, params) params = params or {"layer_1": []} primary_layers = sorted(primary_layers) or [] all_variables = game.configuration.variables.all() variables = process_variables(all_variables, turns) return dict(game=game, params=params, variables=variables, primary_xaxis=primary_xaxis, secondary_xaxis=secondary_xaxis, primary_layers=primary_layers, layers=params, layer_names=layer_names, turns=turns)
def history(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request.user): return forbidden() section = game.course_section(user=request.user) starting_state_id = None if section.starting_states.all().count() > 0: starting_state_id = section.starting_states.all()[0].id display_vars = build_template_context(request, game) display_vars['starting_state_id'] = starting_state_id display_vars['section'] = section return display_vars
def submit_turn(request, game_id): statsd.incr("event.play_turn") game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() state = game.deserialize(game.current_state()) variables, coefficients = state['variables'], state['coefficients'] while '' in variables.owned_items: variables.owned_items.remove('') while '' in variables.user_messages: variables.user_messages.remove('') from engine.simple_controller import adjust_submission kwargs = {} for key in request.POST: kwargs[key] = request.POST.get(key) kwargs = adjust_submission(kwargs, variables.names) user_submission = game.user_input.schema().deserialize(kwargs) for key in user_submission: variables[key] = user_submission[key] tc = ChainedRandom() turn = logic.Turn(variables, coefficients, tc) alive, variables = turn.go() del variables.people old_state = game.current_state() new_state = State(name=old_state.name, game=old_state.game) new_state.state = json.dumps(dict( variables=variables, coefficients=coefficients)) new_state.save() if not alive: game.mark_finished() game.save() game.score = game.calculate_score() game.save() return redirect(game.show_game_url())
def game_over(request, game_id): statsd.incr("event.game_over") game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() section = game.course_section(user=request.user) starting_state_id = None if section.starting_states.all().count() > 0: starting_state_id = section.starting_states.all()[0].id if game.in_progress(): return redirect(game.show_game_url()) display_vars = build_template_context(request, game) display_vars['starting_state_id'] = starting_state_id display_vars['section'] = section return display_vars
def submit_turn(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() state = game.deserialize(game.current_state()) variables, coefficients = state['variables'], state['coefficients'] if '' in variables.owned_items: variables.owned_items.remove('') if '' in variables.user_messages: variables.user_messages.remove('') from engine.simple_controller import adjust_submission kwargs = {} for key in request.POST: kwargs[key] = request.POST.get(key) kwargs = adjust_submission(kwargs, variables.names) user_submission = game.user_input.schema().deserialize(kwargs) for key in user_submission: variables[key] = user_submission[key] from twisterclient import TwisterClient as TC tc = TC(base="http://twister.ccnmtl.columbia.edu/", chain=True) turn = logic.Turn(variables, coefficients, tc) alive, variables = turn.go() del variables.people import json old_state = game.current_state() new_state = State(name=old_state.name, game=old_state.game) new_state.state = json.dumps(dict( variables=variables, coefficients=coefficients)) new_state.save() if not alive: game.mark_finished() game.save() return redirect(game.show_game_url())
def clone_state(request, state_id): if not request.user.is_superuser: return forbidden("Forbidden") state = get_object_or_404(State, id=state_id) new_state = State(name=request.POST.get('state_name') or state.name) new_state.state = state.state new_state.visible = request.POST.get('visible', False) == "True" new_state.save() # Add new sections posted_sections = request.POST.getlist('associated_sections') for section_id in posted_sections: section = get_object_or_404(CourseSection, id=section_id) section.starting_states.add(new_state) section.save() return redirect(new_state.view_state_url())
def associate_state(request, section_id): if not request.user.is_superuser: return forbidden() section = get_object_or_404(CourseSection, id=section_id) posted_states = request.POST.getlist('associated_states') associated_states = list(section.starting_states.all()) # Add new states for state_id in posted_states: state = get_object_or_404(State, id=state_id) if state not in associated_states: section.starting_states.add(state) section.save() # Remove sections as needed for state in associated_states: if str(state.id) not in posted_states: section.starting_states.remove(state) section.save() return redirect("/course_sections/%d/" % section.id)
def view_state(request, state_id): state = State.objects.get(id=state_id) config = Configuration.objects.get(pk=1) schema = config.schema() deform_templates = resource_filename('deform', 'templates') search_path = (settings.DEFORM_TEMPLATE_OVERRIDES, deform_templates) renderer = deform.ZPTRendererFactory(search_path) form = deform.Form(schema, buttons=('submit',), renderer=renderer) readonly = False if state.game: readonly = True # Deform's form.render API allows you to pass a readonly=True flag # to have deform render a readonly representation of the data; # but, the default readonly templates aren't form-like, they're just # unstyled lists which look really ugly in our layout. # So, instead, the mvsim django template receives the readonly flag, # and, if it's set, removes Deform's javascript and injects some JS # to disable all the form fields on page load. The result is prettier. if request.method == "GET": return {'form': form.render(state.loads()), 'readonly': readonly, 'state': state} if readonly: return forbidden() # trick from Chris Pyper, http://groups.google.com/group/pylons-discuss/browse_thread/thread/83b4f2950cbc1892?hl=en controls = parse_qsl(request.raw_post_data, keep_blank_values=True) try: appstruct = form.validate(controls) except deform.ValidationFailure, e: return {'form': e.render(), 'readonly': readonly, 'state': state}
def game_over(request, game_id): sections = CourseSection.objects.filter(users=request.user, course=request.course) try: section = sections[0] except IndexError: section = CourseSection.objects.filter(course=request.course)[0] section.users.add(request.user) section.save() try: starting_state_id = section.starting_states.all()[0].id except: starting_state_id = None game = Game.objects.get(pk=game_id) if game.in_progress(): return redirect(game.show_game_url()) if not game.viewable(request): return forbidden() display_vars = build_template_context(request, game) display_vars['starting_state_id'] = starting_state_id return display_vars
def course_section_game_stats(request, section_id): if not request.user.is_superuser: return forbidden() section = get_object_or_404(CourseSection, id=section_id) return dict(section=section)
def view_turn_history_first_turn(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() return {'game': game}
def graph(request, game_id): game = Game.objects.get(pk=game_id) if not game.viewable(request): return forbidden() turns = [game.deserialize(state) for state in game.state_set.order_by("created")] params = {} primary_layers = [] primary_xaxis = None secondary_xaxis = None layer_names = {} kw = request.GET for key in kw: if key == "primary_xaxis": primary_xaxis = kw['primary_xaxis'] continue if key == "secondary_xaxis": secondary_xaxis = kw['secondary_xaxis'] continue if key.endswith("_label"): layer = key[:-1*len("_label")] name = kw[key] layer_names[layer] = name continue if key == "primary": for val in kw.getlist(key): primary_layers.append(val) continue for val in kw.getlist(key): params.setdefault(key, []).append(val) params = params or {"layer_1": []} primary_layers = sorted(primary_layers) or [] all_variables = game.configuration.variables.all() excluded_variables = ( 'calculated_food_cost', 'cotton_yield', 'energy_req', 'fertilizer_last_turn', 'fertilizer_t1', 'fertilizer_t2', 'fish_coeff', 'food_yield', 'initial_population', 'market', 'maximum_effort', 'propane_fuel', 'season', 'try_for_child', 'wood_coeff', 'wood_fuel', 'year', ) class BoundVariable(object): def __init__(self, name, getter=None, descriptive_name=None): self.name = name self.descriptive_name = descriptive_name or name.replace("_", " ").title() self.values = [] for turn in turns: if getter is None: self.values.append( turn.variables[name]) else: self.values.append( getter(turn, name)) variables = [] def add_divided_farming(): # in addition to effort_farming, we also want to calculate # separate variables for each turn's effort farming spent # on each of maize and cotton def getter(turn, name): total_effort = turn.variables.effort_farming plots = turn.variables.crops if name == "effort_farming_maize": amount = sum(1 for i in plots if i == "Maize") elif name == "effort_farming_cotton": amount = sum(1 for i in plots if i == "Cotton") amount = 1.0 * amount / len(plots) return total_effort * amount variables.append(BoundVariable("effort_farming_maize", getter, "Effort Farming Maize (person-hours/day)")) variables.append(BoundVariable("effort_farming_cotton", getter, "Effort Farming Cotton (person-hours/day)")) def add_divided_health(): # since health is a compound variable, we want to split it apart # into individual variables for each family member def getter(turn, name): health = turn.variables.health person_name = name[len("health_"):].title() # name will be like health_kodjo names = turn.variables.names try: index = names.index(person_name) except ValueError: # this person was not yet born, or was dead, at this turn return 0 return health[index] # we need to figure out all the people who were ever part of the family all_names = {} for turn in turns: names = turn.variables.names for name in names: all_names[name] = "health_" + name.lower() for name, var_name in all_names.items(): variables.append(BoundVariable( var_name, getter, "Health %s " % name + "(%)")) def add_average_health(): # since health is a compound variable, we want to split it apart # into individual variables for each family member def getter(turn, name): health = turn.variables.health names = turn.variables.names if len(names) == 0: return 0 return sum(health) / len(names) variables.append(BoundVariable( "health_average", getter, "Average Family Health (%)")) def add_divided_sickness(): # since sick is a compound variable, we want to split it apart # into individual variables for each family member def getter(turn, name): sick = turn.variables.sick person_name = name[len("sick_"):].title() # name will be like health_kodjo names = turn.variables.names try: index = names.index(person_name) except ValueError: # this person was not yet born, or was dead, at this turn return 0 return int(bool(sick[index].strip())) # we need to figure out all the people who were ever part of the family all_names = {} for turn in turns: names = turn.variables.names for name in names: all_names[name] = "sick_" + name.lower() for name, var_name in all_names.items(): variables.append(BoundVariable( var_name, getter, "%s Sick" % name)) def add_percent_sickness(): def getter(turn, name): sick = turn.variables.sick names = turn.variables.names if len(names) == 0: return 0 return 1.0 * sum(bool(i.strip()) for i in sick) / len(names) variables.append(BoundVariable( "sick_percent", getter, "Family Sick (% of family)")) for variable in all_variables: if variable.name in excluded_variables: continue if variable.name == "health": add_divided_health() add_average_health() continue if variable.name == "sick": add_divided_sickness() add_percent_sickness() continue if variable.type == "bool": def getter(turn, name): value = turn.variables[name] return int(value) variables.append(BoundVariable( variable.name, getter, variable.description)) continue if not variable.graphable(): continue variables.append(BoundVariable( variable.name, descriptive_name=variable.description)) if variable.name == "effort_farming": add_divided_farming() return dict(game=game, params=params, variables=variables, primary_xaxis=primary_xaxis, secondary_xaxis=secondary_xaxis, primary_layers=primary_layers, layers=params, layer_names=layer_names, turns=turns)
def view_turn_history_first_turn(request, game_id): game = get_object_or_404(Game, id=game_id) if not game.viewable(request.user): return forbidden() return {'game': game}