extern crate basic_pathfinding; extern crate web_wars_engine; use uuid::Uuid; use basic_pathfinding::coord::Coord; use web_wars_engine::actions; use web_wars_engine::fixtures::tiles::TileKind; use web_wars_engine::fixtures::powers::PowerKind; use web_wars_engine::fixtures::units; use web_wars_engine::models::action::{Action, ActionKind}; use web_wars_engine::models::game::{Game, MapSettings, Boundary}; use web_wars_engine::models::tile::TileData; use web_wars_engine::models::unit::UnitData; use web_wars_engine::models::user::UserData; use web_wars_engine::models::power::PowerData; use web_wars_engine::traits::stateful::UnitState; #[macro_export] macro_rules! hashmap { ($( $key: expr => $val: expr ),*) => {{ let mut map = ::std::collections::HashMap::new(); $( map.insert($key, $val); )* map }} } // apply/1 #[test] pub fn accrues_funds() { let id = Uuid::new_v4(); let action = Action { kind: ActionKind::Turn, user_id: id, ..Default::default() }; let mut game = Game { active: true, map_settings: MapSettings { funds_per_turn: 1000, ..Default::default() }, tile_data: vec![ TileData {user_id: Some(id), tile_id: TileKind::City, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::City, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Base, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Port, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Airport, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::HQ, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Beacon, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Lab, ..Default::default() }, TileData {tile_id: TileKind::City, ..Default::default() }, ], user_data: vec![ UserData { team: 1, id: Uuid::new_v4(), active: true, turn: false, funds: 123, user_id: id, position: 0, ..Default::default() }, UserData { team: 2, id: Uuid::new_v4(), active: false, turn: true, funds: 321, position: 1, ..Default::default() } ], ..Default::default() }; let result = actions::apply(action, game).unwrap(); game = result.game; assert_eq!(game.user_data[0].team, 2); assert_eq!(game.user_data[0].funds, 321); assert_eq!(game.user_data[0].turn, false); assert_eq!(game.user_data[1].team, 1); assert_eq!(game.user_data[1].funds, 6123); assert_eq!(game.user_data[1].turn, true); assert_eq!(game.turn_user_id, id); } #[test] pub fn accrues_funds_with_fund_income_bonus_power() { let id = Uuid::new_v4(); let mut game = Game { active: true, map_settings: MapSettings { funds_per_turn: 2000, ..Default::default() }, tile_data: vec![ TileData {user_id: Some(id), tile_id: TileKind::City, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::City, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Base, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Port, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Airport, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::HQ, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Beacon, ..Default::default() }, TileData {user_id: Some(id), tile_id: TileKind::Lab, ..Default::default() }, ], user_data: vec![ UserData { active: true, turn: false, id: Uuid::new_v4(), user_id: id, funds: 123, team: 1, position: 0, power_data: vec![ PowerData { power_id: PowerKind::FundIncomeBonus, params: vec!["100"], ..Default::default() } ], ..Default::default() }, UserData { active: false, turn: true, funds: 321, team: 2, position: 1, ..Default::default() } ], ..Default::default() }; let action = Action { kind: ActionKind::Turn, user_id: id, ..Default::default() }; let result = actions::apply(action, game).unwrap(); game = result.game; assert_eq!(game.user_data[0].team, 2); assert_eq!(game.user_data[0].funds, 321); assert_eq!(game.user_data[0].turn, false); assert_eq!(game.user_data[1].team, 1); assert_eq!(game.user_data[1].funds, 12723); assert_eq!(game.user_data[1].turn, true); assert_eq!(game.turn_user_id, id); } #[test] pub fn repairs_resupplies_units() { let id = Uuid::new_v4(); let mech = units::mech(); let mut game = Game { active: true, map_settings: MapSettings { funds_per_turn: 1000, ..Default::default() }, tile_data: vec![ TileData { coord: Coord {x: 0, y: 0}, tile_id: TileKind::City, team: Some(1), user_id: Some(id), ..Default::default() }, TileData { coord: Coord {x: 0, y: 1}, tile_id: TileKind::City, team: Some(1), user_id: Some(id), ..Default::default() }, TileData { coord: Coord {x: 0, y: 2}, tile_id: TileKind::City, team: Some(1), user_id: Some(id), ..Default::default() }, TileData { coord: Coord {x: 0, y: 3}, tile_id: TileKind::City, team: None, ..Default::default() }, ], unit_data: vec![ UnitData { coord: Coord {x: 0, y: 0}, unit_id: mech.id, fuel: 0, cost: 1000, state: UnitState::Ready, health: 81, team: 1, user_id: id, ..Default::default() }, UnitData { coord: Coord {x: 0, y: 1}, unit_id: mech.id, fuel: 0, cost: 1000, state: UnitState::Exhausted, health: 1, team: 1, user_id: id, ..Default::default() }, UnitData { coord: Coord {x: 0, y: 2}, unit_id: mech.id, fuel: 0, cost: 1000, state: UnitState::Exhausted, health: 1, team: 2, ..Default::default() }, UnitData { coord: Coord {x: 0, y: 3}, unit_id: mech.id, fuel: 0, cost: 1000, state: UnitState::Stunned, health: 1, team: 1, user_id: id, ..Default::default() }, ], user_data: vec![ UserData { active: true, turn: false, user_id: id, funds: 1000, team: 1, position: 0, ..Default::default() }, UserData { active: true, turn: true, team: 2, position: 1, ..Default::default() } ], boundary: Boundary { unit_cache: hashmap![ mech.id => mech ], commander_cache: hashmap![] }, ..Default::default() }; let action = Action { kind: ActionKind::Turn, user_id: id, ..Default::default() }; let result = actions::apply(action, game).unwrap(); game = result.game; assert_eq!(game.unit_data[0].fuel, 70); assert_eq!(game.unit_data[0].health, 100); assert_eq!(game.unit_data[0].state, UnitState::Ready); assert_eq!(game.unit_data[1].fuel, 70); assert_eq!(game.unit_data[1].health, 21); assert_eq!(game.unit_data[1].state, UnitState::Ready); assert_eq!(game.unit_data[2].fuel, 0); assert_eq!(game.unit_data[2].health, 1); assert_eq!(game.unit_data[2].state, UnitState::Exhausted); assert_eq!(game.unit_data[3].fuel, 0); assert_eq!(game.unit_data[3].health, 1); assert_eq!(game.unit_data[3].state, UnitState::Exhausted); assert_eq!(game.user_data[0].team, 2); assert_eq!(game.user_data[0].turn, false); assert_eq!(game.user_data[1].team, 1); // todo: reduce funds per repairs assert_eq!(game.user_data[1].funds, 4000); assert_eq!(game.user_data[1].turn, true); assert_eq!(game.turn_user_id, id); } // test "create_action/1 kind: turn" { // user = insert(:user) // commander = insert(:commander) // user_data = build(:user_data, %{ // turn: true, // user_id: user.id, // commander_id: commander.id, // position: 2 // }) // turn_user = insert(:user) // game = insert(:game, %{ // map_settings: build(:map_settings, %{ // starting_weather: "Clear", // }), // weather: "Snow", // tile_data: [], // unit_data: [], // user_data: [ // build(:user_data, %{turn: false, position: 1, commander_id: commander.id, user_id: insert(:user).id}), // user_data, // build(:user_data, %{turn: false, active: false, position: 3, commander_id: commander.id, user_id: insert(:user).id}), // build(:user_data, %{turn: false, position: 4, commander_id: commander.id, user_id: turn_user.id}) // ] // }) // insert(:game_user, %{game: game, faction: 1}) // insert(:game_user, %{game: game, faction: 2}) // action = build(:action, %{ // kind: "turn", // user_id: user.id, // game_id: game.id // }) // |> Map.from_struct() // assert [] = Engine.list_actions() // assert {:ok, Action { // game: Game { // active: true, // turn_user_id: turn_user_id, // user_data: [ // UserData {turn: false, position: 3, active: false}, // UserData {turn: true, position: 4, active: true}, // UserData {turn: false, position: 2, active: true}, // UserData {turn: false, position: 1, active: true} // ] // } // } = action} = Engine.create_action(action) // assert turn_user_id == turn_user.id // assert [ // Action {kind: "turn", turn: 1, round: 1}, // Action {kind: "weather", turn: 3, round: 1} // ] = Engine.list_actions() // assert_delivered_email WebWarsNotify.Mailers.Turn.email(action) // } // test "create_action/1 kind: turn, weather transitions" { // user_1 = insert(:user) // user_2 = insert(:user) // user_3 = insert(:user) // user_4 = insert(:user) // map = insert(:map, %{ // tile_data: [ // build(:tile_data, %{team: 1, faction: 1, tile_id: Tile.City.id()}), // build(:tile_data, %{team: 2, faction: 2, tile_id: Tile.Base.id()}), // build(:tile_data, %{team: 3, faction: 3, tile_id: Tile.Port.id()}), // build(:tile_data, %{team: 3, faction: 3, tile_id: Tile.Airport.id()}) // ], // }) // game = insert(:game, %{ // active: false, // tile_data: [], // unit_data: [], // user_data: [], // map: map, // map_settings: build(:map_settings, %{ // starting_weather: "Clear", // starting_funds: 500, // funds_per_turn: 1000 // }) // }) // insert(:game_user, %{user: user_1, game: game, faction: 1, team: 1, position: 0}) // insert(:game_user, %{user: user_2, game: game, faction: 2, team: 2, position: 1}) // insert(:game_user, %{user: user_3, game: game, faction: 3, team: 3, position: 2}) // insert(:game_user, %{user: user_4, game: game, faction: 4, team: 4, position: 3}) // assert {:ok, Action { // turn: 1, round: 1, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 1, funds: 1_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 500}, // UserData {turn: false, faction: 2, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "game_start", // user_id: user_1.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 1, round: 1, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 2, funds: 1_500}, // UserData {turn: false, faction: 1, funds: 1_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_1.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 2, round: 1, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 3, funds: 2_500}, // UserData {turn: false, faction: 2, funds: 1_500}, // UserData {turn: false, faction: 1, funds: 1_500}, // UserData {turn: false, faction: 4, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_2.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 3, round: 1, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 3, funds: 2_500}, // UserData {turn: false, faction: 2, funds: 1_500}, // UserData {turn: false, faction: 1, funds: 1_500}, // UserData {turn: false, faction: 4, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "weather", // params: ["Rain", "2"], // user_id: user_3.id, // game_id: game.id, // system: true // }) // assert {:ok, Action { // turn: 3, round: 1, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 2_500}, // UserData {turn: false, faction: 2, funds: 1_500}, // UserData {turn: false, faction: 1, funds: 1_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_3.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 4, round: 1, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 1, funds: 2_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 2_500}, // UserData {turn: false, faction: 2, funds: 1_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_4.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 5, round: 2, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 2, funds: 2_500}, // UserData {turn: false, faction: 1, funds: 2_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 2_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_1.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 6, round: 2, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 3, funds: 4_500}, // UserData {turn: false, faction: 2, funds: 2_500}, // UserData {turn: false, faction: 1, funds: 2_500}, // UserData {turn: false, faction: 4, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_2.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 7, round: 2, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 4_500}, // UserData {turn: false, faction: 2, funds: 2_500}, // UserData {turn: false, faction: 1, funds: 2_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_3.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 8, round: 2, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: true, faction: 1, funds: 3_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 4_500}, // UserData {turn: false, faction: 2, funds: 2_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_4.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 9, round: 3, // game: Game { // weather: "Rain", // user_data: [ // UserData {turn: false, faction: 1, funds: 3_500, active: false}, // UserData {turn: true, faction: 2, funds: 3_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 4_500} // ] // } // }} = Engine.create_action(%{ // kind: "resign", // user_id: user_1.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 10, round: 3, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 3, funds: 6_500}, // UserData {turn: false, faction: 2, funds: 3_500}, // UserData {turn: false, faction: 1, funds: 3_500}, // UserData {turn: false, faction: 4, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_2.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 11, round: 3, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 6_500}, // UserData {turn: false, faction: 2, funds: 3_500}, // UserData {turn: false, faction: 1, funds: 3_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_3.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 12, round: 3, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: false, faction: 1, funds: 3_500}, // UserData {turn: true, faction: 2, funds: 4_500}, // UserData {turn: false, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 6_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_4.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 14, round: 4, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 3, funds: 8_500}, // UserData {turn: false, faction: 2, funds: 4_500}, // UserData {turn: false, faction: 1, funds: 3_500}, // UserData {turn: false, faction: 4, funds: 500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_2.id, // game_id: game.id // }) // assert {:ok, Action { // turn: 15, round: 4, // game: Game { // weather: "Clear", // user_data: [ // UserData {turn: true, faction: 4, funds: 500}, // UserData {turn: false, faction: 3, funds: 8_500}, // UserData {turn: false, faction: 2, funds: 4_500}, // UserData {turn: false, faction: 1, funds: 3_500} // ] // } // }} = Engine.create_action(%{ // kind: "turn", // user_id: user_3.id, // game_id: game.id // }) // }