Skip to content
This repository was archived by the owner on Jan 9, 2024. It is now read-only.

Commit 93b5ad1

Browse files
authored
Merge pull request #100 from ruby-nord/bug/join-battle
Bug/join battle
2 parents 5a2c516 + 38ec52f commit 93b5ad1

File tree

20 files changed

+531
-205
lines changed

20 files changed

+531
-205
lines changed
Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
class GamesController < ApplicationController
2-
before_action :set_game, only: [:show]
3-
before_action :join_game, only: [:show], unless: :player_in_game?
2+
before_action :set_game, only: [:show]
43

54
def show
6-
@opponent ||= @game.players.where.not(id: current_player&.id).first || NilPlayer.new
7-
return render FinishedGame.template_path if @game.state == 'finished'
5+
@game = GameExhibit.new(@game, current_player)
86
end
97

108
def create
@@ -14,30 +12,12 @@ def create
1412

1513
private
1614

17-
def join_game
18-
return if @game.state == 'finished'
19-
enlist = Players::Enlist.new(game: @game, player: current_player)
20-
21-
if enlist.game_full?
22-
return render FullGame.template_path
23-
else # try to enter the game
24-
payload = enlist.assign_game_to_player!
25-
set_current_player(enlist.player)
26-
27-
ActionCable.server.broadcast "game_#{current_player.game_id}", payload
28-
end
29-
end
30-
31-
def player_in_game?
32-
current_player && current_player.game == @game
15+
def game_params
16+
params.require(:game).permit(:name)
3317
end
3418

3519
def set_game
3620
@game = Game.find_by(slug: params[:id].parameterize)
3721
redirect_to root_path unless @game
3822
end
39-
40-
def game_params
41-
params.require(:game).permit(:name)
42-
end
4323
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class OpponentController < ApplicationController
2+
before_action :set_game, only: [:create]
3+
4+
def create
5+
@enlist = Players::Enlist.new(game: @game, player: current_player)
6+
enlist_player if @enlist.available?
7+
8+
redirect_to game_path(@game)
9+
end
10+
11+
private
12+
13+
def enlist_player
14+
payload = @enlist.assign_game_to_player!
15+
set_current_player(@enlist.player)
16+
ActionCable.server.broadcast "game_#{current_player.game_id}", payload
17+
end
18+
19+
def set_game
20+
@game = Game.find_by(slug: params[:game_id].parameterize)
21+
return redirect_to root_path unless @game
22+
end
23+
end

app/dispatches/bombs/drop.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def successful_payloads
8282

8383
def finish_game
8484
player.update(won: true)
85-
game.update(state: 'finished')
85+
game.finished!
8686
end
8787
end
8888
end

app/dispatches/players/enlist.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
module Players
22
class Enlist
3-
MAX_PLAYERS = 2
4-
53
private
64
attr_reader :game
75

@@ -15,13 +13,13 @@ def initialize(game:, player:)
1513

1614
def assign_game_to_player!
1715
@player = Player.create!(nickname: nickname, game: game, life: Player::LIFE)
18-
@game.update(state: 'running')
16+
game.running!
1917

2018
return successful_payload
2119
end
2220

23-
def game_full?
24-
game.players.count >= MAX_PLAYERS
21+
def available?
22+
game.state == 'awaiting_opponent' && !game.full?
2523
end
2624

2725
private

app/exhibits/game_exhibit.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
class GameExhibit < SimpleDelegator
2+
def initialize(game, current_player)
3+
@current_player = current_player
4+
super(game)
5+
end
6+
7+
def to_partial_path
8+
case
9+
when finished?
10+
"games/finished_game"
11+
when awaiting_opponent? && player_is_not_part_of_the_game?
12+
"games/awaiting_opponent_game"
13+
when running? && player_is_not_part_of_the_game?
14+
"games/full_game"
15+
else
16+
super
17+
end
18+
end
19+
20+
def current_player
21+
@current_player
22+
end
23+
24+
def opponent
25+
players.where.not(id: current_player&.id).first || NilPlayer.new
26+
end
27+
28+
# this method must **not** be delegated to the underlying model; otherwise,
29+
# when the object is rendered by `ActionView::PartialRenderer` (eg. when calling `render` from a view),
30+
# `to_partial_path` will be sent to the actual model instead of the exhibit
31+
def to_model
32+
self
33+
end
34+
35+
def class
36+
__getobj__.class
37+
end
38+
39+
private
40+
41+
def player_is_not_part_of_the_game?
42+
! player_is_part_of_the_game?
43+
end
44+
45+
def player_is_part_of_the_game?
46+
@current_player&.plays_in?(__getobj__)
47+
end
48+
end
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AwaitingOpponentGame < Game
2+
def self.template_path
3+
"games/awaiting_opponent"
4+
end
5+
end

app/models/game.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,29 @@
33
# - running: the game is started
44
# - finished: game over. A player has destroyed his ennemy mothership
55
class Game < ApplicationRecord
6-
has_many :players, dependent: :destroy
7-
has_many :ships, through: :players
8-
has_many :words, dependent: :destroy
6+
MAX_PLAYERS = 2
7+
STATES = [
8+
AWAITING_OPPONENT = "awaiting_opponent",
9+
RUNNING = "running",
10+
FINISHED = "finished"
11+
]
912

1013
has_one :loser, -> { where(won: false ) }, class_name: 'Player'
1114
has_one :winner, -> { where(won: true ) }, class_name: 'Player'
1215

16+
has_many :players, dependent: :destroy
17+
has_many :ships, through: :players
18+
has_many :words, dependent: :destroy
19+
20+
STATES.each do |state|
21+
define_method("#{state}?") { self.state == state }
22+
define_method("#{state}!") { self.update state: state }
23+
end
24+
25+
def full?
26+
players.count >= MAX_PLAYERS
27+
end
28+
1329
def to_param
1430
slug
1531
end

app/models/player.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ class Player < ApplicationRecord
44
belongs_to :game
55

66
has_many :ships, dependent: :destroy
7+
8+
def plays_in?(game)
9+
self.game == game
10+
end
711
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<div class="row">
2+
<%= render "games/stars" %>
3+
<div class="wrapper">
4+
<div class="join_us">
5+
<div class="mothership">
6+
<div class="ship">
7+
<%= render "games/ships/svg/mothership" %>
8+
</div>
9+
</div>
10+
</div>
11+
<div class="too_late">
12+
<h1>You've been challenged to a battle!</h1>
13+
<p>Your opponent is waiting for you. Join the room <strong><%= awaiting_opponent_game.name %></strong> right now!</p>
14+
15+
<%= form_tag game_opponent_path(awaiting_opponent_game), method: :post do %>
16+
<%= submit_tag "Join Game", class: "button green" %>
17+
<% end %>
18+
</div>
19+
</div>
20+
</div>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<div class="row">
2+
<%= render "games/stars" %>
3+
<div class="wrapper">
4+
<div class="join_us">
5+
<div class="mothership">
6+
<div class="ship">
7+
<%= render "games/ships/svg/mothership" %>
8+
</div>
9+
</div>
10+
</div>
11+
<div class="too_late">
12+
<% case finished_game.current_player
13+
when finished_game.winner %>
14+
<h1>Game Finished, Congratulations! You WON!</h1>
15+
<p>
16+
You're the master of the <strong><%= finished_game.name %></strong> room
17+
where you defeated <strong><%= finished_game.opponent.nickname %></strong>.
18+
</p>
19+
<% when finished_game.loser %>
20+
<h1>Game Finished, You LOSE!</h1>
21+
<p>
22+
Today wasn't a good day for you in the <strong><%= finished_game.name %></strong> room.
23+
Looks like <strong><%= finished_game.opponent.nickname %></strong> ruled this finished_game.
24+
</p>
25+
<% else %>
26+
<h1>Too late! This finished is already finished_game.</h1>
27+
<p>
28+
You're currently in the <strong><%= finished_game.name %></strong> room
29+
where <strong><%= finished_game.players.first.nickname %></strong> and
30+
<strong><%= finished_game.players.last.nickname %></strong> had an epic fight deep in the space.
31+
</p>
32+
<% end %>
33+
34+
<p>In total, the battle involved <strong><%= finished_game.ships.count %> ships</strong> and <strong><%= finished_game.ships.sum(:damage) %> damages</strong>.</p>
35+
36+
<%= render 'components/social_links' %>
37+
</div>
38+
</div>
39+
</div>

0 commit comments

Comments
 (0)