From 71cec256257b9fa864c74164e875188b2cc4dfff Mon Sep 17 00:00:00 2001 From: Gerson2102 Date: Thu, 21 Nov 2024 10:43:40 -0600 Subject: [PATCH 1/4] Adding the model and system tournament blueprint --- src/models/tournament.cairo | 23 +++++++++++++++++++++++ src/systems/tournament.cairo | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/models/tournament.cairo create mode 100644 src/systems/tournament.cairo diff --git a/src/models/tournament.cairo b/src/models/tournament.cairo new file mode 100644 index 0000000..9bfd007 --- /dev/null +++ b/src/models/tournament.cairo @@ -0,0 +1,23 @@ +use super::player::Player; + +#[derive(Serde, Copy, Drop, Introspect, PartialEq)] +pub enum TournamentStatus { + Pending, + Ongoing, + Completed, +} + + +#[derive(Copy, Drop, Serde)] +#[dojo::model] +pub struct Tournament { + #[key] + pub tournament_id: u32, + pub name: felt252, + pub status: TournamentStatus, + pub entry_fee: u32, + pub max_participants: u32, + pub current_participants: Array, + pub prize_pool: u32, +} + diff --git a/src/systems/tournament.cairo b/src/systems/tournament.cairo new file mode 100644 index 0000000..ccfcc4a --- /dev/null +++ b/src/systems/tournament.cairo @@ -0,0 +1,35 @@ +use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; +use bytebeasts::{ + models::{player::Player, tournament::Tournament, tournament::TournamentStatus}, +}; + +#[dojo::interface] +trait ITournamentAction { + fn create_tournament(ref world: IWorldDispatcher, tournament_id: u32, name: felt252, + status: TournamentStatus, + entry_fee: u32, + max_participants: u32, + current_participants: Array, + prize_pool: u32) -> Tournament; + fn register_player(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn complete_torunament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn get_tournament(ref world: IWorldDispatcher, tournament_id: u32) -> Tournament; +} + + +#[dojo::contract] +mod spawn_action { + use super::ITournamentAction; + use bytebeasts::{ + models::{player::Player, tournament::Tournament}, + }; + + #[abi(embed_v0)] + impl TournamentActionImpl of ITournamentAction { + fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament { + let tournament_from_world = get!(world, tournament_id, (Tournament)); + tournament_from_world + } + } +} \ No newline at end of file From 32f38c39871dfad5a337d8afa7976024ae48579d Mon Sep 17 00:00:00 2001 From: Gerson2102 Date: Sat, 23 Nov 2024 16:24:13 -0600 Subject: [PATCH 2/4] Deleting test file from PR --- src/lib.cairo | 3 +++ src/models/tournament.cairo | 2 +- src/systems/tournament.cairo | 48 +++++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/lib.cairo b/src/lib.cairo index 2944835..44d6b37 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -5,6 +5,7 @@ mod systems { mod spawn; mod world_setup; mod bag; + mod tournament; } mod models { @@ -26,9 +27,11 @@ mod models { mod achievement_rarity; mod achievement_type; mod achievements; + mod tournament; } mod tests { mod test_battle; mod test_bag; + mod test_tournament; } diff --git a/src/models/tournament.cairo b/src/models/tournament.cairo index 9bfd007..5feffa2 100644 --- a/src/models/tournament.cairo +++ b/src/models/tournament.cairo @@ -8,7 +8,7 @@ pub enum TournamentStatus { } -#[derive(Copy, Drop, Serde)] +#[derive(Drop, Serde)] #[dojo::model] pub struct Tournament { #[key] diff --git a/src/systems/tournament.cairo b/src/systems/tournament.cairo index ccfcc4a..faf4192 100644 --- a/src/systems/tournament.cairo +++ b/src/systems/tournament.cairo @@ -1,35 +1,59 @@ use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; -use bytebeasts::{ - models::{player::Player, tournament::Tournament, tournament::TournamentStatus}, -}; +use bytebeasts::{models::{player::Player, tournament::Tournament, tournament::TournamentStatus},}; #[dojo::interface] trait ITournamentAction { - fn create_tournament(ref world: IWorldDispatcher, tournament_id: u32, name: felt252, + fn create_tournament( + ref world: IWorldDispatcher, + tournament_id: u32, + name: felt252, status: TournamentStatus, entry_fee: u32, max_participants: u32, current_participants: Array, - prize_pool: u32) -> Tournament; - fn register_player(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); - fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); - fn complete_torunament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); - fn get_tournament(ref world: IWorldDispatcher, tournament_id: u32) -> Tournament; + prize_pool: u32 + ); + // fn register_player(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + // fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + // fn complete_torunament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament; } #[dojo::contract] -mod spawn_action { +mod tournament_system { use super::ITournamentAction; use bytebeasts::{ - models::{player::Player, tournament::Tournament}, + models::{player::Player, tournament::Tournament, tournament::TournamentStatus}, }; #[abi(embed_v0)] impl TournamentActionImpl of ITournamentAction { + fn create_tournament( + ref world: IWorldDispatcher, + tournament_id: u32, + name: felt252, + status: TournamentStatus, + entry_fee: u32, + max_participants: u32, + current_participants: Array, + prize_pool: u32 + ) { + let tournament = Tournament { + tournament_id: tournament_id, + name: name, + status: status, + entry_fee: entry_fee, + max_participants: max_participants, + current_participants: current_participants, + prize_pool: prize_pool + }; + set!(world, (tournament)) + } + fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament { let tournament_from_world = get!(world, tournament_id, (Tournament)); tournament_from_world } } -} \ No newline at end of file +} From 3fac51dd53686be458200d7e094d724c4c622375 Mon Sep 17 00:00:00 2001 From: Gerson2102 Date: Mon, 25 Nov 2024 16:32:59 -0600 Subject: [PATCH 3/4] Adding test file for tournament functions --- src/tests/test_tournament.cairo | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/tests/test_tournament.cairo diff --git a/src/tests/test_tournament.cairo b/src/tests/test_tournament.cairo new file mode 100644 index 0000000..d0edb7e --- /dev/null +++ b/src/tests/test_tournament.cairo @@ -0,0 +1,61 @@ +#[cfg(test)] +mod tests { + use starknet::ContractAddress; + + use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; + use dojo::utils::test::{spawn_test_world, deploy_contract}; + + use bytebeasts::{ + systems::{ + tournament::{ + tournament_system, ITournamentActionDispatcher, ITournamentActionDispatcherTrait + } + }, + }; + + use bytebeasts::{ + models::tournament::{{Tournament, tournament}}, models::tournament::TournamentStatus, + models::player::{{Player, player}}, + }; + + + // Helper function + // This function create the world and define the required models + #[test] + fn setup_world() -> (IWorldDispatcher, ITournamentActionDispatcher) { + let mut models = array![tournament::TEST_CLASS_HASH]; + + let world = spawn_test_world("bytebeasts", models); + + let contract_address = world + .deploy_contract('salt', tournament_system::TEST_CLASS_HASH.try_into().unwrap()); + + let tournament_system = ITournamentActionDispatcher { contract_address }; + + world.grant_writer(dojo::utils::bytearray_hash(@"bytebeasts"), contract_address); + + (world, tournament_system) + } + + #[test] + fn test_create_tournament() { + let (_, tournament_system) = setup_world(); + let mut players = ArrayTrait::new(); + + let player_ash = Player { + player_id: 1, + player_name: 'Ash', + beast_1: 1, // Beast 1 assigned + beast_2: 0, // No beast assigned + beast_3: 0, // No beast assigned + beast_4: 0, // No beast assigned + potions: 1 + }; + players.append(player_ash); + + tournament_system + .create_tournament(1, 'tournament', TournamentStatus::Pending, 1, 2, players, 1); + let tournament = tournament_system.get_tournament(1); + assert!(tournament.name == 'tournament', "The tournament name is wrong!"); + } +} From 7a8bae0b660543baaed6a082c2d8bb2169b9e15f Mon Sep 17 00:00:00 2001 From: Gerson2102 Date: Tue, 26 Nov 2024 14:36:23 -0600 Subject: [PATCH 4/4] Adding new implementations and deleting test file of tournament system --- src/lib.cairo | 1 - src/models/tournament.cairo | 49 +++++++++++++++++++++++++- src/systems/tournament.cairo | 36 +++++++++++++++++-- src/tests/test_tournament.cairo | 61 --------------------------------- 4 files changed, 81 insertions(+), 66 deletions(-) delete mode 100644 src/tests/test_tournament.cairo diff --git a/src/lib.cairo b/src/lib.cairo index 44d6b37..c574db2 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -33,5 +33,4 @@ mod models { mod tests { mod test_battle; mod test_bag; - mod test_tournament; } diff --git a/src/models/tournament.cairo b/src/models/tournament.cairo index 5feffa2..c31bfd9 100644 --- a/src/models/tournament.cairo +++ b/src/models/tournament.cairo @@ -1,6 +1,6 @@ use super::player::Player; -#[derive(Serde, Copy, Drop, Introspect, PartialEq)] +#[derive(Serde, Copy, Drop, Introspect, PartialEq, Debug)] pub enum TournamentStatus { Pending, Ongoing, @@ -21,3 +21,50 @@ pub struct Tournament { pub prize_pool: u32, } + +#[cfg(test)] +mod tests { + use bytebeasts::{ + models::{tournament::Tournament, tournament::TournamentStatus, player::Player} + }; + + + #[test] + fn test_tournament_initialization() { + let mut players = ArrayTrait::new(); + + let player_ash = Player { + player_id: 1, + player_name: 'Ash', + beast_1: 1, // Beast 1 assigned + beast_2: 0, // No beast assigned + beast_3: 0, // No beast assigned + beast_4: 0, // No beast assigned + potions: 1 + }; + players.append(player_ash); + + let tournament = Tournament { + tournament_id: 1, + name: 'gersonwashere', + status: TournamentStatus::Pending, + entry_fee: 1, + max_participants: 2, + current_participants: players, + prize_pool: 1, + }; + + assert_eq!(tournament.tournament_id, 1, "Tournament ID should be 1"); + assert_eq!(tournament.name, 'gersonwashere', "Tournament name should be gersonwashere"); + assert_eq!( + tournament.status, TournamentStatus::Pending, "Tournament status should be pending" + ); + assert_eq!(tournament.entry_fee, 1, "Tournament entry fee should be 1"); + assert_eq!(tournament.max_participants, 2, "Tournament max participants should be 2"); + assert_eq!( + tournament.current_participants.len(), 1, "Tournament current participants should be 1" + ); + assert_eq!(tournament.prize_pool, 1, "Tournament prize pool should be 1"); + } +} + diff --git a/src/systems/tournament.cairo b/src/systems/tournament.cairo index faf4192..6c94b8a 100644 --- a/src/systems/tournament.cairo +++ b/src/systems/tournament.cairo @@ -13,9 +13,9 @@ trait ITournamentAction { current_participants: Array, prize_pool: u32 ); - // fn register_player(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); - // fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); - // fn complete_torunament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player: Player); + fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32); + // fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament; } @@ -51,6 +51,36 @@ mod tournament_system { set!(world, (tournament)) } + fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player: Player) { + let mut tournament = get!(world, tournament_id, (Tournament)); + + assert!(tournament.status == TournamentStatus::Pending, "Tournament not open for registration"); + + assert!( + tournament.current_participants.len() < tournament.max_participants.try_into().unwrap(), + "Tournament is full" + ); + + tournament.current_participants.append(new_player); + + set!(world, (tournament)); + } + + fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32) { + let mut tournament = get!(world, tournament_id, (Tournament)); + + assert!(tournament.status == TournamentStatus::Pending, "Tournament not pending"); + + assert!( + tournament.current_participants.len() >= 2, + "Not enough participants to start" + ); + + tournament.status = TournamentStatus::Ongoing; + + set!(world, (tournament)); + } + fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament { let tournament_from_world = get!(world, tournament_id, (Tournament)); tournament_from_world diff --git a/src/tests/test_tournament.cairo b/src/tests/test_tournament.cairo deleted file mode 100644 index d0edb7e..0000000 --- a/src/tests/test_tournament.cairo +++ /dev/null @@ -1,61 +0,0 @@ -#[cfg(test)] -mod tests { - use starknet::ContractAddress; - - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; - use dojo::utils::test::{spawn_test_world, deploy_contract}; - - use bytebeasts::{ - systems::{ - tournament::{ - tournament_system, ITournamentActionDispatcher, ITournamentActionDispatcherTrait - } - }, - }; - - use bytebeasts::{ - models::tournament::{{Tournament, tournament}}, models::tournament::TournamentStatus, - models::player::{{Player, player}}, - }; - - - // Helper function - // This function create the world and define the required models - #[test] - fn setup_world() -> (IWorldDispatcher, ITournamentActionDispatcher) { - let mut models = array![tournament::TEST_CLASS_HASH]; - - let world = spawn_test_world("bytebeasts", models); - - let contract_address = world - .deploy_contract('salt', tournament_system::TEST_CLASS_HASH.try_into().unwrap()); - - let tournament_system = ITournamentActionDispatcher { contract_address }; - - world.grant_writer(dojo::utils::bytearray_hash(@"bytebeasts"), contract_address); - - (world, tournament_system) - } - - #[test] - fn test_create_tournament() { - let (_, tournament_system) = setup_world(); - let mut players = ArrayTrait::new(); - - let player_ash = Player { - player_id: 1, - player_name: 'Ash', - beast_1: 1, // Beast 1 assigned - beast_2: 0, // No beast assigned - beast_3: 0, // No beast assigned - beast_4: 0, // No beast assigned - potions: 1 - }; - players.append(player_ash); - - tournament_system - .create_tournament(1, 'tournament', TournamentStatus::Pending, 1, 2, players, 1); - let tournament = tournament_system.get_tournament(1); - assert!(tournament.name == 'tournament', "The tournament name is wrong!"); - } -}