From 8e0c127e5defbf425dece9e86771d6045a038d7a Mon Sep 17 00:00:00 2001 From: bal7hazar Date: Sat, 20 Apr 2024 09:25:53 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20slot=20manamgent=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/matchmaker/src/constants.cairo | 2 + examples/matchmaker/src/models/league.cairo | 49 ++++---- examples/matchmaker/src/models/player.cairo | 22 ++-- examples/matchmaker/src/models/registry.cairo | 41 +++---- examples/matchmaker/src/models/slot.cairo | 13 ++- examples/matchmaker/src/store.cairo | 21 ++-- examples/matchmaker/src/systems/maker.cairo | 59 +++++----- examples/matchmaker/src/tests/setup.cairo | 26 ++--- .../matchmaker/src/tests/test_create.cairo | 2 +- .../matchmaker/src/tests/test_fight.cairo | 105 +++++++++++++++++- .../matchmaker/src/tests/test_subscribe.cairo | 2 +- .../src/tests/test_unsubscribe.cairo | 2 +- 12 files changed, 226 insertions(+), 118 deletions(-) diff --git a/examples/matchmaker/src/constants.cairo b/examples/matchmaker/src/constants.cairo index 58186d54..42b296f7 100644 --- a/examples/matchmaker/src/constants.cairo +++ b/examples/matchmaker/src/constants.cairo @@ -6,6 +6,8 @@ const DEFAULT_RATING: u32 = 1000; // Leagues const LEAGUE_SIZE: u8 = 20; +const LEAGUE_COUNT: u8 = 17; +const LEAGUE_MIN_THRESHOLD: u32 = 1000; // World diff --git a/examples/matchmaker/src/models/league.cairo b/examples/matchmaker/src/models/league.cairo index 1bb9baa6..28e6a2a0 100644 --- a/examples/matchmaker/src/models/league.cairo +++ b/examples/matchmaker/src/models/league.cairo @@ -5,7 +5,7 @@ use starknet::ContractAddress; // Internal imports -use matchmaker::constants::LEAGUE_SIZE; +use matchmaker::constants::{LEAGUE_SIZE, LEAGUE_COUNT, LEAGUE_MIN_THRESHOLD}; use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; use matchmaker::models::slot::{Slot, SlotTrait}; @@ -33,7 +33,14 @@ impl LeagueImpl of LeagueTrait { #[inline(always)] fn compute_id(rating: u32) -> u8 { - let id = rating / LEAGUE_SIZE.into(); + if rating <= LEAGUE_MIN_THRESHOLD { + return 1; + } + let max_rating = LEAGUE_MIN_THRESHOLD + LEAGUE_SIZE.into() * LEAGUE_COUNT.into(); + if rating >= max_rating { + return LEAGUE_COUNT; + } + let id = 1 + (rating - LEAGUE_MIN_THRESHOLD) / LEAGUE_SIZE.into(); if id > 251 { 251 } else if id < 1 { @@ -90,7 +97,10 @@ mod tests { // Local imports - use super::{League, LeagueTrait, Player, PlayerTrait, ContractAddress}; + use super::{ + League, LeagueTrait, Player, PlayerTrait, ContractAddress, LEAGUE_SIZE, LEAGUE_COUNT, + LEAGUE_MIN_THRESHOLD + }; // Constants @@ -98,29 +108,30 @@ mod tests { starknet::contract_address_const::<'PLAYER'>() } - const REGISTER_ID: u32 = 1; + const PLAYER_NAME: felt252 = 'NAME'; + const REGISTRY_ID: u32 = 1; const LEAGUE_ID: u8 = 1; #[test] fn test_new() { - let league = LeagueTrait::new(REGISTER_ID, LEAGUE_ID); - assert_eq!(league.registry_id, REGISTER_ID); + let league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); + assert_eq!(league.registry_id, REGISTRY_ID); assert_eq!(league.id, LEAGUE_ID); assert_eq!(league.size, 0); } #[test] fn test_compute_id() { - let rating = 1000; + let rating = LEAGUE_MIN_THRESHOLD - 1; let league_id = LeagueTrait::compute_id(rating); - assert_eq!(league_id, 50); + assert_eq!(league_id, 1); } #[test] fn test_compute_id_overflow() { - let rating = 10000; - let league_id = LeagueTrait::compute_id(rating); - assert_eq!(league_id, 251); + let max_rating = LEAGUE_MIN_THRESHOLD + LEAGUE_SIZE.into() * LEAGUE_COUNT.into() + 1; + let league_id = LeagueTrait::compute_id(max_rating); + assert_eq!(league_id, LEAGUE_COUNT); } #[test] @@ -132,8 +143,8 @@ mod tests { #[test] fn test_subscribe_once() { - let mut player = PlayerTrait::new(REGISTER_ID, PLAYER()); - let mut league = LeagueTrait::new(REGISTER_ID, LEAGUE_ID); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); + let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); let slot = LeagueTrait::subscribe(ref league, ref player); // [Assert] League assert_eq!(league.size, 1); @@ -147,16 +158,16 @@ mod tests { #[test] #[should_panic(expected: ('Player: not subscribable',))] fn test_subscribe_twice() { - let mut player = PlayerTrait::new(REGISTER_ID, PLAYER()); - let mut league = LeagueTrait::new(REGISTER_ID, LEAGUE_ID); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); + let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); LeagueTrait::subscribe(ref league, ref player); LeagueTrait::subscribe(ref league, ref player); } #[test] fn test_unsubscribe_once() { - let mut player = PlayerTrait::new(REGISTER_ID, PLAYER()); - let mut league = LeagueTrait::new(REGISTER_ID, LEAGUE_ID); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); + let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); LeagueTrait::subscribe(ref league, ref player); LeagueTrait::unsubscribe(ref league, ref player); // [Assert] League @@ -169,8 +180,8 @@ mod tests { #[test] #[should_panic(expected: ('League: player not subscribed',))] fn test_unsubscribe_twice() { - let mut player = PlayerTrait::new(REGISTER_ID, PLAYER()); - let mut league = LeagueTrait::new(REGISTER_ID, LEAGUE_ID); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); + let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); LeagueTrait::subscribe(ref league, ref player); LeagueTrait::unsubscribe(ref league, ref player); LeagueTrait::unsubscribe(ref league, ref player); diff --git a/examples/matchmaker/src/models/player.cairo b/examples/matchmaker/src/models/player.cairo index d6da4540..69d7e826 100644 --- a/examples/matchmaker/src/models/player.cairo +++ b/examples/matchmaker/src/models/player.cairo @@ -29,6 +29,7 @@ struct Player { registry_id: u32, #[key] id: ContractAddress, + name: felt252, league_id: u8, index: u32, rating: u32, @@ -37,8 +38,8 @@ struct Player { #[generate_trait] impl PlayerImpl of PlayerTrait { #[inline(always)] - fn new(registry_id: u32, id: ContractAddress) -> Player { - Player { registry_id, id, league_id: 0, index: 0, rating: DEFAULT_RATING, } + fn new(registry_id: u32, id: ContractAddress, name: felt252) -> Player { + Player { registry_id, id, name, league_id: 0, index: 0, rating: DEFAULT_RATING, } } #[inline(always)] @@ -89,7 +90,7 @@ impl PlayerAssert of AssertTrait { impl PlayerZeroable of Zeroable { #[inline(always)] fn zero() -> Player { - Player { registry_id: 0, id: ZERO(), league_id: 0, index: 0, rating: 0, } + Player { registry_id: 0, id: ZERO(), name: 0, league_id: 0, index: 0, rating: 0, } } #[inline(always)] @@ -119,13 +120,14 @@ mod tests { starknet::contract_address_const::<'PLAYER'>() } - const REGISTER_ID: u32 = 1; + const PLAYER_NAME: felt252 = 'NAME'; + const REGISTRY_ID: u32 = 1; #[test] fn test_new() { let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTER_ID, player_id); - assert_eq!(player.registry_id, REGISTER_ID); + let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); + assert_eq!(player.registry_id, REGISTRY_ID); assert_eq!(player.id, player_id); assert_eq!(player.league_id, 0); assert_eq!(player.index, 0); @@ -135,7 +137,7 @@ mod tests { #[test] fn test_subscribable() { let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTER_ID, player_id); + let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); AssertTrait::assert_subscribable(player); } @@ -143,7 +145,7 @@ mod tests { #[should_panic(expected: ('Player: not subscribable',))] fn test_subscribable_revert_not_subscribable() { let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTER_ID, player_id); + let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); player.league_id = 1; AssertTrait::assert_subscribable(player); } @@ -151,7 +153,7 @@ mod tests { #[test] fn test_subscribed() { let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTER_ID, player_id); + let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); player.league_id = 1; AssertTrait::assert_subscribed(player); } @@ -160,7 +162,7 @@ mod tests { #[should_panic(expected: ('Player: not subscribed',))] fn test_subscribed_revert_not_subscribed() { let player_id = PLAYER(); - let player = PlayerTrait::new(REGISTER_ID, player_id); + let player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); AssertTrait::assert_subscribed(player); } } diff --git a/examples/matchmaker/src/models/registry.cairo b/examples/matchmaker/src/models/registry.cairo index 1904d1a6..46544a3f 100644 --- a/examples/matchmaker/src/models/registry.cairo +++ b/examples/matchmaker/src/models/registry.cairo @@ -47,7 +47,7 @@ impl RegistryImpl of RegistryTrait { } #[inline(always)] - fn search_league(mut self: Registry, mut league: League, mut player: Player) -> u8 { + fn search_league(ref self: Registry, ref league: League, ref player: Player) -> u8 { // [Check] Player has subscribed PlayerAssert::assert_subscribed(player); // [Effect] Unsubcribe player from his league @@ -110,6 +110,7 @@ mod tests { starknet::contract_address_const::<'TARGET'>() } + const PLAYER_NAME: felt252 = 'NAME'; const REGISTRY_ID: u32 = 1; const LEAGUE_ID: u8 = 1; const CLOSEST_LEAGUE_ID: u8 = 2; @@ -127,7 +128,7 @@ mod tests { #[test] fn test_subscribe() { let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); registry.subscribe(ref league, ref player); // [Assert] Registry @@ -137,7 +138,7 @@ mod tests { #[test] fn test_unsubscribe() { let mut registry = RegistryTrait::new(REGISTRY_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); registry.subscribe(ref league, ref player); registry.unsubscribe(ref league, ref player); @@ -149,11 +150,11 @@ mod tests { fn test_search_league_same() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET()); + let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); registry.subscribe(ref league, ref foe); - let league_id = registry.search_league(league, player); + let league_id = registry.search_league(ref league, ref player); // [Assert] Registry assert(league_id == LEAGUE_ID, 'Registry: wrong search league'); } @@ -162,12 +163,12 @@ mod tests { fn test_search_league_close() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); let mut foe_league = LeagueTrait::new(REGISTRY_ID, CLOSEST_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET()); + let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(league, player); + let league_id = registry.search_league(ref league, ref player); // [Assert] Registry assert(league_id == CLOSEST_LEAGUE_ID, 'Registry: wrong search league'); } @@ -176,12 +177,12 @@ mod tests { fn test_search_league_target() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); let mut foe_league = LeagueTrait::new(REGISTRY_ID, TARGET_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET()); + let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(league, player); + let league_id = registry.search_league(ref league, ref player); // [Assert] Registry assert(league_id == TARGET_LEAGUE_ID, 'Registry: wrong search league'); } @@ -190,12 +191,12 @@ mod tests { fn test_search_league_far_down_top() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); let mut foe_league = LeagueTrait::new(REGISTRY_ID, FAREST_LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET()); + let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(league, player); + let league_id = registry.search_league(ref league, ref player); // [Assert] Registry assert(league_id == FAREST_LEAGUE_ID, 'Registry: wrong search league'); } @@ -204,12 +205,12 @@ mod tests { fn test_search_league_far_top_down() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, FAREST_LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); let mut foe_league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET()); + let mut foe = PlayerTrait::new(REGISTRY_ID, TARGET(), PLAYER_NAME); registry.subscribe(ref foe_league, ref foe); - let league_id = registry.search_league(league, player); + let league_id = registry.search_league(ref league, ref player); // [Assert] Registry assert(league_id == LEAGUE_ID, 'Registry: wrong search league'); } @@ -219,8 +220,8 @@ mod tests { fn test_search_league_revert_empty() { let mut registry = RegistryTrait::new(REGISTRY_ID); let mut league = LeagueTrait::new(REGISTRY_ID, LEAGUE_ID); - let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER()); + let mut player = PlayerTrait::new(REGISTRY_ID, PLAYER(), PLAYER_NAME); registry.subscribe(ref league, ref player); - registry.search_league(league, player); + registry.search_league(ref league, ref player); } } diff --git a/examples/matchmaker/src/models/slot.cairo b/examples/matchmaker/src/models/slot.cairo index ab1c5056..c36490b2 100644 --- a/examples/matchmaker/src/models/slot.cairo +++ b/examples/matchmaker/src/models/slot.cairo @@ -4,6 +4,7 @@ use starknet::ContractAddress; // Internal imports +use matchmaker::constants::ZERO; use matchmaker::models::player::{Player, PlayerTrait}; #[derive(Model, Copy, Drop, Serde)] @@ -28,6 +29,11 @@ impl SlotImpl of SlotTrait { player_id: player.id, } } + + #[inline(always)] + fn nullify(ref self: Slot) { + self.player_id = ZERO(); + } } #[cfg(test)] @@ -46,18 +52,19 @@ mod tests { starknet::contract_address_const::<'PLAYER'>() } - const REGISTER_ID: u32 = 1; + const PLAYER_NAME: felt252 = 'NAME'; + const REGISTRY_ID: u32 = 1; const LEAGUE_ID: u8 = 2; const INDEX: u32 = 3; #[test] fn test_new() { let player_id = PLAYER(); - let mut player = PlayerTrait::new(REGISTER_ID, player_id); + let mut player = PlayerTrait::new(REGISTRY_ID, player_id, PLAYER_NAME); player.league_id = LEAGUE_ID; player.index = INDEX; let slot = SlotTrait::new(player); - assert_eq!(slot.registry_id, REGISTER_ID); + assert_eq!(slot.registry_id, REGISTRY_ID); assert_eq!(slot.league_id, LEAGUE_ID); assert_eq!(slot.index, INDEX); assert_eq!(slot.player_id, player_id); diff --git a/examples/matchmaker/src/store.cairo b/examples/matchmaker/src/store.cairo index e74c6425..1002bb06 100644 --- a/examples/matchmaker/src/store.cairo +++ b/examples/matchmaker/src/store.cairo @@ -17,7 +17,7 @@ use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; use matchmaker::models::league::{League, LeagueTrait}; use matchmaker::models::player::Player; use matchmaker::models::registry::Registry; -use matchmaker::models::slot::Slot; +use matchmaker::models::slot::{Slot, SlotTrait}; /// Store struct. @@ -77,15 +77,20 @@ impl StoreImpl of StoreTrait { #[inline(always)] fn remove_player_slot(self: Store, player: Player) { // [Effect] Replace the slot with the last slot if needed - let mut league = self.league(player.registry_id, player.league_id); - let mut last_slot = self.slot(league.registry_id, player.league_id, league.size - 1); - if last_slot.player_id != player.id { - last_slot.index = player.index; + let league = self.league(player.registry_id, player.league_id); + let mut player_slot = self.slot(player.registry_id, player.league_id, player.index); + let mut last_slot = self.slot(player.registry_id, player.league_id, league.size - 1); + if last_slot.index != player_slot.index { + let mut last_player = self.player(player.registry_id, last_slot.player_id); + let last_slot_index = last_slot.index; + last_slot.index = player_slot.index; + last_player.index = player_slot.index; + player_slot.index = last_slot_index; + self.set_player(last_player); self.set_slot(last_slot); } // [Effect] Remove the last slot - let mut empty_slot = self.slot(league.registry_id, player.league_id, league.size); - empty_slot.index = league.size - 1; - self.set_slot(empty_slot); + player_slot.nullify(); + self.set_slot(player_slot); } } diff --git a/examples/matchmaker/src/systems/maker.cairo b/examples/matchmaker/src/systems/maker.cairo index ae49071c..ad9f1047 100644 --- a/examples/matchmaker/src/systems/maker.cairo +++ b/examples/matchmaker/src/systems/maker.cairo @@ -10,7 +10,7 @@ use dojo::world::IWorldDispatcher; #[starknet::interface] trait IMaker { - fn create(self: @TContractState, world: IWorldDispatcher); + fn create(self: @TContractState, world: IWorldDispatcher, name: felt252); fn subscribe(self: @TContractState, world: IWorldDispatcher); fn unsubscribe(self: @TContractState, world: IWorldDispatcher); fn fight(self: @TContractState, world: IWorldDispatcher); @@ -80,7 +80,7 @@ mod maker { #[abi(embed_v0)] impl MakerImpl of IMaker { - fn create(self: @ContractState, world: IWorldDispatcher) { + fn create(self: @ContractState, world: IWorldDispatcher, name: felt252) { // [Setup] Datastore let mut store: Store = StoreTrait::new(world); @@ -90,7 +90,7 @@ mod maker { PlayerAssert::assert_not_exist(player); // [Effect] Create one - let player = PlayerTrait::new(0, caller); + let player = PlayerTrait::new(0, caller, name); store.set_player(player); } @@ -158,48 +158,45 @@ mod maker { let mut player = store.player(0, caller); PlayerAssert::assert_does_exist(player); - // [Compute] Search opponent + // [Effect] Remove slot + store.remove_player_slot(player); + + // [Effect] Search opponent which unsubscribe, then update league let seed = get_tx_info().unbox().transaction_hash; let mut registry = store.registry(0); let mut player_league = store.league(0, player.league_id); - let foe_league_id = registry.search_league(player_league, player); + let foe_league_id = registry.search_league(ref player_league, ref player); + store.set_league(player_league); + + // [Compute] Foe let mut foe_league = store.league(0, foe_league_id); let foe_slot_id = foe_league.search_player(seed); let foe_slot = store.slot(0, foe_league_id, foe_slot_id); let mut foe = store.player(0, foe_slot.player_id); - // [Effect] Fight - player.fight(ref foe, seed); - - // [Effect] Remove player slot - store.remove_player_slot(player); - - // [Effect] Update Player league and slot - registry.unsubscribe(ref player_league, ref player); - let league_id = LeagueTrait::compute_id(player.rating); - let mut player_league = store.league(0, league_id); - let player_slot = registry.subscribe(ref player_league, ref player); - - // [Effect] Remove foe slot + // [Effect] Remove foe slot, unsubscribe and update league store.remove_player_slot(foe); - - // [Effect] Update Foe league and slot registry.unsubscribe(ref foe_league, ref foe); - let foe_league_id = LeagueTrait::compute_id(foe.rating); - let mut foe_league = store.league(0, foe_league_id); - let foe_slot = registry.subscribe(ref foe_league, ref foe); + store.set_league(foe_league); - // [Effect] Update Slots - store.set_slot(player_slot); - store.set_slot(foe_slot); + // [Effect] Fight and update players + player.fight(ref foe, seed); - // [Effect] Update Players + // [Effect] Update player, league and slot + let league_id = LeagueTrait::compute_id(player.rating); + let mut league = store.league(0, league_id); + let slot = registry.subscribe(ref league, ref player); + store.set_league(league); + store.set_slot(slot); store.set_player(player); - store.set_player(foe); - // [Effect] Update League - store.set_league(player_league); - store.set_league(foe_league); + // [Effect] Update Foe, league and slot + let league_id = LeagueTrait::compute_id(foe.rating); + let mut league = store.league(0, league_id); + let slot = registry.subscribe(ref league, ref foe); + store.set_league(league); + store.set_slot(slot); + store.set_player(foe); // [Effect] Update Registry store.set_registry(registry); diff --git a/examples/matchmaker/src/tests/setup.cairo b/examples/matchmaker/src/tests/setup.cairo index cee0866a..9fc86243 100644 --- a/examples/matchmaker/src/tests/setup.cairo +++ b/examples/matchmaker/src/tests/setup.cairo @@ -27,18 +27,12 @@ mod setup { starknet::contract_address_const::<'PLAYER'>() } - fn ANYONE() -> ContractAddress { - starknet::contract_address_const::<'ANYONE'>() - } - fn SOMEONE() -> ContractAddress { starknet::contract_address_const::<'SOMEONE'>() } - fn NOONE() -> ContractAddress { - starknet::contract_address_const::<'NOONE'>() - } - + const PLAYER_NAME: felt252 = 'PLAYER'; + const SOMEONE_NAME: felt252 = 'SOMEONE'; const REGISTRY_ID: u32 = 0; #[derive(Drop)] @@ -51,8 +45,8 @@ mod setup { registry_id: u32, player_id: ContractAddress, someone_id: ContractAddress, - anyone_id: ContractAddress, - noone_id: ContractAddress, + player_name: felt252, + someone_name: felt252, } #[inline(always)] @@ -71,21 +65,15 @@ mod setup { // [Setup] Context set_contract_address(SOMEONE()); - systems.maker.create(world); - systems.maker.subscribe(world); - set_contract_address(ANYONE()); - systems.maker.create(world); - systems.maker.subscribe(world); - set_contract_address(NOONE()); - systems.maker.create(world); + systems.maker.create(world, SOMEONE_NAME); systems.maker.subscribe(world); set_contract_address(PLAYER()); let context = Context { registry_id: REGISTRY_ID, player_id: PLAYER(), someone_id: SOMEONE(), - anyone_id: ANYONE(), - noone_id: NOONE() + player_name: PLAYER_NAME, + someone_name: SOMEONE_NAME, }; // [Return] diff --git a/examples/matchmaker/src/tests/test_create.cairo b/examples/matchmaker/src/tests/test_create.cairo index 6a41fbae..f77607a7 100644 --- a/examples/matchmaker/src/tests/test_create.cairo +++ b/examples/matchmaker/src/tests/test_create.cairo @@ -27,7 +27,7 @@ fn test_maker_create() { let store = StoreTrait::new(world); // [Create] - systems.maker.create(world); + systems.maker.create(world, context.player_name); // [Assert] Player let player = store.player(context.registry_id, context.player_id); diff --git a/examples/matchmaker/src/tests/test_fight.cairo b/examples/matchmaker/src/tests/test_fight.cairo index 3c8d83f5..ca682dbf 100644 --- a/examples/matchmaker/src/tests/test_fight.cairo +++ b/examples/matchmaker/src/tests/test_fight.cairo @@ -4,7 +4,7 @@ use core::debug::PrintTrait; // Starknet imports -use starknet::testing::set_contract_address; +use starknet::testing::{set_contract_address, set_transaction_hash}; // Dojo imports @@ -12,6 +12,7 @@ use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; // Internal imports +use matchmaker::constants::DEFAULT_RATING; use matchmaker::store::{Store, StoreTrait}; use matchmaker::models::player::{Player, PlayerTrait, PlayerAssert}; use matchmaker::models::registry::{Registry, RegistryTrait, RegistryAssert}; @@ -21,23 +22,117 @@ use matchmaker::systems::maker::IMakerDispatcherTrait; use matchmaker::tests::setup::{setup, setup::Systems}; #[test] -fn test_maker_fight() { +fn test_maker_fight_lose() { // [Setup] let (world, systems, context) = setup::spawn(); let store = StoreTrait::new(world); // [Create] - systems.maker.create(world); + systems.maker.create(world, context.player_name); // [Subscribe] systems.maker.subscribe(world); // [Fight] + set_transaction_hash(0); + systems.maker.fight(world); + + // [Assert] Player let player = store.player(context.registry_id, context.player_id); - let rating = player.rating; + assert(player.rating != DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Someone + let someone = store.player(context.registry_id, context.someone_id); + assert(someone.rating != DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Global rating + let total = 2 * DEFAULT_RATING; + assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); +} + +#[test] +fn test_maker_fight_draw() { + // [Setup] + let (world, systems, context) = setup::spawn(); + let store = StoreTrait::new(world); + + // [Create] + systems.maker.create(world, context.player_name); + + // [Subscribe] + systems.maker.subscribe(world); + + // [Fight] + set_transaction_hash(1); + systems.maker.fight(world); + + // [Assert] Player + let player = store.player(context.registry_id, context.player_id); + assert(player.rating == DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Someone + let someone = store.player(context.registry_id, context.someone_id); + assert(someone.rating == DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Global rating + let total = 2 * DEFAULT_RATING; + assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); +} + +#[test] +fn test_maker_fight_win() { + // [Setup] + let (world, systems, context) = setup::spawn(); + let store = StoreTrait::new(world); + + // [Create] + systems.maker.create(world, context.player_name); + + // [Subscribe] + systems.maker.subscribe(world); + + // [Fight] + set_transaction_hash(2); systems.maker.fight(world); // [Assert] Player let player = store.player(context.registry_id, context.player_id); - assert(player.rating != rating, 'Fight: wrong player rating'); + assert(player.rating != DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Someone + let someone = store.player(context.registry_id, context.someone_id); + assert(someone.rating != DEFAULT_RATING, 'Fight: wrong player rating'); + + // [Assert] Global rating + let total = 2 * DEFAULT_RATING; + assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); +} + +#[test] +fn test_maker_fight_several_times() { + // [Setup] + let (world, systems, context) = setup::spawn(); + let store = StoreTrait::new(world); + + // [Create] + systems.maker.create(world, context.player_name); + + // [Subscribe] + systems.maker.subscribe(world); + + // [Fight] + let mut iter = 2; + loop { + if iter == 0 { + break; + } + systems.maker.fight(world); + iter -= 1; + }; + + // [Assert] Global rating + let total = 2 * DEFAULT_RATING; + let player = store.player(context.registry_id, context.player_id); + let someone = store.player(context.registry_id, context.someone_id); + assert(player.rating + someone.rating == total, 'Fight: wrong global rating'); } diff --git a/examples/matchmaker/src/tests/test_subscribe.cairo b/examples/matchmaker/src/tests/test_subscribe.cairo index 5c5555d4..b208ba37 100644 --- a/examples/matchmaker/src/tests/test_subscribe.cairo +++ b/examples/matchmaker/src/tests/test_subscribe.cairo @@ -27,7 +27,7 @@ fn test_maker_subscribe() { let store = StoreTrait::new(world); // [Create] - systems.maker.create(world); + systems.maker.create(world, context.player_name); // [Subscribe] systems.maker.subscribe(world); diff --git a/examples/matchmaker/src/tests/test_unsubscribe.cairo b/examples/matchmaker/src/tests/test_unsubscribe.cairo index dab14f06..8aa89cbc 100644 --- a/examples/matchmaker/src/tests/test_unsubscribe.cairo +++ b/examples/matchmaker/src/tests/test_unsubscribe.cairo @@ -27,7 +27,7 @@ fn test_maker_unsubscribe() { let store = StoreTrait::new(world); // [Create] - systems.maker.create(world); + systems.maker.create(world, context.player_name); // [Subscribe] systems.maker.subscribe(world);