feat: max timeout for move
This commit is contained in:
@@ -11,6 +11,7 @@ pub struct Server {
|
|||||||
pub admin_password: Arc<String>,
|
pub admin_password: Arc<String>,
|
||||||
pub tournament: WrappedTournament,
|
pub tournament: WrappedTournament,
|
||||||
pub waiting_timeout: Arc<RwLock<u64>>,
|
pub waiting_timeout: Arc<RwLock<u64>>,
|
||||||
|
pub max_timeout: Arc<RwLock<u64>>,
|
||||||
pub demo_mode: Arc<RwLock<bool>>,
|
pub demo_mode: Arc<RwLock<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ impl Server {
|
|||||||
admin_password: Arc::new(admin_password),
|
admin_password: Arc::new(admin_password),
|
||||||
tournament: Arc::new(RwLock::new(None)),
|
tournament: Arc::new(RwLock::new(None)),
|
||||||
waiting_timeout: Arc::new(RwLock::new(5000)),
|
waiting_timeout: Arc::new(RwLock::new(5000)),
|
||||||
|
max_timeout: Arc::new(RwLock::new(30000)),
|
||||||
demo_mode: Arc::new(RwLock::new(demo_mode)),
|
demo_mode: Arc::new(RwLock::new(demo_mode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +127,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clients_guard.get(&addr).unwrap().read().await.ready {
|
if clients_guard.get(&addr).unwrap().read().await.ready {
|
||||||
return Err(anyhow::anyhow!("ERROR:INVALID"));
|
return Err(anyhow::anyhow!("ERROR:INVALID:READY"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut client = clients_guard.get(&addr).unwrap().write().await;
|
let mut client = clients_guard.get(&addr).unwrap().write().await;
|
||||||
@@ -263,8 +265,12 @@ impl Server {
|
|||||||
self.matches.write().await.remove(¤t_match_id).unwrap();
|
self.matches.write().await.remove(¤t_match_id).unwrap();
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
}
|
||||||
|
|
||||||
current_match.place_token(client.color.clone(), column);
|
current_match.place_token(client.color.clone(), column);
|
||||||
|
|
||||||
|
if let Some(timeout_thread) = ¤t_match.timeout_thread {
|
||||||
|
timeout_thread.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut viewer_messages = Vec::new();
|
let mut viewer_messages = Vec::new();
|
||||||
@@ -357,19 +363,21 @@ impl Server {
|
|||||||
let demo_move = random_move(¤t_match.board);
|
let demo_move = random_move(¤t_match.board);
|
||||||
let no_winner = winner == Color::None && !filled;
|
let no_winner = winner == Color::None && !filled;
|
||||||
let observers = self.observers.clone();
|
let observers = self.observers.clone();
|
||||||
|
let opp_connection_move = opponent_connection.clone();
|
||||||
|
let client_tx = tx.clone();
|
||||||
if current_match.demo_mode {
|
if current_match.demo_mode {
|
||||||
current_match.ledger.push((!client.color, demo_move, Instant::now()));
|
current_match.ledger.push((!client.color, demo_move, Instant::now()));
|
||||||
current_match.place_token(!client.color, demo_move);
|
current_match.place_token(!client.color, demo_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
let opp_connection_move = opponent_connection.clone();
|
|
||||||
|
|
||||||
current_match.wait_thread = Some(tokio::spawn(async move {
|
current_match.wait_thread = Some(tokio::spawn(async move {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_millis(adjusted_waiting as u64)).await;
|
tokio::time::sleep(tokio::time::Duration::from_millis(adjusted_waiting as u64)).await;
|
||||||
|
|
||||||
if !demo_mode && no_winner {
|
if !demo_mode && no_winner {
|
||||||
let _ = send(&opp_connection_move.as_ref().unwrap(), &format!("OPPONENT:{}", column));
|
let _ = send(
|
||||||
|
&opp_connection_move.as_ref().unwrap(),
|
||||||
|
&format!("OPPONENT:{}", column),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for msg in viewer_messages {
|
for msg in viewer_messages {
|
||||||
@@ -378,7 +386,7 @@ impl Server {
|
|||||||
|
|
||||||
if demo_mode && no_winner {
|
if demo_mode && no_winner {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_millis(default_waiting_time)).await;
|
tokio::time::sleep(tokio::time::Duration::from_millis(default_waiting_time)).await;
|
||||||
let _ = send(&tx, &format!("OPPONENT:{}", demo_move));
|
let _ = send(&client_tx, &format!("OPPONENT:{}", demo_move));
|
||||||
broadcast_message(
|
broadcast_message(
|
||||||
&observers,
|
&observers,
|
||||||
&viewers,
|
&viewers,
|
||||||
@@ -388,6 +396,60 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let max_timeout = *self.max_timeout.read().await;
|
||||||
|
let matches = self.matches.clone();
|
||||||
|
let tournament = self.tournament.clone();
|
||||||
|
let clients = self.clients.clone();
|
||||||
|
let match_id = current_match.id;
|
||||||
|
let ledger_size = current_match.ledger.len();
|
||||||
|
let client_username = client.username.clone();
|
||||||
|
let client_tx = tx.clone();
|
||||||
|
let client_addr = addr.clone();
|
||||||
|
let observers = self.observers.clone();
|
||||||
|
let viewers = current_match.viewers.clone();
|
||||||
|
current_match.timeout_thread = Some(tokio::spawn(async move {
|
||||||
|
if demo_mode {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_millis(adjusted_waiting as u64)).await;
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_millis(max_timeout as u64)).await;
|
||||||
|
|
||||||
|
let matches_guard = matches.read().await;
|
||||||
|
let the_match = matches_guard.get(&match_id);
|
||||||
|
if let Some(the_match) = the_match {
|
||||||
|
let the_match = the_match.read().await;
|
||||||
|
if the_match.ledger.len() == ledger_size {
|
||||||
|
// forfeit the match
|
||||||
|
let _ = send(&client_tx, "GAME:WINS");
|
||||||
|
let _ = send(&opponent_connection.unwrap(), "GAME:LOSS");
|
||||||
|
broadcast_message(
|
||||||
|
&observers,
|
||||||
|
&viewers,
|
||||||
|
&format!("GAME:WIN:{}", client_username),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let mut clients_guard = clients.write().await;
|
||||||
|
let mut client = clients_guard.get_mut(&client_addr).unwrap().write().await;
|
||||||
|
client.current_match = None;
|
||||||
|
client.color = Color::None;
|
||||||
|
drop(client);
|
||||||
|
|
||||||
|
let mut opponent = clients_guard.get_mut(&opponent_addr).unwrap().write().await;
|
||||||
|
opponent.current_match = None;
|
||||||
|
opponent.color = Color::None;
|
||||||
|
drop(opponent);
|
||||||
|
|
||||||
|
let mut tournament_guard = tournament.write().await;
|
||||||
|
let tourney = tournament_guard.as_mut().unwrap();
|
||||||
|
tourney.write().await.inform_winnder(client_addr, false);
|
||||||
|
drop(tournament_guard);
|
||||||
|
|
||||||
|
matches.write().await.remove(&match_id).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,6 +712,10 @@ impl Server {
|
|||||||
let demo_mode = *self.demo_mode.read().await;
|
let demo_mode = *self.demo_mode.read().await;
|
||||||
msg += demo_mode.to_string().as_str();
|
msg += demo_mode.to_string().as_str();
|
||||||
}
|
}
|
||||||
|
"MAX_TIMEOUT" => {
|
||||||
|
let max_time = *self.max_timeout.read().await as f64 / 1000f64;
|
||||||
|
msg += max_time.to_string().as_str();
|
||||||
|
}
|
||||||
&_ => return Err(anyhow::anyhow!("ERROR:INVALID:GET")),
|
&_ => return Err(anyhow::anyhow!("ERROR:INVALID:GET")),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,6 +749,13 @@ impl Server {
|
|||||||
}
|
}
|
||||||
*self.waiting_timeout.write().await = (wait_time.unwrap() * 1000.0) as u64;
|
*self.waiting_timeout.write().await = (wait_time.unwrap() * 1000.0) as u64;
|
||||||
}
|
}
|
||||||
|
"MAX_TIMEOUT" => {
|
||||||
|
let max_time = data_value.parse::<f64>();
|
||||||
|
if max_time.is_err() {
|
||||||
|
return Err(anyhow::anyhow!("ERROR:INVALID:SET"));
|
||||||
|
}
|
||||||
|
*self.max_timeout.write().await = (max_time.unwrap() * 1000.0) as u64;
|
||||||
|
}
|
||||||
&_ => return Err(anyhow::anyhow!("ERROR:INVALID:SET")),
|
&_ => return Err(anyhow::anyhow!("ERROR:INVALID:SET")),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,8 +822,12 @@ impl Server {
|
|||||||
}
|
}
|
||||||
let the_match = the_match.unwrap().read().await;
|
let the_match = the_match.unwrap().read().await;
|
||||||
|
|
||||||
if the_match.wait_thread.is_some() {
|
if let Some(wait_thread) = &the_match.wait_thread {
|
||||||
the_match.wait_thread.as_ref().unwrap().abort();
|
wait_thread.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(timeout_thread) = &the_match.timeout_thread {
|
||||||
|
timeout_thread.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.broadcast_message(&the_match.viewers, "GAME:TERMINATED").await;
|
self.broadcast_message(&the_match.viewers, "GAME:TERMINATED").await;
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ impl Tournament for RoundRobin {
|
|||||||
// Send scores
|
// Send scores
|
||||||
let clients_guard = server.clients.read().await;
|
let clients_guard = server.clients.read().await;
|
||||||
for (_, player_addr) in self.players.iter() {
|
for (_, player_addr) in self.players.iter() {
|
||||||
let mut player = clients_guard.get(&player_addr.0).unwrap().write().await;
|
let player = clients_guard.get(&player_addr.0).unwrap().read().await;
|
||||||
let _ = send(&player.connection.clone(), "TOURNAMENT:END");
|
let _ = send(&player.connection.clone(), "TOURNAMENT:END");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ pub struct Match {
|
|||||||
pub viewers: Vec<SocketAddr>,
|
pub viewers: Vec<SocketAddr>,
|
||||||
pub ledger: Vec<(Color, usize, Instant)>,
|
pub ledger: Vec<(Color, usize, Instant)>,
|
||||||
pub wait_thread: Option<tokio::task::JoinHandle<()>>,
|
pub wait_thread: Option<tokio::task::JoinHandle<()>>,
|
||||||
|
pub timeout_thread: Option<tokio::task::JoinHandle<()>>,
|
||||||
pub player1: SocketAddr,
|
pub player1: SocketAddr,
|
||||||
pub player2: SocketAddr,
|
pub player2: SocketAddr,
|
||||||
}
|
}
|
||||||
@@ -73,6 +74,7 @@ impl Match {
|
|||||||
viewers: Vec::new(),
|
viewers: Vec::new(),
|
||||||
ledger: Vec::new(),
|
ledger: Vec::new(),
|
||||||
wait_thread: None,
|
wait_thread: None,
|
||||||
|
timeout_thread: None,
|
||||||
player1: if player1 == first { player1 } else { player2 },
|
player1: if player1 == first { player1 } else { player2 },
|
||||||
player2: if player1 == first { player2 } else { player1 },
|
player2: if player1 == first { player2 } else { player1 },
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user