Merge branch 'develop' into face-imgs
This commit is contained in:
@@ -20,7 +20,7 @@ use img;
|
||||
use failure::Error;
|
||||
use failure::{err_msg, format_err};
|
||||
|
||||
static PASSWORD_MIN_LEN: usize = 11;
|
||||
static PASSWORD_MIN_LEN: usize = 3;
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct Account {
|
||||
@@ -189,7 +189,7 @@ pub fn new_img(tx: &mut Transaction, id: Uuid) -> Result<Account, Error> {
|
||||
}
|
||||
|
||||
pub fn set_password(tx: &mut Transaction, id: Uuid, current: &String, password: &String) -> Result<String, MnmlHttpError> {
|
||||
if password.len() < PASSWORD_MIN_LEN {
|
||||
if password.len() < PASSWORD_MIN_LEN || password.len() > 100 {
|
||||
return Err(MnmlHttpError::PasswordUnacceptable);
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ pub fn set_subscribed(tx: &mut Transaction, id: Uuid, subscribed: bool) -> Resul
|
||||
}
|
||||
|
||||
pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result<String, MnmlHttpError> {
|
||||
if password.len() < PASSWORD_MIN_LEN {
|
||||
if password.len() < PASSWORD_MIN_LEN || password.len() > 100 {
|
||||
return Err(MnmlHttpError::PasswordUnacceptable);
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ pub fn create(name: &String, password: &String, tx: &mut Transaction) -> Result<
|
||||
|
||||
let id = Uuid::new_v4();
|
||||
let img = Uuid::new_v4();
|
||||
let rounds = 8;
|
||||
let rounds = 12;
|
||||
let password = hash(&password, rounds)?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
+44
-8
@@ -27,7 +27,7 @@ pub enum Phase {
|
||||
Start,
|
||||
Skill,
|
||||
Resolve,
|
||||
Finish,
|
||||
Finished,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
@@ -325,6 +325,30 @@ impl Game {
|
||||
return Ok(self);
|
||||
}
|
||||
|
||||
fn offer_draw(mut self, player_id: Uuid) -> Result<Game, Error> {
|
||||
if self.phase != Phase::Skill {
|
||||
return Err(err_msg("game not in skill phase"));
|
||||
}
|
||||
|
||||
{
|
||||
let player = self.player_by_id(player_id)?;
|
||||
player.draw_offered = true;
|
||||
}
|
||||
|
||||
// bots automatically accept draws
|
||||
for player in self.players.iter_mut() {
|
||||
if player.bot {
|
||||
player.draw_offered = true;
|
||||
}
|
||||
}
|
||||
|
||||
if self.players.iter().all(|p| p.draw_offered) {
|
||||
return Ok(self.finish());
|
||||
}
|
||||
|
||||
return Ok(self);
|
||||
}
|
||||
|
||||
fn clear_skill(&mut self, player_id: Uuid) -> Result<&mut Game, Error> {
|
||||
self.player_by_id(player_id)?;
|
||||
if self.phase != Phase::Skill {
|
||||
@@ -564,15 +588,18 @@ impl Game {
|
||||
// }
|
||||
|
||||
pub fn finished(&self) -> bool {
|
||||
self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko()))
|
||||
self.phase == Phase::Finished || self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko()))
|
||||
}
|
||||
|
||||
pub fn winner(&self) -> Option<&Player> {
|
||||
self.players.iter().find(|t| t.constructs.iter().any(|c| !c.is_ko()))
|
||||
match self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko())) {
|
||||
true => self.players.iter().find(|t| t.constructs.iter().any(|c| !c.is_ko())),
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(mut self) -> Game {
|
||||
self.phase = Phase::Finish;
|
||||
self.phase = Phase::Finished;
|
||||
// self.log.push(format!("Game finished."));
|
||||
|
||||
// {
|
||||
@@ -594,7 +621,7 @@ impl Game {
|
||||
}
|
||||
|
||||
pub fn upkeep(mut self) -> Game {
|
||||
if self.phase == Phase::Finish {
|
||||
if self.phase == Phase::Finished {
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -903,6 +930,15 @@ pub fn game_skill(tx: &mut Transaction, account: &Account, game_id: Uuid, constr
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
pub fn game_offer_draw(tx: &mut Transaction, account: &Account, game_id: Uuid) -> Result<Game, Error> {
|
||||
let game = game_get(tx, game_id)?
|
||||
.offer_draw(account.id)?;
|
||||
|
||||
game_update(tx, &game)?;
|
||||
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
pub fn game_skill_clear(tx: &mut Transaction, account: &Account, game_id: Uuid) -> Result<Game, Error> {
|
||||
let mut game = game_get(tx, game_id)?;
|
||||
|
||||
@@ -1051,7 +1087,7 @@ mod tests {
|
||||
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
||||
assert!([Phase::Skill, Phase::Finished].contains(&game.phase));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1117,7 +1153,7 @@ mod tests {
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
assert!(!game.player_by_id(y_player.id).unwrap().constructs[0].is_stunned());
|
||||
assert!(game.phase == Phase::Finish);
|
||||
assert!(game.phase == Phase::Finished);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1423,7 +1459,7 @@ mod tests {
|
||||
assert!(game.skill_phase_finished());
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
||||
assert!([Phase::Skill, Phase::Finished].contains(&game.phase));
|
||||
|
||||
// kill a construct
|
||||
game.player_by_id(i_player.id).unwrap().construct_by_id(i_construct.id).unwrap().green_life.reduce(u64::max_value());
|
||||
|
||||
+21
-49
@@ -317,7 +317,13 @@ impl Instance {
|
||||
self.phase_start = Utc::now();
|
||||
self.phase_end = self.time_control.vbox_phase_end();
|
||||
|
||||
let bits = match self.rounds.len() > 0 {
|
||||
true => 12 + 6 * self.rounds.len(),
|
||||
false => 0,
|
||||
};
|
||||
|
||||
self.players.iter_mut().for_each(|p| {
|
||||
p.vbox.balance_add(bits.into());
|
||||
p.set_ready(false);
|
||||
p.vbox.fill();
|
||||
});
|
||||
@@ -329,28 +335,18 @@ impl Instance {
|
||||
}
|
||||
|
||||
fn finish_condition(&mut self) -> bool {
|
||||
// tennis
|
||||
for player in self.players.iter() {
|
||||
if player.score == Score::Win {
|
||||
self.winner = Some(player.id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Game defaults to lose otherwise
|
||||
if self.rounds.len() < 4 {
|
||||
return false;
|
||||
}
|
||||
|
||||
// both players afk
|
||||
if self.players.iter().all(|p| p.score == Score::Zero) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
self.players.iter().any(|p| p.score == Score::Win)
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) -> &mut Instance {
|
||||
self.phase = InstancePhase::Finished;
|
||||
|
||||
for player in self.players.iter() {
|
||||
if player.score == Score::Win {
|
||||
self.winner = Some(player.id);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@@ -412,38 +408,14 @@ impl Instance {
|
||||
}
|
||||
|
||||
// if you don't win, you lose
|
||||
// ties can happen if both players forfeit
|
||||
// in this case we just finish the game and
|
||||
// dock them 10k mmr
|
||||
let winner_id = match game.winner() {
|
||||
Some(w) => w.id,
|
||||
None => return Ok(self.finish()),
|
||||
};
|
||||
|
||||
let bits = 12 + 6 * self.rounds.len();
|
||||
|
||||
{
|
||||
let loser = self.players.iter()
|
||||
.find(|p| p.id != winner_id)
|
||||
.map(|p| p.score)
|
||||
.unwrap();
|
||||
|
||||
// ties can happen if both players agree to a draw
|
||||
// or ticks fire and knock everybody out
|
||||
if let Some(winner) = game.winner() {
|
||||
let winner = self.players.iter_mut()
|
||||
.find(|p| p.id == winner_id)
|
||||
.find(|p| p.id == winner.id)
|
||||
.unwrap();
|
||||
|
||||
winner.score = winner.score.add_win(&loser);
|
||||
winner.vbox.balance_add(bits.into());
|
||||
}
|
||||
|
||||
{
|
||||
let loser = self.players.iter_mut()
|
||||
.find(|p| p.id != winner_id)
|
||||
.unwrap();
|
||||
|
||||
loser.score = loser.score.add_loss();
|
||||
loser.vbox.balance_add(bits.into());
|
||||
}
|
||||
winner.score = winner.score.add_win(&Score::Zero);
|
||||
};
|
||||
|
||||
if self.all_games_finished() {
|
||||
self.next_round();
|
||||
@@ -799,7 +771,7 @@ pub fn instance_state(tx: &mut Transaction, instance_id: Uuid) -> Result<RpcMess
|
||||
let game = game_get(tx, game_id)?;
|
||||
|
||||
// return the game until it's finished
|
||||
if game.phase != Phase::Finish {
|
||||
if game.phase != Phase::Finished {
|
||||
return Ok(RpcMessage::GameState(game))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ pub struct Player {
|
||||
pub bot: bool,
|
||||
pub ready: bool,
|
||||
pub warnings: u8,
|
||||
pub draw_offered: bool,
|
||||
pub score: Score,
|
||||
}
|
||||
|
||||
@@ -85,6 +86,7 @@ impl Player {
|
||||
bot: false,
|
||||
ready: false,
|
||||
warnings: 0,
|
||||
draw_offered: false,
|
||||
score: Score::Zero,
|
||||
})
|
||||
}
|
||||
@@ -99,6 +101,7 @@ impl Player {
|
||||
bot: false,
|
||||
ready: false,
|
||||
warnings: 0,
|
||||
draw_offered: false,
|
||||
score: Score::Zero,
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -22,7 +22,7 @@ use account::{Account};
|
||||
use account;
|
||||
use construct::{Construct};
|
||||
use events::{Event};
|
||||
use game::{Game, game_state, game_skill, game_skill_clear, game_ready};
|
||||
use game::{Game, game_state, game_skill, game_skill_clear, game_ready, game_offer_draw};
|
||||
use instance::{Instance, ChatState, instance_state, instance_practice, instance_ready, instance_abandon, demo};
|
||||
use item::{Item, ItemInfoCtr, item_info};
|
||||
use mtx;
|
||||
@@ -90,6 +90,7 @@ pub enum RpcRequest {
|
||||
GameReady { id: Uuid },
|
||||
GameSkill { game_id: Uuid, construct_id: Uuid, target_construct_id: Uuid, skill: Skill },
|
||||
GameSkillClear { game_id: Uuid },
|
||||
GameOfferDraw { game_id: Uuid },
|
||||
|
||||
AccountState {},
|
||||
AccountShop {},
|
||||
@@ -218,6 +219,9 @@ impl Connection {
|
||||
RpcRequest::GameReady { id } =>
|
||||
Ok(RpcMessage::GameState(game_ready(&mut tx, account, id)?)),
|
||||
|
||||
RpcRequest::GameOfferDraw { game_id } =>
|
||||
Ok(RpcMessage::GameState(game_offer_draw(&mut tx, account, game_id)?)),
|
||||
|
||||
RpcRequest::InstancePractice {} =>
|
||||
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, account)?)),
|
||||
|
||||
@@ -450,6 +454,7 @@ pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
||||
}
|
||||
// we done
|
||||
Err(_e) => {
|
||||
// info!("{:?}", e);
|
||||
break;
|
||||
},
|
||||
};
|
||||
|
||||
+4
-1
@@ -1264,6 +1264,9 @@ impl Skill {
|
||||
Skill::Invert|
|
||||
Skill::InvertPlus |
|
||||
Skill::InvertPlusPlus |
|
||||
Skill::Intercept|
|
||||
Skill::InterceptPlus |
|
||||
Skill::InterceptPlusPlus |
|
||||
Skill::Counter|
|
||||
Skill::CounterPlus |
|
||||
Skill::CounterPlusPlus |
|
||||
@@ -2083,7 +2086,7 @@ mod tests {
|
||||
|
||||
let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
|
||||
match event {
|
||||
Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier())
|
||||
Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier())
|
||||
+ 220.pct(Skill::SiphonTick.multiplier())),
|
||||
_ => panic!("not damage siphon"),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user