Trading card city builder game?

implement updating the deck state when card is created

+143 -6
+1 -1
Justfile
··· 119 119 120 120 [group: "database"] 121 121 [working-directory: "server"] 122 - squirrel: up migrate 122 + squirrel: up 123 123 gleam run -m squirrel 124 124 125 125 [group: "database"]
+64 -5
server/src/actor/game_state_watcher.gleam
··· 1 1 import bus 2 2 import cartography_api/game_state 3 3 import db/game_state as db_game_state 4 + import db/rows 5 + import db/sql 4 6 import gleam/erlang/process 7 + import gleam/option 5 8 import gleam/otp/actor 6 9 import gleam/result 10 + import gleam/string 7 11 import mist 8 12 import pog 9 13 import youid/uuid ··· 66 70 } 67 71 68 72 fn handle_message(state: State, message: Message) -> actor.Next(State, Message) { 69 - case message { 70 - CardCreated(_card_id) -> { 71 - // TODO: include the card in the deck? 72 - actor.continue(state) 73 + let result = case message { 74 + CardCreated(game_state.TileId(tile_id)) -> { 75 + use tile <- result.try( 76 + state.db 77 + |> pog.named_connection() 78 + |> sql.get_tile(tile_id) 79 + |> result.map_error(string.inspect), 80 + ) 81 + use tile <- rows.one_or(tile, "created card (tile) not found") 82 + state.game_state 83 + |> add_tile_to_deck(game_state.Tile( 84 + id: game_state.TileId(tile.id), 85 + name: tile.name, 86 + tile_type_id: game_state.TileTypeId(tile.tile_type_id), 87 + )) 88 + |> fn(gs) { State(..state, game_state: gs) } 89 + |> actor.continue() 90 + |> Ok() 91 + } 92 + CardCreated(game_state.CitizenId(citizen_id)) -> { 93 + use citizen <- result.try( 94 + state.db 95 + |> pog.named_connection() 96 + |> sql.get_citizen(citizen_id) 97 + |> result.map_error(string.inspect), 98 + ) 99 + use citizen <- rows.one_or(citizen, "created card (citizen) not found") 100 + state.game_state 101 + |> add_citizen_to_deck(game_state.Citizen( 102 + id: game_state.CitizenId(citizen.id), 103 + name: citizen.name, 104 + species_id: game_state.SpeciesId(citizen.species_id), 105 + home_tile_id: option.map(citizen.home_tile_id, game_state.TileId), 106 + )) 107 + |> fn(gs) { State(..state, game_state: gs) } 108 + |> actor.continue() 109 + |> Ok() 73 110 } 74 - Stop -> actor.stop() 111 + Stop -> Ok(actor.stop()) 112 + } 113 + 114 + case result { 115 + Ok(next) -> next 116 + Error(error) -> actor.stop_abnormal(error) 75 117 } 76 118 } 119 + 120 + fn add_tile_to_deck(state: game_state.GameState, tile: game_state.Tile) { 121 + game_state.GameState( 122 + ..state, 123 + deck: game_state.Deck(..state.deck, tiles: [tile, ..state.deck.tiles]), 124 + ) 125 + } 126 + 127 + fn add_citizen_to_deck(state: game_state.GameState, citizen: game_state.Citizen) { 128 + game_state.GameState( 129 + ..state, 130 + deck: game_state.Deck(..state.deck, citizens: [ 131 + citizen, 132 + ..state.deck.citizens 133 + ]), 134 + ) 135 + }
+76
server/src/db/sql.gleam
··· 251 251 |> pog.execute(db) 252 252 } 253 253 254 + /// A row you get from running the `get_citizen` query 255 + /// defined in `./src/db/sql/get_citizen.sql`. 256 + /// 257 + /// > 🐿️ This type definition was generated automatically using v4.6.0 of the 258 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 259 + /// 260 + pub type GetCitizenRow { 261 + GetCitizenRow( 262 + species_id: String, 263 + name: String, 264 + home_tile_id: Option(Int), 265 + id: Int, 266 + ) 267 + } 268 + 269 + /// Runs the `get_citizen` query 270 + /// defined in `./src/db/sql/get_citizen.sql`. 271 + /// 272 + /// > 🐿️ This function was generated automatically using v4.6.0 of 273 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 274 + /// 275 + pub fn get_citizen( 276 + db: pog.Connection, 277 + arg_1: Int, 278 + ) -> Result(pog.Returned(GetCitizenRow), pog.QueryError) { 279 + let decoder = { 280 + use species_id <- decode.field(0, decode.string) 281 + use name <- decode.field(1, decode.string) 282 + use home_tile_id <- decode.field(2, decode.optional(decode.int)) 283 + use id <- decode.field(3, decode.int) 284 + decode.success(GetCitizenRow(species_id:, name:, home_tile_id:, id:)) 285 + } 286 + 287 + "SELECT * FROM citizens WHERE id = $1; 288 + " 289 + |> pog.query 290 + |> pog.parameter(pog.int(arg_1)) 291 + |> pog.returning(decoder) 292 + |> pog.execute(db) 293 + } 294 + 254 295 /// A row you get from running the `get_field_and_tiles_by_id` query 255 296 /// defined in `./src/db/sql/get_field_and_tiles_by_id.sql`. 256 297 /// ··· 499 540 " 500 541 |> pog.query 501 542 |> pog.parameter(pog.text(arg_1)) 543 + |> pog.returning(decoder) 544 + |> pog.execute(db) 545 + } 546 + 547 + /// A row you get from running the `get_tile` query 548 + /// defined in `./src/db/sql/get_tile.sql`. 549 + /// 550 + /// > 🐿️ This type definition was generated automatically using v4.6.0 of the 551 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 552 + /// 553 + pub type GetTileRow { 554 + GetTileRow(id: Int, tile_type_id: String, name: String) 555 + } 556 + 557 + /// Runs the `get_tile` query 558 + /// defined in `./src/db/sql/get_tile.sql`. 559 + /// 560 + /// > 🐿️ This function was generated automatically using v4.6.0 of 561 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 562 + /// 563 + pub fn get_tile( 564 + db: pog.Connection, 565 + arg_1: Int, 566 + ) -> Result(pog.Returned(GetTileRow), pog.QueryError) { 567 + let decoder = { 568 + use id <- decode.field(0, decode.int) 569 + use tile_type_id <- decode.field(1, decode.string) 570 + use name <- decode.field(2, decode.string) 571 + decode.success(GetTileRow(id:, tile_type_id:, name:)) 572 + } 573 + 574 + "SELECT * FROM tiles WHERE id = $1; 575 + " 576 + |> pog.query 577 + |> pog.parameter(pog.int(arg_1)) 502 578 |> pog.returning(decoder) 503 579 |> pog.execute(db) 504 580 }
+1
server/src/db/sql/get_citizen.sql
··· 1 + SELECT * FROM citizens WHERE id = $1;
+1
server/src/db/sql/get_tile.sql
··· 1 + SELECT * FROM tiles WHERE id = $1;