Skip to content

Commit

Permalink
feat: implement Change for Room and Player
Browse files Browse the repository at this point in the history
  • Loading branch information
dennyabrain committed Aug 20, 2024
1 parent 9e39d80 commit 15640fb
Show file tree
Hide file tree
Showing 17 changed files with 314 additions and 56 deletions.
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ config :viral_spiral, RoomConfig,
chaos_counter: 10,
volatility: :medium

config :viral_spiral, CardConfig, card_types: [:affinity, :bias, :topical, :conflated]

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
21 changes: 21 additions & 0 deletions lib/viral_spiral/deck/card.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule ViralSpiral.Deck.Card do
import ViralSpiral.Deck.CardGuards
alias ViralSpiral.Deck.Card

defstruct id: nil,
type: nil

@type card_types :: :affinity | :bias | :topical | :conflated

@type t :: %__MODULE__{
id: String.t(),
type: card_types()
}

def new(type) when is_card_type(type) do
%Card{
id: UXID.generate!(prefix: "card", size: :small),
type: type
}
end
end
6 changes: 6 additions & 0 deletions lib/viral_spiral/deck/card_content.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
defmodule ViralSpiral.Deck.CardContent do
defstruct title: "",
description: "",
fake_title: "",
fake_description: ""
end
5 changes: 5 additions & 0 deletions lib/viral_spiral/deck/card_guards.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule ViralSpiral.Deck.CardGuards do
@card_types Application.compile_env(:viral_spiral, CardConfig)[:card_types]

defguard is_card_type(value) when value in @card_types
end
22 changes: 21 additions & 1 deletion lib/viral_spiral/game.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
defmodule ViralSpiral.Game do
@moduledoc """
Context for Game
"""
alias ViralSpiral.Game.State
alias ViralSpiral.Game.Score.Player
alias ViralSpiral.Game.Player
alias ViralSpiral.Deck.Card
alias ViralSpiral.Game.Room

@spec create_room(String.t()) :: Room.t()
Expand All @@ -9,7 +16,17 @@ defmodule ViralSpiral.Game do
def join_room(_name, _password) do
end

def pass_card(_state, _player, _to) do
@doc """
Pass a card from one player to another.
"""
# @spec pass_card(Player.t(), Card.t()) :: list(Change.t())
def pass_card(state, %Card{} = card, %Player{} = from, %Player{} = _to) do
changes =
case card.type do
:affinity -> [{state.player_scores[from.id], [type: :inc, target: :affinity, count: 1]}]
end

State.apply_changes(state, changes)
end

def keep_card(_player) do
Expand All @@ -24,6 +41,9 @@ defmodule ViralSpiral.Game do
def cancel_player(_player, _target) do
end

def cancel_player_vote(_player, _target) do
end

def viral_spiral(_player, _targets) do
end
end
14 changes: 14 additions & 0 deletions lib/viral_spiral/game/_change.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# defmodule ViralSpiral.Game.Change do
# defstruct type: nil,
# target: nil,
# target_id: nil

# @type change_type :: :inc | :dec | :value
# @type target :: :chaos_counter | :clout | :affinity | :bias

# @type t :: %__MODULE__{
# type: change_type(),
# target: target(),
# target_id: String.t()
# }
# end
8 changes: 8 additions & 0 deletions lib/viral_spiral/game/player.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule ViralSpiral.Game.Player do
alias ViralSpiral.Deck.Card
alias ViralSpiral.Game.Player
alias ViralSpiral.Game.RoomConfig

Expand All @@ -7,6 +8,13 @@ defmodule ViralSpiral.Game.Player do
identity: nil,
hand: []

@type t :: %__MODULE__{
id: String.t(),
name: String.t(),
identity: atom(),
hand: list(Card.t())
}

def new() do
%Player{
id: UXID.generate!(prefix: "player", size: :small)
Expand Down
51 changes: 0 additions & 51 deletions lib/viral_spiral/game/score.ex

This file was deleted.

25 changes: 25 additions & 0 deletions lib/viral_spiral/game/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule ViralSpiral.Game.State do
When a round begins, we also start a Turn. Within each Round there's a turn that includes everyone except the person who started the turn.
"""
alias ViralSpiral.Game.State
alias ViralSpiral.Game.Change

def set_round(%State{} = game, round) do
%State{game | round: round}
Expand All @@ -26,4 +27,28 @@ defmodule ViralSpiral.Game.State do
def set_turn(%State{} = game, turn) do
%State{game | turn: turn}
end

# @spec apply_changes(list(Change.t())) ::
# list({:ok, message :: String.t()} | {:error, reason :: String.t()})
def apply_changes(state, changes) do

Check warning on line 33 in lib/viral_spiral/game/state.ex

View workflow job for this annotation

GitHub Actions / build-and-deploy

variable "state" is unused (if the variable is not meant to be used, prefix it with an underscore)
# Enum.reduce(changes, [], &(&2 ++ [apply_change(elem(&1, 0), elem(&1, 1))]))
_results = Enum.map(changes, &apply(elem(&1, 0), elem(&1, 1)))
# new_state = Enum.reduce(results, state, &)

# results = Enum.reduce...
# state = Enum.reduce(results, state, &Map.put(&1.id, &1.value))
end

defdelegate apply_change(change, opts), to: Change

Check warning on line 42 in lib/viral_spiral/game/state.ex

View workflow job for this annotation

GitHub Actions / build-and-deploy

ViralSpiral.Game.Change.apply_change/2 is undefined (module ViralSpiral.Game.Change is not available or is yet to be defined)

# @doc """
# Change various components of state.

# round, turn, room, card, player_score
# """
# def apply(state, change) do
# case change do
# %{id: id, value: value}
# end
# end
end
2 changes: 1 addition & 1 deletion lib/viral_spiral/game/turn.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defmodule ViralSpiral.Game.Turn do
pass_to: []

@type t :: %__MODULE__{
current: String.t(),
current: String.t() | nil,
pass_to: list(String.t())
}

Expand Down
10 changes: 10 additions & 0 deletions lib/viral_spiral/score/change.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defprotocol ViralSpiral.Score.Change do
@moduledoc """
Protocol to change scores used in Viral Spiral.
## Fields
- score: struct which implements the `Change` protocol
- change_description: a Keyword List with parameters defining the change
"""
def apply_change(score, change_description)
end
70 changes: 70 additions & 0 deletions lib/viral_spiral/score/player.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
defmodule ViralSpiral.Score.Player do
@moduledoc """
Create and update Player Score.
## Example
iex> player_score = %ViralSpiral.Game.Score.Player{
biases: %{red: 0, blue: 0},
affinities: %{cat: 0, sock: 0},
clout: 0
}
"""
alias ViralSpiral.Score.Player
alias ViralSpiral.Game.RoomConfig
alias ViralSpiral.Game.Player, as: PlayerData
import ViralSpiral.Game.RoomConfig.Guards
alias ViralSpiral.Score.Change

defstruct biases: %{}, affinities: %{}, clout: 0

@type change_opts :: [type: :clout | :affinity | :bias, offset: integer(), target: atom()]
@type t :: %__MODULE__{
biases: map(),
affinities: map(),
clout: integer()
}

def new(%PlayerData{} = player, %RoomConfig{} = room_config) do
bias_list = Enum.filter(room_config.communities, &(&1 != player.identity))
bias_map = Enum.reduce(bias_list, %{}, fn x, acc -> Map.put(acc, x, 0) end)

affinity_list = room_config.affinities
affinity_map = Enum.reduce(affinity_list, %{}, fn x, acc -> Map.put(acc, x, 0) end)

%Player{
biases: bias_map,
affinities: affinity_map
}
end

defimpl Change do
@doc """
Implement change protocol for a Player's Score.
"""
@spec apply_change(Player.t(), Player.change_opts()) :: Player.t()
def apply_change(player, opts) do
case opts[:type] do
:clout -> change(player, :clout, opts[:offset])
:affinity -> change(player, :affinity, opts[:target], opts[:offset])
:bias -> change(player, :bias, opts[:target], opts[:offset])
end
end

def change(%Player{} = player, :bias, target_bias, count)
when is_community(target_bias) and is_integer(count) do
new_biases = Map.put(player.biases, target_bias, player.biases[target_bias] + count)
%{player | biases: new_biases}
end

def change(%Player{} = player, :affinity, target, count)
when is_affinity(target) and is_integer(count) do
new_affinities = Map.put(player.affinities, target, player.affinities[target] + count)
%{player | affinities: new_affinities}
end

def change(%Player{} = player, :clout, count) when is_integer(count) do
new_clout = player.clout + count
%{player | clout: new_clout}
end
end
end
38 changes: 38 additions & 0 deletions lib/viral_spiral/score/room.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule ViralSpiral.Score.Room do
@moduledoc """
## Example
"""
alias ViralSpiral.Score.Change
alias ViralSpiral.Score.Room
defstruct chaos_countdown: 10

@type t :: %__MODULE__{
chaos_countdown: integer()
}

@spec new() :: ViralSpiral.Score.Room.t()
def new() do
%Room{}
end

@spec countdown(ViralSpiral.Score.Room.t()) :: ViralSpiral.Score.Room.t()
def countdown(%Room{} = room) do
%{room | chaos_countdown: room.chaos_countdown - 1}
end

defimpl Change do
@spec apply_change(ViralSpiral.Score.Room.t(), keyword()) :: ViralSpiral.Score.Room.t()
def apply_change(%Room{} = score, opts) do
opts = Keyword.validate!(opts, offset: 0)

case opts[:offset] do
x when is_integer(x) ->
Map.put(score, :chaos_countdown, score.chaos_countdown + opts[:offset])

y when is_bitstring(y) ->
Map.put(score, :chaos_countdown, score.chaos_countdown)
end
end
end
end
20 changes: 18 additions & 2 deletions test/support/fixtures.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule Fixtures do
alias ViralSpiral.Deck.Card
alias ViralSpiral.Game.Score.Player
alias ViralSpiral.Game.Turn
alias ViralSpiral.Game.Round
Expand All @@ -10,7 +11,7 @@ defmodule Fixtures do
alias ViralSpiral.Game.State

def initialized_game() do
room_config = %RoomConfig{} |> IO.inspect()
room_config = %RoomConfig{}

player_list = [
Player.new(room_config) |> Player.set_name("adhiraj"),
Expand All @@ -24,6 +25,17 @@ defmodule Fixtures do
round = Round.new(player_list)
turn = Turn.new(round)

player_score_list =
Enum.map(
player_list,
&(Map.new() |> Map.put(:id, &1.id) |> Map.put(:score, PlayerScore.new(&1, room_config)))
)

player_score_map =
Enum.reduce(player_score_list, %{}, fn player, acc ->
Map.put(acc, player.id, player.score)
end)

%State{
room_config: room_config,
room: Room.new(),
Expand All @@ -32,7 +44,11 @@ defmodule Fixtures do
round: round,
turn: turn,
# room_score: RoomScore.new(),
player_scores: Enum.map(player_list, &PlayerScore.new(&1, room_config))
player_scores: player_score_map
}
end

def card_affinity() do
Card.new(:affinity)
end
end
Loading

0 comments on commit 15640fb

Please sign in to comment.