Elixir遊戲服設計六

接上章,我新建了個app作包含Table模型, TableServer等。Table桌子的代碼暫時以下, 有一些狀態還沒用上app

defmodule Table do
    
    @state_accept 0   #準備接入玩家
    @state_ready 1    #開局準備?
    defdelegate [fetch(t, key), get_and_update(t, key, list)], to: Map
    defstruct [:config, :seats, :state]
    def new(config) do
        %Table{
            config: config,
            seats: %{},
            state: @state_accept
        }
    end

    def is_full?(table) do
        cur_count = Enum.count(table.seats)
        cur_count >= table.config.allow_count
    end

    def has_player?(table, player_id) do
        table.seats[player_id]
    end

    def check_in(table, player) do
        update_in(table.seats, &(Map.put(&1, player.base_info.id, player)))
    end

    def check_out(table, player_id) do
        update_in(table.seats, &(Map.delete(&1, player_id)))
    end
end

咱們須要相關的配置table_config.txt函數

id,     allow_count,   base_gold,   need_gold,     desc
int,    int,           int,         int,        string
1,      4,             10,          480,         新手場
2,      4,             100,         4800,        中級場
3,      4,             1000,        48000,       高級場

這個txt能夠由excel經過xslx2csv工具生成。而後咱們利用table_config.txt 生成代碼配置table_config.ex.工具

咱們固然能夠在TableConfig裏經由excel文件直接生成,那樣會更方便。測試

defmodule TableConfig do
    Module.register_attribute __MODULE__, :column_names, []
    Module.register_attribute __MODULE__, :column_types, []
    Module.register_attribute __MODULE__, :config, []
    line_with_index = File.stream!(Path.join([__DIR__, "table_config.txt"]) , [], :line) 
                      |> Stream.with_index
    for {line, index} <- line_with_index do
        items = line |> String.split(",") |> Stream.map(&String.strip(&1)) 
        case index do
            0 ->
                @column_names items |> Enum.map(&String.to_atom(&1))
            1 ->
                @column_types items 
                              |> Stream.with_index 
                              |> Enum.map(fn {v, i} -> {i, String.to_atom(v)} end)
                              |> IO.inspect
                              |> Enum.into(%{})
            _ ->
                new_items = items 
                            |> Stream.with_index
                            |> Stream.map( &( TypeConverter.convert(&1, @column_types) ) )    
                zip = Enum.zip(@column_names, new_items)
                @config  Enum.into(zip, %{})
                IO.inspect @config
       # 如下函數花了我點時間,最後不得不經過模塊屬性完成,我不知道有沒有其餘方法
         # 早期的版本是者這樣的
# config = Enum.into(zip, %{})
# def get(unquote(config.id)) do
#   unquote(config) # 這裏會報錯,百思不得其解,在ErrorMsg裏我是這樣用的,沒有問題。不知2者區別在哪
# end
def get(unquote(@config.id)) do @config end end end end

最後上點測試代碼table_test.exsfetch

defmodule TabelTest do
  use ExUnit.Case
  # import PipeHere
  setup do
      config = TableConfig.get(1)   
      table = Table.new(config)
      {:ok, table: table}
  end

  test "table is full ", %{table: table} do
      new_table =
        1..table.config.allow_count 
        |> Stream.map(&Player.new/1)
        |> Enum.reduce(table, fn p, acc -> Table.check_in(acc, p) end)
    assert new_table |> Table.is_full?
  end

  test "table has player", %{table: table} do
       p1 = Player.new(1)
       p2 = Player.new(2)
       new_table = Table.check_in(table, p1)
       assert Table.has_player?(new_table, p1.base_info.id)
       refute Table.has_player?(table, p2.base_info.id)
  end

  test "table check_in_and_out", %{table: table} do
        p1 = Player.new(1)
        new_table = Table.check_in(table, p1)
        check_out_table = Table.check_out(new_table, p1.base_info.id)
        refute Table.has_player?(check_out_table, p1.base_info.id)
  end
end

下一小節會從牌局開始吧,而後TableServer,而後讓它跑起來。atom

相關文章
相關標籤/搜索