You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

134 lines
4.3 KiB

  1. from collections import OrderedDict
  2. from io import BytesIO
  3. import qrcode
  4. from django.http import HttpResponse
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.views.decorators.http import require_safe, require_http_methods
  7. from django.urls import reverse
  8. from .forms import NewGameForm, JoinGameForm, PlayerFormSet
  9. from .models import Game, Player
  10. def lookup_access_code(func):
  11. def with_game(request, access_code, *args, **kwargs):
  12. game = get_object_or_404(Game, access_code=access_code.lower())
  13. return func(request, game, *args, **kwargs)
  14. return with_game
  15. @require_safe
  16. def index(request):
  17. return render(request, 'index.html')
  18. @require_http_methods(["HEAD", "GET", "POST"])
  19. def enter_code(request):
  20. if request.method == 'POST':
  21. form = JoinGameForm(request.POST)
  22. if form.is_valid():
  23. game = form.cleaned_data['game']
  24. return redirect('game', access_code=game.access_code)
  25. else:
  26. form = JoinGameForm()
  27. return render(request, 'enter_code.html', {'form': form})
  28. @require_http_methods(["HEAD", "GET", "POST"])
  29. def new_game(request):
  30. if request.method == 'POST':
  31. form = NewGameForm(request.POST)
  32. formset = PlayerFormSet(request.POST)
  33. if form.is_valid() and formset.is_valid():
  34. player_forms = list(filter(lambda p: p.cleaned_data.get('name'),
  35. formset.forms))
  36. num_players = len(player_forms)
  37. game = Game()
  38. game.combined_growth_spirit =\
  39. form.cleaned_data.get('combined_growth_spirit')
  40. game.england_build = form.cleaned_data.get('england_build')
  41. game.fear_per_card =\
  42. form.cleaned_data.get('fear_per_player') * num_players
  43. game.save()
  44. for player_form in player_forms:
  45. player = Player()
  46. player.order = int(player_form.prefix[5:]) + 1
  47. player.spirit = player_form.cleaned_data.get('spirit')
  48. player.name = player_form.cleaned_data.get('name')
  49. player.game = game
  50. player.save()
  51. game.advance_phase()
  52. return redirect('game', access_code=game.access_code)
  53. else:
  54. form = NewGameForm()
  55. initial_player_data = [{'spirit': i}
  56. for i in enumerate(Player.SPIRIT_NAMES)]
  57. formset = PlayerFormSet(initial=initial_player_data)
  58. for player_form in formset:
  59. player_form.player_id = int(player_form.prefix[5:]) + 1
  60. return render(request, 'new_game.html',
  61. {'form': form, 'formset': formset})
  62. @require_safe
  63. def qr_code(request, access_code):
  64. join_url = reverse('game', kwargs={'access_code': access_code.lower()})
  65. join_url = request.build_absolute_uri(join_url)
  66. img = qrcode.make(join_url)
  67. output = BytesIO()
  68. img.save(output, "PNG")
  69. return HttpResponse(output.getvalue(), content_type='image/png')
  70. @lookup_access_code
  71. @require_safe
  72. def game(request, game):
  73. players = OrderedDict()
  74. for player in game.player_set.order_by('order').all():
  75. player.total_fear = 0
  76. player.fear = OrderedDict()
  77. players[player.order] = player
  78. for fear in game.get_current_phase().fear_set.order_by('effect').all():
  79. player[fear.player.order].fear[fear.effect] = {
  80. 'pure_fear': fear.pure_fear,
  81. 'towns': fear.towns_destroyed,
  82. 'cities': fear.cities_destroyed,
  83. }
  84. players[fear.player.order].total_fear +=\
  85. fear.pure_fear + fear.towns_destroyed + 2*fear.cities_destroyed
  86. for player in players.values():
  87. info = player.fear
  88. if not info:
  89. new_effect = 0
  90. else:
  91. new_effect = max(info.keys()) + 1
  92. info[new_effect] = {
  93. 'pure_fear': 0,
  94. 'towns': 0,
  95. 'cities': 0,
  96. }
  97. return render(request, 'game.html', {
  98. 'access_code': game.access_code,
  99. 'turn': game.game_turn,
  100. 'phase': game.get_current_phase_name(),
  101. 'available_fear_cards': game.num_available_fear_cards(),
  102. 'fear_to_next_card': game.get_fear_to_next_card(),
  103. 'fear_this_phase': game.get_current_phase().fear_this_phase(),
  104. 'players': players,
  105. })
  106. @lookup_access_code
  107. @require_safe
  108. def status(request, game):
  109. # TODO status json
  110. pass