Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: self attack #111

Open
wants to merge 1 commit into
base: tickNew
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 42 additions & 21 deletions src/api/attack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ async fn init_attack(
pool: web::Data<PgPool>,
redis_pool: Data<RedisPool>,
user: AuthUser,
is_self: web::Query<HashMap<String, bool>>,
) -> Result<impl Responder> {
let attacker_id = user.0;

let is_self_attack = *is_self.get("is_self").unwrap_or(&false);
log::info!("Attacker:{} is trying to initiate an attack", attacker_id);
let mut conn = pool.get().map_err(|err| error::handle_error(err.into()))?;
if let Ok(check) = util::can_attack_happen(&mut conn, attacker_id, true) {
Expand All @@ -71,22 +72,27 @@ async fn init_attack(
.get()
.map_err(|err| error::handle_error(err.into()))?;

let random_opponent_id = web::block(move || {
Ok(util::get_random_opponent_id(
attacker_id,
&mut conn,
redis_conn,
)?) as anyhow::Result<Option<i32>>
})
.await?
.map_err(|err| error::handle_error(err.into()))?;

let opponent_id = if let Some(id) = random_opponent_id {
id
let opponent_id: i32;
if is_self_attack {
opponent_id = attacker_id;
} else {
log::info!("No opponent found for Attacker:{}", attacker_id);
return Err(ErrorBadRequest("No opponent found"));
};
let random_opponent_id = web::block(move || {
Ok(util::get_random_opponent_id(
attacker_id,
&mut conn,
redis_conn,
)?) as anyhow::Result<Option<i32>>
})
.await?
.map_err(|err| error::handle_error(err.into()))?;

opponent_id = if let Some(id) = random_opponent_id {
id
} else {
log::info!("No opponent found for Attacker:{}", attacker_id);
return Err(ErrorBadRequest("No opponent found"));
};
}

log::info!(
"Opponent:{} found for Attacker:{}",
Expand Down Expand Up @@ -136,10 +142,10 @@ async fn init_attack(

log::info!("User details fetched for Opponent:{}", opponent_id);

//Create game
//Create a new game
let mut conn = pool.get().map_err(|err| error::handle_error(err.into()))?;
let game_id = web::block(move || {
Ok(util::add_game(attacker_id, opponent_id, map_id, &mut conn)?) as anyhow::Result<i32>
Ok(util::add_game(attacker_id, opponent_id, map_id, &mut conn, is_self_attack)?) as anyhow::Result<i32>
})
.await?
.map_err(|err| error::handle_error(err.into()))?;
Expand Down Expand Up @@ -199,6 +205,12 @@ async fn socket_handler(
let query_params = req.query_string().split('&').collect::<Vec<&str>>();
let user_token = query_params[0].split('=').collect::<Vec<&str>>()[1];
let attack_token = query_params[1].split('=').collect::<Vec<&str>>()[1];
let is_self_attack = query_params[2]
.split('=')
.collect::<Vec<&str>>()
.get(1)
.map(|&s| s == "true")
.unwrap_or(false);

let attacker_id =
util::decode_user_token(user_token).map_err(|err| error::handle_error(err.into()))?;
Expand All @@ -224,9 +236,16 @@ async fn socket_handler(
}

let defender_id = attack_token_data.defender_id;
if attacker_id == defender_id {
log::info!("Attacker:{} is trying to attack himself", attacker_id);
return Err(ErrorBadRequest("Can't attack yourself"));
if !is_self_attack {
if attacker_id == defender_id {
log::info!("Attacker:{} is trying to attack himself", attacker_id);
return Err(ErrorBadRequest("Can't attack yourself"));
}
} else {
if attacker_id != defender_id {
log::info!("Attacker:{} is trying to attack someone else", attacker_id);
return Err(ErrorBadRequest("Can't attack someone else"));
}
}

let mut redis_conn = redis_pool
Expand Down Expand Up @@ -487,6 +506,7 @@ async fn socket_handler(
&mut conn,
&damaged_base_items.buildings_damaged,
&mut redis_conn,
is_self_attack,
)
.is_err()
{
Expand Down Expand Up @@ -586,6 +606,7 @@ async fn socket_handler(
&mut conn,
&damaged_base_items.buildings_damaged,
&mut redis_conn,
is_self_attack,
)
.is_err()
{
Expand Down
223 changes: 114 additions & 109 deletions src/api/attack/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub fn add_game(
defender_id: i32,
map_layout_id: i32,
conn: &mut PgConnection,
is_self_attack: bool,
) -> Result<i32> {
use crate::schema::game;

Expand All @@ -160,17 +161,20 @@ pub fn add_game(
is_game_over: &false,
date: &chrono::Local::now().date_naive(),
};

let inserted_game: Game = diesel::insert_into(game::table)
let inserted_game: Game;
if !is_self_attack {
inserted_game = diesel::insert_into(game::table)
.values(&new_game)
.get_result(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

Ok(inserted_game.id)
Ok(inserted_game.id)
} else {
Ok(-1)
}
}

pub fn fetch_attack_history(
Expand Down Expand Up @@ -825,28 +829,29 @@ pub fn terminate_game(
conn: &mut PgConnection,
damaged_buildings: &[BuildingDamageResponse],
redis_conn: &mut RedisConn,
is_self_attack: bool,
) -> Result<()> {
use crate::schema::{artifact, game};
let attacker_id = game_log.a.id;
let defender_id = game_log.d.id;
let damage_done = game_log.r.d;
let bombs_used = game_log.r.b;
let artifacts_collected = game_log.r.a;
let game_id = game_log.g;
log::info!(
"Terminating game for game:{} and attacker:{} and opponent:{}",
game_id,
attacker_id,
defender_id
);

let (attack_score, defense_score) = if damage_done < WIN_THRESHOLD {
(damage_done - 100, 100 - damage_done)
} else {
(damage_done, -damage_done)
};
if !is_self_attack {
use crate::schema::{artifact, game};
let damage_done = game_log.r.d;
let bombs_used = game_log.r.b;
let artifacts_collected = game_log.r.a;
log::info!(
"Terminating game for game:{} and attacker:{} and opponent:{}",
game_id,
attacker_id,
defender_id
);

let attacker_details = user::table
let (attack_score, defense_score) = if damage_done < WIN_THRESHOLD {
(damage_done - 100, 100 - damage_done)
} else {
(damage_done, -damage_done)
};
let attacker_details = user::table
.filter(user::id.eq(attacker_id))
.first::<User>(conn)
.map_err(|err| DieselError {
Expand All @@ -855,102 +860,102 @@ pub fn terminate_game(
error: err,
})?;

let defender_details = user::table
.filter(user::id.eq(defender_id))
.first::<User>(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

let attack_score = attack_score as f32 / 100_f32;
let defence_score = defense_score as f32 / 100_f32;
let defender_details = user::table
.filter(user::id.eq(defender_id))
.first::<User>(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

let new_trophies = new_rating(
attacker_details.trophies,
defender_details.trophies,
attack_score,
defence_score,
);
let attack_score = attack_score as f32 / 100_f32;
let defence_score = defense_score as f32 / 100_f32;

//Add bonus trophies (just call the function)

game_log.r.oa = attacker_details.trophies;
game_log.r.od = defender_details.trophies;
game_log.r.na = new_trophies.0;
game_log.r.nd = new_trophies.1;

diesel::update(game::table.find(game_id))
.set((
game::damage_done.eq(damage_done),
game::is_game_over.eq(true),
game::emps_used.eq(bombs_used),
game::attack_score.eq(new_trophies.0 - attacker_details.trophies),
game::defend_score.eq(new_trophies.1 - defender_details.trophies),
game::artifacts_collected.eq(artifacts_collected),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;
let new_trophies = new_rating(
attacker_details.trophies,
defender_details.trophies,
attack_score,
defence_score,
);

let (attacker_wins, defender_wins) = if damage_done < WIN_THRESHOLD {
(0, 1)
} else {
(1, 0)
};
//Add bonus trophies (just call the function)

game_log.r.oa = attacker_details.trophies;
game_log.r.od = defender_details.trophies;
game_log.r.na = new_trophies.0;
game_log.r.nd = new_trophies.1;

diesel::update(game::table.find(game_id))
.set((
game::damage_done.eq(damage_done),
game::is_game_over.eq(true),
game::emps_used.eq(bombs_used),
game::attack_score.eq(new_trophies.0 - attacker_details.trophies),
game::defend_score.eq(new_trophies.1 - defender_details.trophies),
game::artifacts_collected.eq(artifacts_collected),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

diesel::update(user::table.find(&game_log.a.id))
.set((
user::artifacts.eq(user::artifacts + artifacts_collected),
user::trophies.eq(user::trophies + new_trophies.0 - attacker_details.trophies),
user::attacks_won.eq(user::attacks_won + attacker_wins),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;
let (attacker_wins, defender_wins) = if damage_done < WIN_THRESHOLD {
(0, 1)
} else {
(1, 0)
};

if deduct_artifacts_from_building(damaged_buildings.to_vec(), conn).is_err() {
log::info!(
"Failed to deduct artifacts from building for game:{} and attacker:{} and opponent:{}",
game_id,
attacker_id,
defender_id
);
}
diesel::update(user::table.find(&game_log.d.id))
.set((
user::artifacts.eq(user::artifacts - artifacts_collected),
user::trophies.eq(user::trophies + new_trophies.1 - defender_details.trophies),
user::defenses_won.eq(user::defenses_won + defender_wins),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;
diesel::update(user::table.find(&game_log.a.id))
.set((
user::artifacts.eq(user::artifacts + artifacts_collected),
user::trophies.eq(user::trophies + new_trophies.0 - attacker_details.trophies),
user::attacks_won.eq(user::attacks_won + attacker_wins),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

let attacker_map_id = get_user_map_id(attacker_id, conn)?;
let attacker_bank_block_type_id = get_block_id_of_bank(conn, &attacker_id)?;
let attacker_bank_map_space_id =
get_bank_map_space_id(conn, &attacker_map_id, &attacker_bank_block_type_id)?;
if deduct_artifacts_from_building(damaged_buildings.to_vec(), conn).is_err() {
log::info!(
"Failed to deduct artifacts from building for game:{} and attacker:{} and opponent:{}",
game_id,
attacker_id,
defender_id
);
}
diesel::update(user::table.find(&game_log.d.id))
.set((
user::artifacts.eq(user::artifacts - artifacts_collected),
user::trophies.eq(user::trophies + new_trophies.1 - defender_details.trophies),
user::defenses_won.eq(user::defenses_won + defender_wins),
))
.execute(conn)
.map_err(|err| DieselError {
table: "game",
function: function!(),
error: err,
})?;

diesel::update(artifact::table.find(attacker_bank_map_space_id))
.set(artifact::count.eq(artifact::count + artifacts_collected))
.execute(conn)
.map_err(|err| DieselError {
table: "artifact",
function: function!(),
error: err,
})?;
let attacker_map_id = get_user_map_id(attacker_id, conn)?;
let attacker_bank_block_type_id = get_block_id_of_bank(conn, &attacker_id)?;
let attacker_bank_map_space_id =
get_bank_map_space_id(conn, &attacker_map_id, &attacker_bank_block_type_id)?;

diesel::update(artifact::table.find(attacker_bank_map_space_id))
.set(artifact::count.eq(artifact::count + artifacts_collected))
.execute(conn)
.map_err(|err| DieselError {
table: "artifact",
function: function!(),
error: err,
})?;
}
// if let Ok(sim_log) = serde_json::to_string(&game_log) {
// let new_simulation_log = NewSimulationLog {
// game_id: &game_id,
Expand Down