diff --git a/.tool-versions b/.tool-versions index 75cda2c6..cd71bda4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -starknet-foundry 0.31.0 +starknet-foundry 0.34.0 scarb 2.8.4 \ No newline at end of file diff --git a/onchain/src/contracts/lyricsflip.cairo b/onchain/src/contracts/lyricsflip.cairo index 09d116b4..f8093327 100644 --- a/onchain/src/contracts/lyricsflip.cairo +++ b/onchain/src/contracts/lyricsflip.cairo @@ -47,6 +47,8 @@ pub mod LyricsFlip { >, // round_id -> player_index -> player_address round_players_count: Map, round_cards: Map>, // round_id -> vec + round_ready_players: Map>, // round_id -> player_address -> is_ready + round_ready_count: Map, #[substorage(v0)] ownable: OwnableComponent::Storage, #[substorage(v0)] @@ -63,6 +65,7 @@ pub mod LyricsFlip { RoundStarted: RoundStarted, RoundJoined: RoundJoined, SetCardPerRound: SetCardPerRound, + PlayerReady: PlayerReady, #[flat] OwnableEvent: OwnableComponent::Event, #[flat] @@ -105,6 +108,15 @@ pub mod LyricsFlip { pub new_value: u8, } + #[derive(Drop, starknet::Event)] + pub struct PlayerReady { + #[key] + pub round_id: u64, + #[key] + pub player: ContractAddress, + pub ready_time: u64, + } + const ADMIN_ROLE: felt252 = selector!("ADMIN_ROLE"); #[constructor] @@ -197,16 +209,43 @@ pub mod LyricsFlip { let caller_address = get_caller_address(); let round = self.rounds.entry(round_id); - //TODO: check if caller is an admin or round participant - assert(round.admin.read() == caller_address, Errors::NOT_ROUND_ADMIN); + //check if caller is a participant + assert(self._is_round_player(round_id, caller_address), Errors::NOT_A_PARTICIPANT); - let start_time = get_block_timestamp(); - round.start_time.write(start_time); - round.is_started.write(true); - - //TODO: call the next_card function to get the first QuestionCard + //check if round hasn't started + assert(!round.is_started.read(), Errors::ROUND_ALREADY_STARTED); - self + //check if caller has already signaled readiness + let is_ready = self.round_ready_players.entry(round_id).entry(caller_address).read(); + assert(!is_ready, Errors::ALREADY_READY); + + // mark player as ready + self.round_ready_players.entry(round_id).entry(caller_address).write(true); + + // update ready players count + let ready_count = self.round_ready_count.entry(round_id).read() + 1; + self.round_ready_count.entry(round_id).write(ready_count); + + + // Emit player ready event + self.emit( + Event::PlayerReady( + PlayerReady { + round_id, + player: caller_address, + ready_time: get_block_timestamp(), + } + ) + ); + + // check if all players are ready and start round + let total_players = self.round_players_count.entry(round_id).read(); + if ready_count == total_players { + let start_time = get_block_timestamp(); + round.start_time.write(start_time); + round.is_started.write(true); + + self .emit( Event::RoundStarted( RoundStarted { @@ -214,6 +253,13 @@ pub mod LyricsFlip { }, ), ); + + } + + + + //TODO: call the next_card function to get the first QuestionCard + } fn join_round(ref self: ContractState, round_id: u64) { diff --git a/onchain/src/utils/errors.cairo b/onchain/src/utils/errors.cairo index d6f27be8..54711ed5 100644 --- a/onchain/src/utils/errors.cairo +++ b/onchain/src/utils/errors.cairo @@ -9,4 +9,6 @@ pub mod Errors { pub const EMPTY_YEAR_CARDS: felt252 = 'Year cards is zero'; pub const ROUND_NOT_STARTED: felt252 = 'Round not started'; pub const ROUND_COMPLETED: felt252 = 'Round already completed'; + pub const NOT_A_PARTICIPANT: felt252 = 'Not a participant'; + pub const ALREADY_READY: felt252 = 'Already signalled ready'; }