From 71231098d1213621a24158b527c22b3ec6a55395 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Wed, 27 Nov 2024 22:56:44 +0100 Subject: [PATCH 01/16] Dependencies and leaderboardEntry class --- Scarb.lock | 51 ++++++++++++++++ Scarb.toml | 3 + src/lib.cairo | 1 + src/models/leaderboard.cairo | 115 +++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 src/models/leaderboard.cairo diff --git a/Scarb.lock b/Scarb.lock index 0295b6c..8c1a2e0 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,10 +1,61 @@ # Code generated by scarb DO NOT EDIT. version = 1 +[[package]] +name = "alexandria_data_structures" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_encoding", +] + +[[package]] +name = "alexandria_encoding" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_math", + "alexandria_numeric", +] + +[[package]] +name = "alexandria_math" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_data_structures", +] + +[[package]] +name = "alexandria_numeric" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_math", +] + +[[package]] +name = "alexandria_searching" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_data_structures", +] + +[[package]] +name = "alexandria_sorting" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +dependencies = [ + "alexandria_data_structures", +] + [[package]] name = "bytebeasts" version = "0.1.0" dependencies = [ + "alexandria_searching", + "alexandria_sorting", "dojo", ] diff --git a/Scarb.toml b/Scarb.toml index 7a14c65..0b27d87 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -13,5 +13,8 @@ move = "./scripts/move.sh" [dependencies] dojo = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.5" } +# Alexandria versions with tag greater that "cairo-v.5.4" conflict with dojo engine +alexandria_searching = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.5.4" } +alexandria_sorting = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.5.4" } [[target.dojo]] diff --git a/src/lib.cairo b/src/lib.cairo index c574db2..b6ba634 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -28,6 +28,7 @@ mod models { mod achievement_type; mod achievements; mod tournament; + mod leaderboard; } mod tests { diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo new file mode 100644 index 0000000..2865ac3 --- /dev/null +++ b/src/models/leaderboard.cairo @@ -0,0 +1,115 @@ +use starknet::ContractAddress; +use alexandria_data_structures::array_ext::ArrayTraitExt; +use alexandria_searching::binary_search::binary_search; +use alexandria_sorting::merge_sort::sort; +use core::{ + result::Result, + option::OptionTrait, + array::ArrayTrait +}; + +const MAX_ENTRIES: usize = 5; + +#[derive(Copy, Drop, Serde)] +#[dojo::model] +pub struct LeaderboardEntry { + #[key] + pub player_id: u32, // On-chain player address + pub player_name: felt252, // Display name + pub score: u32, // Overall score + pub rank: u32, // Rank in the leaderboard + pub wins: u32, // Total wins + pub losses: u32, // Total losses + pub highest_score: u32, // Highest score in a single game + pub is_active: bool, // Whether the player is currently active +} + + +impl LeaderboardEntryPartialOrd of PartialOrd { + fn le(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { + // less than or equal + lhs.score <= rhs.score + } + + fn ge(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { + // greater than or equal + lhs.score >= rhs.score + } + + fn lt(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { + lhs.score < rhs.score + } + + fn gt(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { + lhs.score > rhs.score + } +} + +impl LeaderboardEntryPartialEq of PartialEq { + fn eq(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { + lhs.score == rhs.score + } + + fn ne(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { + lhs.score != rhs.score + } +} + + +#[derive(Drop, Serde)] +#[dojo::model] +pub struct Leaderboard { + #[key] + pub leaderboard_id: u64, // Unique ID for leaderboard (could be incremental) + pub name: felt252, // Leaderboard name (e.g., "Global", "Monthly") + pub description: felt252, // Description of what this leaderboard tracks + pub entries: Array, // List of leaderboard entries + pub last_updated: u64, // Timestamp of last update +} + + + +trait LeaderboardBehavior { + // implemented: + fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; + fn is_full(self: @Leaderboard) -> bool; + // not implemented: + // fn remove_entry(&mut self, player_id: ContractAddress); + // fn sort_by_score(&mut self); + // fn get_top_n(&self, n: usize) -> Vec; + // fn filter_players(&self, filter: LeaderboardFilter) -> Vec; + // fn get_player_rank(&self, player_id: ContractAddress) -> Option; + // fn get_summary(&self) -> LeaderboardSummary; + // fn batch_update_entries(&mut self, updates: Vec); + // fn save_snapshot(&self); + // fn get_snapshot(&self, timestamp: u64) -> Option; + // fn merge_leaderboards(&mut self, other: Leaderboard); + // fn last_updated_string(&self) -> felt252; +} + + +#[generate_trait] +impl LeaderboardImpl of LeaderboardTrait { + fn add_entry(ref self: Leaderboard, mut entry: LeaderboardEntry) -> Result<(), felt252> { + if self.is_full() { + return Result::Err('Leaderboard is full'); + } + // Assign an initial value + entry.rank = self.entries.len() + 1; + // Add new entry + self.entries.append(entry); + // Sort array DONT WORK + // let sorted = merge(entries_span); + // Update timestamp + self.last_updated = starknet::get_block_timestamp(); + Result::Ok(()) + } + + fn is_full(self: @Leaderboard) -> bool { + self.entries.len() >= MAX_ENTRIES + } + + +} + + From dc13459ecc0563ddc25ef1c0d52b3c108f11ed71 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Wed, 27 Nov 2024 23:30:00 +0100 Subject: [PATCH 02/16] leaderboard behavior --- src/models/leaderboard.cairo | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 2865ac3..6df230a 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -74,17 +74,17 @@ trait LeaderboardBehavior { fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; fn is_full(self: @Leaderboard) -> bool; // not implemented: - // fn remove_entry(&mut self, player_id: ContractAddress); - // fn sort_by_score(&mut self); + // fn remove_entry(mut self, player_id: ContractAddress); + // fn sort_by_score(mut self); // fn get_top_n(&self, n: usize) -> Vec; - // fn filter_players(&self, filter: LeaderboardFilter) -> Vec; - // fn get_player_rank(&self, player_id: ContractAddress) -> Option; + // fn filter_players(self, filter: LeaderboardFilter) -> Vec; + // fn get_player_rank(self, player_id: ContractAddress) -> Option; // fn get_summary(&self) -> LeaderboardSummary; - // fn batch_update_entries(&mut self, updates: Vec); - // fn save_snapshot(&self); - // fn get_snapshot(&self, timestamp: u64) -> Option; - // fn merge_leaderboards(&mut self, other: Leaderboard); - // fn last_updated_string(&self) -> felt252; + // fn batch_update_entries(mut self, updates: Vec); + // fn save_snapshot(self); + // fn get_snapshot(self, timestamp: u64) -> Option; + // fn merge_leaderboards(mut self, other: Leaderboard); + // fn last_updated_string(self) -> felt252; } From 04831ba649868eb12bb9b3426092d5570cb5e834 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Thu, 28 Nov 2024 01:53:29 +0100 Subject: [PATCH 03/16] dynamycally update entry --- src/models/leaderboard.cairo | 81 +++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 6df230a..e2c00b9 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -1,7 +1,6 @@ use starknet::ContractAddress; use alexandria_data_structures::array_ext::ArrayTraitExt; -use alexandria_searching::binary_search::binary_search; -use alexandria_sorting::merge_sort::sort; +use alexandria_sorting::bubble_sort::bubble_sort_elements; use core::{ result::Result, option::OptionTrait, @@ -24,7 +23,7 @@ pub struct LeaderboardEntry { pub is_active: bool, // Whether the player is currently active } - +//trait for sorting by score impl LeaderboardEntryPartialOrd of PartialOrd { fn le(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { // less than or equal @@ -45,16 +44,47 @@ impl LeaderboardEntryPartialOrd of PartialOrd { } } +//trait for search by player_id impl LeaderboardEntryPartialEq of PartialEq { fn eq(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { - lhs.score == rhs.score + lhs.player_id == rhs.player_id } fn ne(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { - lhs.score != rhs.score + lhs.player_id != rhs.player_id } } +// impl SpanLeaderboardEntryPartialOrd of PartialOrd<@LeaderboardEntry> { +// fn le(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { +// // less than or equal +// lhs.player_id <= rhs.player_id +// } + +// fn ge(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { +// // greater than or equal +// lhs.player_id >= rhs.player_id +// } + +// fn lt(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { +// lhs.player_id < rhs.player_id +// } + +// fn gt(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { +// lhs.player_id > rhs.player_id +// } +// } + +// impl SpanLeaderboardEntryPartialEq of PartialEq<@LeaderboardEntry> { +// fn eq(lhs: @@LeaderboardEntry, rhs: @@LeaderboardEntry) -> bool { +// lhs.player_id == rhs.player_id +// } + +// fn ne(lhs: @@LeaderboardEntry, rhs: @@LeaderboardEntry) -> bool { +// lhs.player_id != rhs.player_id +// } +// } + #[derive(Drop, Serde)] #[dojo::model] @@ -72,6 +102,7 @@ pub struct Leaderboard { trait LeaderboardBehavior { // implemented: fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; + fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; fn is_full(self: @Leaderboard) -> bool; // not implemented: // fn remove_entry(mut self, player_id: ContractAddress); @@ -91,25 +122,47 @@ trait LeaderboardBehavior { #[generate_trait] impl LeaderboardImpl of LeaderboardTrait { fn add_entry(ref self: Leaderboard, mut entry: LeaderboardEntry) -> Result<(), felt252> { - if self.is_full() { - return Result::Err('Leaderboard is full'); + // look for entry by player_id + let res = self.entries.index_of(entry); + if res.is_some() { + return Result::Err('Entry already exists'); } - // Assign an initial value - entry.rank = self.entries.len() + 1; - // Add new entry self.entries.append(entry); - // Sort array DONT WORK - // let sorted = merge(entries_span); + // Sort array by score + let sorted = bubble_sort_elements(self.entries.clone(), true); + self.entries = sorted; // Update timestamp self.last_updated = starknet::get_block_timestamp(); Result::Ok(()) } - fn is_full(self: @Leaderboard) -> bool { - self.entries.len() >= MAX_ENTRIES + fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { + // we have to devide array into two parts change the entry and merge them back + // Find entry + let res = self.entries.index_of(entry); + if res.is_none() { + return Result::Err('Entry not found'); + } + let index = res.unwrap(); + let mut left = 0; + if index != 0 { + let mut left = self.entries.pop_front_n(index); + left.append(entry); + let _ = self.entries.pop_front(); + self.entries = left.append_all(ref self.entries); + } + else { + let mut left = array![entry]; + let _ = self.entries.pop_front(); + } + self.entries = left.append_all(ref self.entries); + // Update entry + self.last_updated = starknet::get_block_timestamp(); + Result::Ok(()) } + } From acccbc49b6253082b9fb0f02ee49997900e16f1c Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Thu, 28 Nov 2024 02:27:36 +0100 Subject: [PATCH 04/16] deleted unnecessary comments --- src/models/leaderboard.cairo | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index e2c00b9..79df103 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -55,36 +55,6 @@ impl LeaderboardEntryPartialEq of PartialEq { } } -// impl SpanLeaderboardEntryPartialOrd of PartialOrd<@LeaderboardEntry> { -// fn le(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { -// // less than or equal -// lhs.player_id <= rhs.player_id -// } - -// fn ge(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { -// // greater than or equal -// lhs.player_id >= rhs.player_id -// } - -// fn lt(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { -// lhs.player_id < rhs.player_id -// } - -// fn gt(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { -// lhs.player_id > rhs.player_id -// } -// } - -// impl SpanLeaderboardEntryPartialEq of PartialEq<@LeaderboardEntry> { -// fn eq(lhs: @@LeaderboardEntry, rhs: @@LeaderboardEntry) -> bool { -// lhs.player_id == rhs.player_id -// } - -// fn ne(lhs: @@LeaderboardEntry, rhs: @@LeaderboardEntry) -> bool { -// lhs.player_id != rhs.player_id -// } -// } - #[derive(Drop, Serde)] #[dojo::model] @@ -98,7 +68,6 @@ pub struct Leaderboard { } - trait LeaderboardBehavior { // implemented: fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; @@ -160,9 +129,6 @@ impl LeaderboardImpl of LeaderboardTrait { self.last_updated = starknet::get_block_timestamp(); Result::Ok(()) } - - - } From df38edc261f5bcbf15e6752aeed70f00feb0f097 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Thu, 28 Nov 2024 15:47:29 +0100 Subject: [PATCH 05/16] switched Alexandria to 2.6.0 and add good methods --- Scarb.lock | 12 +-- Scarb.toml | 4 +- src/models/leaderboard.cairo | 202 +++++++++++++++++++++++++++-------- 3 files changed, 163 insertions(+), 55 deletions(-) diff --git a/Scarb.lock b/Scarb.lock index 8c1a2e0..35ba7e2 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -4,7 +4,7 @@ version = 1 [[package]] name = "alexandria_data_structures" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_encoding", ] @@ -12,7 +12,7 @@ dependencies = [ [[package]] name = "alexandria_encoding" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_math", "alexandria_numeric", @@ -21,7 +21,7 @@ dependencies = [ [[package]] name = "alexandria_math" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_data_structures", ] @@ -29,7 +29,7 @@ dependencies = [ [[package]] name = "alexandria_numeric" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_math", ] @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "alexandria_searching" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_data_structures", ] @@ -45,7 +45,7 @@ dependencies = [ [[package]] name = "alexandria_sorting" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.5.4#e7b69575f92076e96a83a76efa6bed3c32a15f9f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" dependencies = [ "alexandria_data_structures", ] diff --git a/Scarb.toml b/Scarb.toml index 0b27d87..4b83c61 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -14,7 +14,7 @@ move = "./scripts/move.sh" [dependencies] dojo = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.5" } # Alexandria versions with tag greater that "cairo-v.5.4" conflict with dojo engine -alexandria_searching = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.5.4" } -alexandria_sorting = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.5.4" } +alexandria_searching = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.6.0" } +alexandria_sorting = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.6.0" } [[target.dojo]] diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 79df103..3bf7b30 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -1,11 +1,11 @@ use starknet::ContractAddress; -use alexandria_data_structures::array_ext::ArrayTraitExt; -use alexandria_sorting::bubble_sort::bubble_sort_elements; use core::{ result::Result, option::OptionTrait, array::ArrayTrait }; +use alexandria_data_structures::array_ext::ArrayTraitExt; +use alexandria_sorting::bubble_sort::bubble_sort_elements; const MAX_ENTRIES: usize = 5; @@ -56,6 +56,7 @@ impl LeaderboardEntryPartialEq of PartialEq { } + #[derive(Drop, Serde)] #[dojo::model] pub struct Leaderboard { @@ -68,67 +69,174 @@ pub struct Leaderboard { } -trait LeaderboardBehavior { - // implemented: - fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; - fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; - fn is_full(self: @Leaderboard) -> bool; - // not implemented: - // fn remove_entry(mut self, player_id: ContractAddress); - // fn sort_by_score(mut self); - // fn get_top_n(&self, n: usize) -> Vec; - // fn filter_players(self, filter: LeaderboardFilter) -> Vec; - // fn get_player_rank(self, player_id: ContractAddress) -> Option; - // fn get_summary(&self) -> LeaderboardSummary; - // fn batch_update_entries(mut self, updates: Vec); - // fn save_snapshot(self); - // fn get_snapshot(self, timestamp: u64) -> Option; - // fn merge_leaderboards(mut self, other: Leaderboard); - // fn last_updated_string(self) -> felt252; -} - - #[generate_trait] impl LeaderboardImpl of LeaderboardTrait { - fn add_entry(ref self: Leaderboard, mut entry: LeaderboardEntry) -> Result<(), felt252> { - // look for entry by player_id + // PRIVATE METHODS + + fn pop_front_n(ref self: Leaderboard, mut n: usize) -> Array { + // generic fn pop_front_n of ArrayTraitExt does not work properly, so its my implementation + // only for internal use + let mut res: Array = array![]; + + while (n != 0) { + match self.entries.pop_front() { + Option::Some(e) => { + res.append(e); + n -= 1; + }, + Option::None => { break; }, + }; + }; + + res + } + + fn unsafe_add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { + // adds user entry to leaderboard without sorting let res = self.entries.index_of(entry); if res.is_some() { return Result::Err('Entry already exists'); } self.entries.append(entry); - // Sort array by score - let sorted = bubble_sort_elements(self.entries.clone(), true); - self.entries = sorted; - // Update timestamp self.last_updated = starknet::get_block_timestamp(); Result::Ok(()) } - fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { - // we have to devide array into two parts change the entry and merge them back - // Find entry - let res = self.entries.index_of(entry); - if res.is_none() { - return Result::Err('Entry not found'); - } - let index = res.unwrap(); - let mut left = 0; - if index != 0 { - let mut left = self.entries.pop_front_n(index); - left.append(entry); - let _ = self.entries.pop_front(); - self.entries = left.append_all(ref self.entries); + // PUBLIC METHODS + + fn get_index_by_player_id(ref self: Leaderboard, player_id: u32) -> Result { + let entry = LeaderboardEntry { + player_id: player_id, + player_name: '', + score: 0, + rank: 0, + wins: 0, + losses: 0, + highest_score: 0, + is_active: false, + }; + match self.entries.index_of(entry) { + Option::Some(index) => Result::Ok(index), + Option::None => Result::Err('Entry not found'), } - else { - let mut left = array![entry]; - let _ = self.entries.pop_front(); + } + + + fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { + // adds user entry to leaderboard and sorts internal Array + let res = self.entries.index_of(entry); + if res.is_some() { + return Result::Err('Entry already exists'); } - self.entries = left.append_all(ref self.entries); - // Update entry + self.entries.append(entry); + self.entries = bubble_sort_elements(self.entries, false); self.last_updated = starknet::get_block_timestamp(); Result::Ok(()) } + + fn add_batch(ref self: Leaderboard, mut entries: Array) -> Array { + // adds multiple entries, sorts it and returns array of entries that were not added + let mut not_added: Array = array![]; + let mut res = entries.pop_front(); + while (res.is_some()) { + let entry = res.unwrap(); + match self.unsafe_add_entry(entry) { + Result::Err(_) => { not_added.append(entry); }, + Result::Ok(_) => {}, + }; + res = entries.pop_front(); + }; + self.entries = bubble_sort_elements(self.entries, false); + not_added + } + + fn remove_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { + // removes user entry from leaderboard + match self.entries.index_of(entry) { + Option::Some(index) => { + let mut left = self.pop_front_n(index); + let _ = self.entries.pop_front(); + left.append_all(ref self.entries); + self.entries = left; + Result::Ok(()) + }, + Option::None => Result::Err('Entry not found'), + } + } + + fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { + // updates user entry in leaderboard + match self.remove_entry(entry) { + Result::Ok(_) => { + match self.add_entry(entry) { + Result::Ok(_) => Result::Ok(()), + Result::Err(e) => Result::Err(e) + } + }, + Result::Err(e) => Result::Err(e), + } + } } +#[cfg(test)] +mod tests { + use core::{ + result::{Result, ResultTrait}, + array::ArrayTrait, + }; + use super::{LeaderboardTrait, MAX_ENTRIES}; + use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry}; + use alexandria_data_structures::array_ext::ArrayTraitExt; + use alexandria_sorting::bubble_sort::bubble_sort_elements; + + fn create_mock_entry(player_id: u32, name: felt252, score: u32, wins: u32, losses: u32, highest_score: u32, is_active: bool) -> LeaderboardEntry { + LeaderboardEntry { + player_id: player_id, + player_name: name, + score: score, + rank: 0, + wins: wins, + losses: losses, + highest_score: highest_score, + is_active: is_active, + } + } + + fn create_empty_leaderboard() -> Leaderboard { + Leaderboard { + leaderboard_id: 1, + name: 'Global Leaderboard', + description: 'Top players worldwide', + entries: ArrayTrait::new(), + last_updated: 0, + } + } + #[test] + fn test_add_single_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry = create_mock_entry(1, 'Alice', 100, 10, 5, 100, true); + let res = leaderboard.add_entry(entry); + assert_eq!(res.is_ok(), true); + assert_eq!(leaderboard.entries.len(), 1); + assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong player name"); + + } + + #[test] + fn test_add_multiple_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let entries = array![entry1, entry2, entry3, entry4, entry5]; + let not_added = leaderboard.add_batch(entries); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(not_added.len(), 0, "Wrong number of not added entries"); + assert_eq!(leaderboard.entries.at(0).player_name, @'Bob', "Wrong first player name"); + assert_eq!(leaderboard.entries.at(4).player_name, @'Eve', "Wrong last player name"); + } +} From 992bed6329ba8ada3cce39603c488e299b1d0bde Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Thu, 28 Nov 2024 17:08:35 +0100 Subject: [PATCH 06/16] remove entry test --- src/models/leaderboard.cairo | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 3bf7b30..72eccc9 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -7,13 +7,12 @@ use core::{ use alexandria_data_structures::array_ext::ArrayTraitExt; use alexandria_sorting::bubble_sort::bubble_sort_elements; -const MAX_ENTRIES: usize = 5; #[derive(Copy, Drop, Serde)] #[dojo::model] pub struct LeaderboardEntry { #[key] - pub player_id: u32, // On-chain player address + pub player_id: u32, // player ID pub player_name: felt252, // Display name pub score: u32, // Overall score pub rank: u32, // Rank in the leaderboard @@ -26,12 +25,10 @@ pub struct LeaderboardEntry { //trait for sorting by score impl LeaderboardEntryPartialOrd of PartialOrd { fn le(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { - // less than or equal lhs.score <= rhs.score } fn ge(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { - // greater than or equal lhs.score >= rhs.score } @@ -56,7 +53,6 @@ impl LeaderboardEntryPartialEq of PartialEq { } - #[derive(Drop, Serde)] #[dojo::model] pub struct Leaderboard { @@ -184,7 +180,7 @@ mod tests { result::{Result, ResultTrait}, array::ArrayTrait, }; - use super::{LeaderboardTrait, MAX_ENTRIES}; + use super::{LeaderboardTrait}; use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry}; use alexandria_data_structures::array_ext::ArrayTraitExt; use alexandria_sorting::bubble_sort::bubble_sort_elements; @@ -232,11 +228,30 @@ mod tests { let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + let _ = leaderboard.add_entry(entry4); + let _ = leaderboard.add_entry(entry5); let entries = array![entry1, entry2, entry3, entry4, entry5]; let not_added = leaderboard.add_batch(entries); assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); - assert_eq!(not_added.len(), 0, "Wrong number of not added entries"); + assert_eq!(not_added.len(), 2, "Wrong number of not added entries"); assert_eq!(leaderboard.entries.at(0).player_name, @'Bob', "Wrong first player name"); assert_eq!(leaderboard.entries.at(4).player_name, @'Eve', "Wrong last player name"); } + + #[test] + fn test_remove_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let entries = array![entry1, entry2, entry3, entry4, entry5]; + let _ = leaderboard.add_batch(entries); + let res = leaderboard.remove_entry(entry3); + assert_eq!(res.is_ok(), true); + assert_eq!(leaderboard.entries.len(), 4, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(2).player_name, @'Alice', "Wrong player name"); + } } From ab3f627f5a451a6b2b75656fef2d8fbe5cf93d1e Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 07:32:35 +0100 Subject: [PATCH 07/16] removed an unnecessary dependency --- Scarb.lock | 9 --------- Scarb.toml | 1 - 2 files changed, 10 deletions(-) diff --git a/Scarb.lock b/Scarb.lock index 35ba7e2..0030b4e 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -34,14 +34,6 @@ dependencies = [ "alexandria_math", ] -[[package]] -name = "alexandria_searching" -version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" -dependencies = [ - "alexandria_data_structures", -] - [[package]] name = "alexandria_sorting" version = "0.1.0" @@ -54,7 +46,6 @@ dependencies = [ name = "bytebeasts" version = "0.1.0" dependencies = [ - "alexandria_searching", "alexandria_sorting", "dojo", ] diff --git a/Scarb.toml b/Scarb.toml index 4b83c61..f196a80 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -14,7 +14,6 @@ move = "./scripts/move.sh" [dependencies] dojo = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.5" } # Alexandria versions with tag greater that "cairo-v.5.4" conflict with dojo engine -alexandria_searching = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.6.0" } alexandria_sorting = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.6.0" } [[target.dojo]] From 4df6a6c7e0bfc7e356ffe8d49a1e24551e57974c Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 07:34:14 +0100 Subject: [PATCH 08/16] getter functions and necessary tests with negative scenarious as well --- .../bytebeasts-Leaderboard-7e680376.json | 467 ++++++++++++++++++ .../bytebeasts-LeaderboardEntry-7237950c.json | 441 +++++++++++++++++ .../bytebeasts-Leaderboard-7e680376.toml | 31 ++ .../bytebeasts-LeaderboardEntry-7237950c.toml | 41 ++ src/models/leaderboard.cairo | 165 ++++++- 5 files changed, 1139 insertions(+), 6 deletions(-) create mode 100644 manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json create mode 100644 manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json create mode 100644 manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml create mode 100644 manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml diff --git a/manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json b/manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json new file mode 100644 index 0000000..462aba6 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json @@ -0,0 +1,467 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "leaderboardImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "wins", + "type": "core::integer::u32" + }, + { + "name": "losses", + "type": "core::integer::u32" + }, + { + "name": "highest_score", + "type": "core::integer::u32" + }, + { + "name": "is_active", + "type": "core::bool" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::Leaderboard", + "members": [ + { + "name": "leaderboard_id", + "type": "core::integer::u64" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "description", + "type": "core::felt252" + }, + { + "name": "entries", + "type": "core::array::Array::" + }, + { + "name": "last_updated", + "type": "core::integer::u64" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::leaderboard::Ileaderboard", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::leaderboard::Leaderboard" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::leaderboard::leaderboard::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json b/manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json new file mode 100644 index 0000000..6723d2a --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json @@ -0,0 +1,441 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "leaderboard_entryImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard_entry" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "wins", + "type": "core::integer::u32" + }, + { + "name": "losses", + "type": "core::integer::u32" + }, + { + "name": "highest_score", + "type": "core::integer::u32" + }, + { + "name": "is_active", + "type": "core::bool" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::leaderboard::Ileaderboard_entry", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::leaderboard::LeaderboardEntry" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::leaderboard::leaderboard_entry::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml b/manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml new file mode 100644 index 0000000..b32b775 --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml @@ -0,0 +1,31 @@ +kind = "DojoModel" +class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" +original_class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" +abi = "manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json" +tag = "bytebeasts-Leaderboard" +manifest_name = "bytebeasts-Leaderboard-7e680376" + +[[members]] +name = "leaderboard_id" +type = "u64" +key = true + +[[members]] +name = "name" +type = "felt252" +key = false + +[[members]] +name = "description" +type = "felt252" +key = false + +[[members]] +name = "entries" +type = "Array" +key = false + +[[members]] +name = "last_updated" +type = "u64" +key = false diff --git a/manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml b/manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml new file mode 100644 index 0000000..b460d64 --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml @@ -0,0 +1,41 @@ +kind = "DojoModel" +class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" +original_class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" +abi = "manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json" +tag = "bytebeasts-LeaderboardEntry" +manifest_name = "bytebeasts-LeaderboardEntry-7237950c" + +[[members]] +name = "player_id" +type = "u32" +key = true + +[[members]] +name = "player_name" +type = "felt252" +key = false + +[[members]] +name = "score" +type = "u32" +key = false + +[[members]] +name = "wins" +type = "u32" +key = false + +[[members]] +name = "losses" +type = "u32" +key = false + +[[members]] +name = "highest_score" +type = "u32" +key = false + +[[members]] +name = "is_active" +type = "bool" +key = false diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 72eccc9..c552664 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -15,7 +15,6 @@ pub struct LeaderboardEntry { pub player_id: u32, // player ID pub player_name: felt252, // Display name pub score: u32, // Overall score - pub rank: u32, // Rank in the leaderboard pub wins: u32, // Total wins pub losses: u32, // Total losses pub highest_score: u32, // Highest score in a single game @@ -70,8 +69,9 @@ impl LeaderboardImpl of LeaderboardTrait { // PRIVATE METHODS fn pop_front_n(ref self: Leaderboard, mut n: usize) -> Array { - // generic fn pop_front_n of ArrayTraitExt does not work properly, so its my implementation - // only for internal use + // pops n elements from the front of the array, and returns them + // Alexandria implementation of pop_front_n does not return the popped elements + // in the current version of the library let mut res: Array = array![]; while (n != 0) { @@ -98,14 +98,21 @@ impl LeaderboardImpl of LeaderboardTrait { Result::Ok(()) } + // PUBLIC METHODS + fn get_liderboard_length(ref self: Leaderboard) -> u32 { + // returns number of entries in the leaderboard + self.entries.len() + } + fn get_index_by_player_id(ref self: Leaderboard, player_id: u32) -> Result { + // returns index of entry with given player_id. Index stands for rank in the leaderboard + // player with highest score has index 0 let entry = LeaderboardEntry { player_id: player_id, player_name: '', score: 0, - rank: 0, wins: 0, losses: 0, highest_score: 0, @@ -161,7 +168,7 @@ impl LeaderboardImpl of LeaderboardTrait { } fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { - // updates user entry in leaderboard + // updates user entry in leaderboard, sorts array match self.remove_entry(entry) { Result::Ok(_) => { match self.add_entry(entry) { @@ -172,6 +179,35 @@ impl LeaderboardImpl of LeaderboardTrait { Result::Err(e) => Result::Err(e), } } + + fn get_entries(ref self: Leaderboard) -> Array { + // returns all entries in the leaderboard + self.entries.clone() + } + + fn get_slice(ref self: Leaderboard, start: u32, end: u32) -> Result, felt252> { + // returns entries from start to end (exclusive) + // can be used to get top of the leaderboard + let mut res: Array = array![]; + match self.entries.len() { + 0 => Result::Err('Leaderboard is empty'), + _ => { + if (start >= end) { + return Result::Err('Invalid range'); + } + if (end > self.entries.len()) { + return Result::Err('End index out of bounds'); + } + let mut i = start; + while (i < end) { + res.append(self.entries.at(i).clone()); + i += 1; + }; + Result::Ok(res) + }, + } + } + } #[cfg(test)] @@ -190,7 +226,6 @@ mod tests { player_id: player_id, player_name: name, score: score, - rank: 0, wins: wins, losses: losses, highest_score: highest_score, @@ -217,6 +252,8 @@ mod tests { assert_eq!(leaderboard.entries.len(), 1); assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong player name"); + let duplicate_res = leaderboard.add_entry(entry); + assert_eq!(duplicate_res.is_err(), true, "Duplicate entry should return error"); } #[test] @@ -236,6 +273,29 @@ mod tests { assert_eq!(not_added.len(), 2, "Wrong number of not added entries"); assert_eq!(leaderboard.entries.at(0).player_name, @'Bob', "Wrong first player name"); assert_eq!(leaderboard.entries.at(4).player_name, @'Eve', "Wrong last player name"); + + let duplicate_entries = array![entry1, entry2]; + let not_added_duplicates = leaderboard.add_batch(duplicate_entries); + assert_eq!(not_added_duplicates.len(), 2, "Duplicate entries should not be added"); + } + + #[test] + fn test_pop_front_n() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let _ = leaderboard.add_batch(array![entry1, entry2, entry3]); + let popped_entries = leaderboard.pop_front_n(2); + assert_eq!(popped_entries.len(), 2, "Wrong number of popped entries"); + assert_eq!(popped_entries.at(0).player_name, @'Bob', "Wrong first popped player name"); + assert_eq!(popped_entries.at(1).player_name, @'Charlie', "Wrong second popped player name"); + assert_eq!(leaderboard.entries.len(), 1, "Wrong number of remaining entries"); + assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong remaining player name"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let popped_entries_empty = empty_leaderboard.pop_front_n(5); + assert_eq!(popped_entries_empty.len(), 0, "Popping from empty leaderboard should return empty array"); } #[test] @@ -253,5 +313,98 @@ mod tests { assert_eq!(res.is_ok(), true); assert_eq!(leaderboard.entries.len(), 4, "Wrong number of entries"); assert_eq!(leaderboard.entries.at(2).player_name, @'Alice', "Wrong player name"); + + let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); + let res_non_existent = leaderboard.remove_entry(non_existent_entry); + assert_eq!(res_non_existent.is_err(), true, "Removing non-existent entry should return error"); + } + + #[test] + fn test_get_index_by_player_id() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + assert_eq!(rank, 2, "Wrong rank for Charlie"); + let rank = leaderboard.get_index_by_player_id(2).unwrap(); + assert_eq!(rank, 0, "Wrong rank for Bob"); + let rank = leaderboard.get_index_by_player_id(5).unwrap(); + assert_eq!(rank, 4, "Wrong rank for Eve"); + + let non_existent_rank = leaderboard.get_index_by_player_id(99); + assert_eq!(non_existent_rank.is_err(), true, "Getting index of non-existent player should return error"); + } + + #[test] + fn test_update_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let new_score: u32 = 100; + let new_wins: u32 = 31; + let updated_entry = create_mock_entry(34, 'Charlie', new_score, new_wins, 15, 300, true); + let res = leaderboard.update_entry(updated_entry); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + assert_eq!(res.is_ok(), true); + assert_eq!(rank, 4, "Wrong rank"); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(rank).score, @new_score, "Wrong score"); + assert_eq!(leaderboard.entries.at(rank).wins, @new_wins, "Wrong wins"); + + let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); + let res_non_existent = leaderboard.update_entry(non_existent_entry); + assert_eq!(res_non_existent.is_err(), true, "Updating non-existent entry should return error"); + } + + #[test] + fn test_get_entries() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let _ = leaderboard.add_batch(array![entry1, entry2]); + let entries = leaderboard.get_entries(); + assert_eq!(entries.len(), 2, "Wrong number of entries"); + assert_eq!(entries.at(0).player_name, @'Bob', "Wrong first player name"); + assert_eq!(entries.at(1).player_name, @'Alice', "Wrong second player name"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let entries_empty = empty_leaderboard.get_entries(); + assert_eq!(entries_empty.len(), 0, "Empty leaderboard should return empty array"); + } + + #[test] + fn test_get_slice() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let slice = leaderboard.get_slice(1, 4).unwrap(); + assert_eq!(slice.len(), 3, "Wrong number of entries in slice"); + assert_eq!(slice.at(0).player_name, @'David', "Wrong first player name in slice"); + assert_eq!(slice.at(2).player_name, @'Alice', "Wrong last player name in slice"); + + let invalid_slice = leaderboard.get_slice(4, 1); + assert_eq!(invalid_slice.is_err(), true, "Invalid slice range should return error"); + + let out_of_bounds_slice = leaderboard.get_slice(1, 10); + assert_eq!(out_of_bounds_slice.is_err(), true, "Out of bounds slice should return error"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let empty_slice = empty_leaderboard.get_slice(0, 1); + assert_eq!(empty_slice.is_err(), true, "Empty leaderboard should return error"); } } From 623f6762df30ac18b1f6bdfc7445bdf3618346d1 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 07:54:49 +0100 Subject: [PATCH 09/16] timestamp update in remove_entry function --- src/models/leaderboard.cairo | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index c552664..7518fff 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -161,6 +161,7 @@ impl LeaderboardImpl of LeaderboardTrait { let _ = self.entries.pop_front(); left.append_all(ref self.entries); self.entries = left; + self.last_updated = starknet::get_block_timestamp(); Result::Ok(()) }, Option::None => Result::Err('Entry not found'), From ada590a572402a5ca04b432dab9bc3cf7a9cc99e Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 08:17:06 +0100 Subject: [PATCH 10/16] typo --- src/models/leaderboard.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 7518fff..b3dafb0 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -101,7 +101,7 @@ impl LeaderboardImpl of LeaderboardTrait { // PUBLIC METHODS - fn get_liderboard_length(ref self: Leaderboard) -> u32 { + fn get_leaderboard_length(ref self: Leaderboard) -> u32 { // returns number of entries in the leaderboard self.entries.len() } From f98d1a8f8bf0a6d56b6b8cc940ab8d2b6af28961 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 08:53:48 +0100 Subject: [PATCH 11/16] score calculation --- src/models/leaderboard.cairo | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index b3dafb0..954682c 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -51,6 +51,16 @@ impl LeaderboardEntryPartialEq of PartialEq { } } +#[generate_trait] +impl LeaderboardEntryImpl of LeaderboardEntryTrait { + fn calculate_score (ref self: LeaderboardEntry) -> u32 { + // calculates score based on wins, losses and highest score + self.wins * 100 + self.highest_score - self.losses * 70 + } +} + + + #[derive(Drop, Serde)] #[dojo::model] @@ -106,6 +116,28 @@ impl LeaderboardImpl of LeaderboardTrait { self.entries.len() } + + fn update_entry_stats(ref self: Leaderboard, player_id: u32, new_wins: u32, new_losses: u32, new_highest_score: u32) -> Result<(), felt252> { + // recalculates score and updates entry in the leaderboard + // addning new wins, losses and changing highest score to an old entry + match self.get_index_by_player_id(player_id) { + Result::Ok(index) => { + let mut entry = self.entries.at(index).clone(); + entry.wins += new_wins; + entry.losses += new_losses; + if new_highest_score > entry.highest_score { + entry.highest_score = new_highest_score; + } + entry.score = entry.calculate_score(); + match self.update_entry(entry) { + Result::Ok(_) => Result::Ok(()), + Result::Err(e) => Result::Err(e), + } + }, + Result::Err(e) => Result::Err(e), + } + } + fn get_index_by_player_id(ref self: Leaderboard, player_id: u32) -> Result { // returns index of entry with given player_id. Index stands for rank in the leaderboard // player with highest score has index 0 @@ -181,6 +213,7 @@ impl LeaderboardImpl of LeaderboardTrait { } } + fn get_entries(ref self: Leaderboard) -> Array { // returns all entries in the leaderboard self.entries.clone() @@ -408,4 +441,30 @@ mod tests { let empty_slice = empty_leaderboard.get_slice(0, 1); assert_eq!(empty_slice.is_err(), true, "Empty leaderboard should return error"); } + + #[test] + fn test_update_entry_stats() { + let mut leaderboard = create_empty_leaderboard(); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + let entry3 = create_mock_entry(34, 'Charlie', 2250, 30, 15, 300, true); + let entry1 = create_mock_entry(12, 'Alice', 2400, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let new_wins: u32 = 31; + let new_losses: u32 = 10; + let new_highest_score: u32 = 400; + let res = leaderboard.update_entry_stats(34, new_wins, new_losses, new_highest_score); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + + let total_wins: u32 = entry3.wins + new_wins; + let total_losses: u32 = entry3.losses + new_losses; + assert_eq!(res.is_ok(), true); + assert_eq!(rank, 2, "Wrong rank after update"); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(rank).wins, @total_wins, "Wrong wins"); + assert_eq!(leaderboard.entries.at(rank).losses, @total_losses, "Wrong losses"); + assert_eq!(leaderboard.entries.at(rank).highest_score, @new_highest_score, "Wrong highest score"); + } } From d1508ad382ca40fca7931386f3eeba86be718577 Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Fri, 29 Nov 2024 09:00:10 +0100 Subject: [PATCH 12/16] manifests --- ...bytebeasts-tournament_system-1f2bbf20.json | 383 ++ .../bytebeasts-Tournament-12bdecb1.json | 479 +++ ...bytebeasts-tournament_system-1f2bbf20.toml | 10 + .../bytebeasts-Tournament-12bdecb1.toml | 41 + ...bytebeasts-tournament_system-1f2bbf20.json | 383 ++ .../bytebeasts-Leaderboard-7e680376.json | 467 ++ .../bytebeasts-LeaderboardEntry-7237950c.json | 441 ++ .../bytebeasts-Tournament-12bdecb1.json | 479 +++ manifests/dev/deployment/manifest.json | 3766 +++++++++++++---- manifests/dev/deployment/manifest.toml | 132 + 10 files changed, 5650 insertions(+), 931 deletions(-) create mode 100644 manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json create mode 100644 manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json create mode 100644 manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml create mode 100644 manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml create mode 100644 manifests/dev/deployment/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json create mode 100644 manifests/dev/deployment/abis/models/bytebeasts-Leaderboard-7e680376.json create mode 100644 manifests/dev/deployment/abis/models/bytebeasts-LeaderboardEntry-7237950c.json create mode 100644 manifests/dev/deployment/abis/models/bytebeasts-Tournament-12bdecb1.json diff --git a/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json b/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json new file mode 100644 index 0000000..2d4cb03 --- /dev/null +++ b/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json @@ -0,0 +1,383 @@ +[ + { + "type": "impl", + "name": "ContractImpl", + "interface_name": "dojo::contract::contract::IContract" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo::contract::contract::IContract", + "items": [ + { + "type": "function", + "name": "contract_name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::world_contract::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::world_contract::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::world_contract::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::world_contract::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "TournamentActionImpl", + "interface_name": "bytebeasts::systems::tournament::ITournamentAction" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::player::Player", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::systems::tournament::ITournamentAction", + "items": [ + { + "type": "function", + "name": "create_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "register_player", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "new_player", + "type": "bytebeasts::models::player::Player" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "start_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], + "outputs": [ + { + "type": "bytebeasts::models::tournament::Tournament" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "bytebeasts::systems::tournament::tournament_system::IDojoInit" + }, + { + "type": "interface", + "name": "bytebeasts::systems::tournament::tournament_system::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::contract::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::contract::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::systems::tournament::tournament_system::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json b/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json new file mode 100644 index 0000000..73bd005 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json @@ -0,0 +1,479 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "tournamentImpl", + "interface_name": "bytebeasts::models::tournament::Itournament" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::player::Player", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::tournament::Itournament", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::tournament::Tournament" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::tournament::tournament::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml b/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml new file mode 100644 index 0000000..e288571 --- /dev/null +++ b/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml @@ -0,0 +1,10 @@ +kind = "DojoContract" +class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" +original_class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" +base_class_hash = "0x0" +abi = "manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json" +reads = [] +writes = [] +init_calldata = [] +tag = "bytebeasts-tournament_system" +manifest_name = "bytebeasts-tournament_system-1f2bbf20" diff --git a/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml b/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml new file mode 100644 index 0000000..417660e --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml @@ -0,0 +1,41 @@ +kind = "DojoModel" +class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" +original_class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" +abi = "manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json" +tag = "bytebeasts-Tournament" +manifest_name = "bytebeasts-Tournament-12bdecb1" + +[[members]] +name = "tournament_id" +type = "u32" +key = true + +[[members]] +name = "name" +type = "felt252" +key = false + +[[members]] +name = "status" +type = "TournamentStatus" +key = false + +[[members]] +name = "entry_fee" +type = "u32" +key = false + +[[members]] +name = "max_participants" +type = "u32" +key = false + +[[members]] +name = "current_participants" +type = "Array" +key = false + +[[members]] +name = "prize_pool" +type = "u32" +key = false diff --git a/manifests/dev/deployment/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json b/manifests/dev/deployment/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json new file mode 100644 index 0000000..2d4cb03 --- /dev/null +++ b/manifests/dev/deployment/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json @@ -0,0 +1,383 @@ +[ + { + "type": "impl", + "name": "ContractImpl", + "interface_name": "dojo::contract::contract::IContract" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo::contract::contract::IContract", + "items": [ + { + "type": "function", + "name": "contract_name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::world_contract::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::world_contract::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::world_contract::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::world_contract::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "TournamentActionImpl", + "interface_name": "bytebeasts::systems::tournament::ITournamentAction" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::player::Player", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::systems::tournament::ITournamentAction", + "items": [ + { + "type": "function", + "name": "create_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "register_player", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "new_player", + "type": "bytebeasts::models::player::Player" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "start_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], + "outputs": [ + { + "type": "bytebeasts::models::tournament::Tournament" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "bytebeasts::systems::tournament::tournament_system::IDojoInit" + }, + { + "type": "interface", + "name": "bytebeasts::systems::tournament::tournament_system::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::contract::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::contract::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::systems::tournament::tournament_system::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/manifests/dev/deployment/abis/models/bytebeasts-Leaderboard-7e680376.json b/manifests/dev/deployment/abis/models/bytebeasts-Leaderboard-7e680376.json new file mode 100644 index 0000000..462aba6 --- /dev/null +++ b/manifests/dev/deployment/abis/models/bytebeasts-Leaderboard-7e680376.json @@ -0,0 +1,467 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "leaderboardImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "wins", + "type": "core::integer::u32" + }, + { + "name": "losses", + "type": "core::integer::u32" + }, + { + "name": "highest_score", + "type": "core::integer::u32" + }, + { + "name": "is_active", + "type": "core::bool" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::Leaderboard", + "members": [ + { + "name": "leaderboard_id", + "type": "core::integer::u64" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "description", + "type": "core::felt252" + }, + { + "name": "entries", + "type": "core::array::Array::" + }, + { + "name": "last_updated", + "type": "core::integer::u64" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::leaderboard::Ileaderboard", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::leaderboard::Leaderboard" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::leaderboard::leaderboard::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/deployment/abis/models/bytebeasts-LeaderboardEntry-7237950c.json b/manifests/dev/deployment/abis/models/bytebeasts-LeaderboardEntry-7237950c.json new file mode 100644 index 0000000..6723d2a --- /dev/null +++ b/manifests/dev/deployment/abis/models/bytebeasts-LeaderboardEntry-7237950c.json @@ -0,0 +1,441 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "leaderboard_entryImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard_entry" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "wins", + "type": "core::integer::u32" + }, + { + "name": "losses", + "type": "core::integer::u32" + }, + { + "name": "highest_score", + "type": "core::integer::u32" + }, + { + "name": "is_active", + "type": "core::bool" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::leaderboard::Ileaderboard_entry", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::leaderboard::LeaderboardEntry" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::leaderboard::leaderboard_entry::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/deployment/abis/models/bytebeasts-Tournament-12bdecb1.json b/manifests/dev/deployment/abis/models/bytebeasts-Tournament-12bdecb1.json new file mode 100644 index 0000000..73bd005 --- /dev/null +++ b/manifests/dev/deployment/abis/models/bytebeasts-Tournament-12bdecb1.json @@ -0,0 +1,479 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "tournamentImpl", + "interface_name": "bytebeasts::models::tournament::Itournament" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::player::Player", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::tournament::Itournament", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::tournament::Tournament" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::tournament::tournament::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/deployment/manifest.json b/manifests/dev/deployment/manifest.json index 5647cd5..fb19fa0 100644 --- a/manifests/dev/deployment/manifest.json +++ b/manifests/dev/deployment/manifest.json @@ -2861,9 +2861,9 @@ }, { "kind": "DojoContract", - "address": "0x1a0997571ba63300bba592512cc9ac1daa8911ee08c049b5693d93c06377d25", - "class_hash": "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880", - "original_class_hash": "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880", + "address": "0x2671b8a136f1441cbd5fb6d3d9c5bdc45a3fbf184970b334cfd31ed98cf0b69", + "class_hash": "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7", + "original_class_hash": "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7", "base_class_hash": "0x2427dd10a58850ac9a5ca6ce04b7771b05330fd18f2e481831ad903b969e6b2", "abi": [ { @@ -2995,30 +2995,189 @@ }, { "type": "impl", - "name": "WorldSetupImpl", - "interface_name": "bytebeasts::systems::world_setup::IWorldSetup" + "name": "TournamentActionImpl", + "interface_name": "bytebeasts::systems::tournament::ITournamentAction" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::player::Player", + "members": [ + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ] }, { "type": "interface", - "name": "bytebeasts::systems::world_setup::IWorldSetup", + "name": "bytebeasts::systems::tournament::ITournamentAction", "items": [ { "type": "function", - "name": "setWorld", - "inputs": [], + "name": "create_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "register_player", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "new_player", + "type": "bytebeasts::models::player::Player" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "start_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], "outputs": [], "state_mutability": "external" + }, + { + "type": "function", + "name": "get_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + } + ], + "outputs": [ + { + "type": "bytebeasts::models::tournament::Tournament" + } + ], + "state_mutability": "view" } ] }, { "type": "impl", "name": "IDojoInitImpl", - "interface_name": "bytebeasts::systems::world_setup::world_setup::IDojoInit" + "interface_name": "bytebeasts::systems::tournament::tournament_system::IDojoInit" }, { "type": "interface", - "name": "bytebeasts::systems::world_setup::world_setup::IDojoInit", + "name": "bytebeasts::systems::tournament::tournament_system::IDojoInit", "items": [ { "type": "function", @@ -3065,85 +3224,1802 @@ ] }, { - "type": "event", - "name": "dojo::contract::upgradeable::upgradeable::Event", - "kind": "enum", - "variants": [ + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::systems::tournament::tournament_system::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [], + "init_calldata": [], + "tag": "bytebeasts-tournament_system", + "manifest_name": "bytebeasts-tournament_system-1f2bbf20" + }, + { + "kind": "DojoContract", + "address": "0x1a0997571ba63300bba592512cc9ac1daa8911ee08c049b5693d93c06377d25", + "class_hash": "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880", + "original_class_hash": "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880", + "base_class_hash": "0x2427dd10a58850ac9a5ca6ce04b7771b05330fd18f2e481831ad903b969e6b2", + "abi": [ + { + "type": "impl", + "name": "ContractImpl", + "interface_name": "dojo::contract::contract::IContract" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo::contract::contract::IContract", + "items": [ + { + "type": "function", + "name": "contract_name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::world_contract::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::world_contract::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::world_contract::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::world_contract::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldSetupImpl", + "interface_name": "bytebeasts::systems::world_setup::IWorldSetup" + }, + { + "type": "interface", + "name": "bytebeasts::systems::world_setup::IWorldSetup", + "items": [ + { + "type": "function", + "name": "setWorld", + "inputs": [], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "bytebeasts::systems::world_setup::world_setup::IDojoInit" + }, + { + "type": "interface", + "name": "bytebeasts::systems::world_setup::world_setup::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::contract::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::contract::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::contract::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::systems::world_setup::world_setup::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::contract::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [ + "bytebeasts-Beast", + "bytebeasts-Mt", + "bytebeasts-Player", + "bytebeasts-Potion", + "bytebeasts-Position" + ], + "init_calldata": [], + "tag": "bytebeasts-world_setup", + "manifest_name": "bytebeasts-world_setup-674b640b" + } + ], + "models": [ + { + "kind": "DojoModel", + "members": [ + { + "name": "achievement_id", + "type": "u64", + "key": true + }, + { + "name": "achievement_type", + "type": "AchievementType", + "key": false + }, + { + "name": "rarity", + "type": "AchievementRarity", + "key": false + }, + { + "name": "name", + "type": "felt252", + "key": false + }, + { + "name": "description", + "type": "ByteArray", + "key": false + }, + { + "name": "is_hidden", + "type": "bool", + "key": false + }, + { + "name": "is_unlocked", + "type": "bool", + "key": false + } + ], + "class_hash": "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40", + "original_class_hash": "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "achievementImpl", + "interface_name": "bytebeasts::models::achievements::Iachievement" + }, + { + "type": "enum", + "name": "bytebeasts::models::achievement_type::AchievementType", + "variants": [ + { + "name": "FirstWin", + "type": "()" + }, + { + "name": "TenWins", + "type": "()" + }, + { + "name": "HundredWins", + "type": "()" + }, + { + "name": "FirstBeast", + "type": "()" + }, + { + "name": "TenBeasts", + "type": "()" + }, + { + "name": "RareBeast", + "type": "()" + }, + { + "name": "FirstNPCInteraction", + "type": "()" + }, + { + "name": "RandomBattleChampion", + "type": "()" + }, + { + "name": "BeastMaster", + "type": "()" + }, + { + "name": "LegendaryPlayer", + "type": "()" + }, + { + "name": "TopScorer", + "type": "()" + } + ] + }, + { + "type": "enum", + "name": "bytebeasts::models::achievement_rarity::AchievementRarity", + "variants": [ + { + "name": "Common", + "type": "()" + }, + { + "name": "Uncommon", + "type": "()" + }, + { + "name": "Rare", + "type": "()" + }, + { + "name": "Epic", + "type": "()" + }, + { + "name": "Legendary", + "type": "()" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::achievements::Achievement", + "members": [ + { + "name": "achievement_id", + "type": "core::integer::u64" + }, + { + "name": "achievement_type", + "type": "bytebeasts::models::achievement_type::AchievementType" + }, + { + "name": "rarity", + "type": "bytebeasts::models::achievement_rarity::AchievementRarity" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "description", + "type": "core::byte_array::ByteArray" + }, + { + "name": "is_hidden", + "type": "core::bool" + }, + { + "name": "is_unlocked", + "type": "core::bool" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::achievements::Iachievement", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::achievements::Achievement" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::achievements::achievement::Event", + "kind": "enum", + "variants": [] + } + ], + "tag": "bytebeasts-Achievement", + "manifest_name": "bytebeasts-Achievement-58a03b97" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "player_id", + "type": "u64", + "key": true + }, + { + "name": "achievement_id", + "type": "u64", + "key": false + }, + { + "name": "progress", + "type": "u32", + "key": false + }, + { + "name": "is_unlocked", + "type": "bool", + "key": false + } + ], + "class_hash": "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15", + "original_class_hash": "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "achievement_progressImpl", + "interface_name": "bytebeasts::models::achievements::Iachievement_progress" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::achievements::AchievementProgress", + "members": [ + { + "name": "player_id", + "type": "core::integer::u64" + }, + { + "name": "achievement_id", + "type": "core::integer::u64" + }, + { + "name": "progress", + "type": "core::integer::u32" + }, + { + "name": "is_unlocked", + "type": "core::bool" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::achievements::Iachievement_progress", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::achievements::AchievementProgress" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::achievements::achievement_progress::Event", + "kind": "enum", + "variants": [] + } + ], + "tag": "bytebeasts-AchievementProgress", + "manifest_name": "bytebeasts-AchievementProgress-221f2719" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "bag_id", + "type": "u32", + "key": true + }, + { + "name": "player_id", + "type": "u32", + "key": true + }, + { + "name": "max_capacity", + "type": "u32", + "key": false + }, + { + "name": "potions", + "type": "Array", + "key": false + } + ], + "class_hash": "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c", + "original_class_hash": "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "bagImpl", + "interface_name": "bytebeasts::models::bag::Ibag" + }, + { + "type": "struct", + "name": "bytebeasts::models::potion::Potion", + "members": [ + { + "name": "potion_id", + "type": "core::integer::u32" + }, + { + "name": "potion_name", + "type": "core::felt252" + }, + { + "name": "potion_effect", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::bag::Bag", + "members": [ + { + "name": "bag_id", + "type": "core::integer::u32" + }, + { + "name": "player_id", + "type": "core::integer::u32" + }, + { + "name": "max_capacity", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::array::Array::" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::bag::Ibag", + "items": [ { - "name": "Upgraded", - "type": "dojo::contract::upgradeable::upgradeable::Upgraded", - "kind": "nested" + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::bag::Bag" + } + ], + "outputs": [], + "state_mutability": "view" } ] }, { "type": "event", - "name": "bytebeasts::systems::world_setup::world_setup::Event", + "name": "bytebeasts::models::bag::bag::Event", "kind": "enum", - "variants": [ - { - "name": "UpgradeableEvent", - "type": "dojo::contract::upgradeable::upgradeable::Event", - "kind": "nested" - } - ] + "variants": [] } ], - "reads": [], - "writes": [ - "bytebeasts-Beast", - "bytebeasts-Mt", - "bytebeasts-Player", - "bytebeasts-Potion", - "bytebeasts-Position" - ], - "init_calldata": [], - "tag": "bytebeasts-world_setup", - "manifest_name": "bytebeasts-world_setup-674b640b" - } - ], - "models": [ + "tag": "bytebeasts-Bag", + "manifest_name": "bytebeasts-Bag-2571b77d" + }, { "kind": "DojoModel", "members": [ { - "name": "achievement_id", - "type": "u64", + "name": "battle_id", + "type": "u32", "key": true }, { - "name": "achievement_type", - "type": "AchievementType", + "name": "player_id", + "type": "u32", "key": false }, { - "name": "rarity", - "type": "AchievementRarity", + "name": "opponent_id", + "type": "u32", "key": false }, { - "name": "name", - "type": "felt252", + "name": "active_beast_player", + "type": "u32", "key": false }, { - "name": "description", - "type": "ByteArray", + "name": "active_beast_opponent", + "type": "u32", "key": false }, { - "name": "is_hidden", - "type": "bool", + "name": "battle_active", + "type": "u32", "key": false }, { - "name": "is_unlocked", - "type": "bool", + "name": "turn", + "type": "u32", "key": false } ], - "class_hash": "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40", - "original_class_hash": "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40", + "class_hash": "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32", + "original_class_hash": "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32", "abi": [ { "type": "impl", @@ -3509,187 +5385,152 @@ }, { "type": "impl", - "name": "achievementImpl", - "interface_name": "bytebeasts::models::achievements::Iachievement" + "name": "battleImpl", + "interface_name": "bytebeasts::models::battle::Ibattle" }, { - "type": "enum", - "name": "bytebeasts::models::achievement_type::AchievementType", - "variants": [ - { - "name": "FirstWin", - "type": "()" - }, - { - "name": "TenWins", - "type": "()" - }, - { - "name": "HundredWins", - "type": "()" - }, - { - "name": "FirstBeast", - "type": "()" - }, + "type": "struct", + "name": "bytebeasts::models::battle::Battle", + "members": [ { - "name": "TenBeasts", - "type": "()" + "name": "battle_id", + "type": "core::integer::u32" }, { - "name": "RareBeast", - "type": "()" + "name": "player_id", + "type": "core::integer::u32" }, { - "name": "FirstNPCInteraction", - "type": "()" + "name": "opponent_id", + "type": "core::integer::u32" }, { - "name": "RandomBattleChampion", - "type": "()" + "name": "active_beast_player", + "type": "core::integer::u32" }, { - "name": "BeastMaster", - "type": "()" + "name": "active_beast_opponent", + "type": "core::integer::u32" }, { - "name": "LegendaryPlayer", - "type": "()" + "name": "battle_active", + "type": "core::integer::u32" }, { - "name": "TopScorer", - "type": "()" + "name": "turn", + "type": "core::integer::u32" } ] }, { - "type": "enum", - "name": "bytebeasts::models::achievement_rarity::AchievementRarity", - "variants": [ - { - "name": "Common", - "type": "()" - }, - { - "name": "Uncommon", - "type": "()" - }, - { - "name": "Rare", - "type": "()" - }, - { - "name": "Epic", - "type": "()" - }, + "type": "interface", + "name": "bytebeasts::models::battle::Ibattle", + "items": [ { - "name": "Legendary", - "type": "()" + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::battle::Battle" + } + ], + "outputs": [], + "state_mutability": "view" } ] }, { - "type": "enum", - "name": "core::bool", - "variants": [ - { - "name": "False", - "type": "()" - }, - { - "name": "True", - "type": "()" - } - ] + "type": "event", + "name": "bytebeasts::models::battle::battle::Event", + "kind": "enum", + "variants": [] + } + ], + "tag": "bytebeasts-Battle", + "manifest_name": "bytebeasts-Battle-55b5860b" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "beast_id", + "type": "u32", + "key": true }, { - "type": "struct", - "name": "bytebeasts::models::achievements::Achievement", - "members": [ - { - "name": "achievement_id", - "type": "core::integer::u64" - }, - { - "name": "achievement_type", - "type": "bytebeasts::models::achievement_type::AchievementType" - }, - { - "name": "rarity", - "type": "bytebeasts::models::achievement_rarity::AchievementRarity" - }, - { - "name": "name", - "type": "core::felt252" - }, - { - "name": "description", - "type": "core::byte_array::ByteArray" - }, - { - "name": "is_hidden", - "type": "core::bool" - }, - { - "name": "is_unlocked", - "type": "core::bool" - } - ] + "name": "beast_name", + "type": "felt252", + "key": false + }, + { + "name": "beast_type", + "type": "WorldElements", + "key": false + }, + { + "name": "beast_description", + "type": "felt252", + "key": false + }, + { + "name": "player_id", + "type": "u32", + "key": false + }, + { + "name": "hp", + "type": "u32", + "key": false + }, + { + "name": "current_hp", + "type": "u32", + "key": false + }, + { + "name": "attack", + "type": "u32", + "key": false }, { - "type": "interface", - "name": "bytebeasts::models::achievements::Iachievement", - "items": [ - { - "type": "function", - "name": "ensure_abi", - "inputs": [ - { - "name": "model", - "type": "bytebeasts::models::achievements::Achievement" - } - ], - "outputs": [], - "state_mutability": "view" - } - ] + "name": "defense", + "type": "u32", + "key": false }, { - "type": "event", - "name": "bytebeasts::models::achievements::achievement::Event", - "kind": "enum", - "variants": [] - } - ], - "tag": "bytebeasts-Achievement", - "manifest_name": "bytebeasts-Achievement-58a03b97" - }, - { - "kind": "DojoModel", - "members": [ + "name": "mt1", + "type": "u32", + "key": false + }, { - "name": "player_id", - "type": "u64", - "key": true + "name": "mt2", + "type": "u32", + "key": false }, { - "name": "achievement_id", - "type": "u64", + "name": "mt3", + "type": "u32", "key": false }, { - "name": "progress", + "name": "mt4", "type": "u32", "key": false }, { - "name": "is_unlocked", - "type": "bool", + "name": "level", + "type": "u32", + "key": false + }, + { + "name": "experience_to_next_level", + "type": "u64", "key": false } ], - "class_hash": "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15", - "original_class_hash": "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15", + "class_hash": "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c", + "original_class_hash": "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c", "abi": [ { "type": "impl", @@ -4055,48 +5896,104 @@ }, { "type": "impl", - "name": "achievement_progressImpl", - "interface_name": "bytebeasts::models::achievements::Iachievement_progress" + "name": "beastImpl", + "interface_name": "bytebeasts::models::beast::Ibeast" }, { "type": "enum", - "name": "core::bool", + "name": "bytebeasts::models::world_elements::WorldElements", "variants": [ { - "name": "False", + "name": "Crystal", "type": "()" }, { - "name": "True", + "name": "Draconic", + "type": "()" + }, + { + "name": "Shadow", + "type": "()" + }, + { + "name": "Light", + "type": "()" + }, + { + "name": "Titanium", "type": "()" } ] }, { "type": "struct", - "name": "bytebeasts::models::achievements::AchievementProgress", + "name": "bytebeasts::models::beast::Beast", "members": [ + { + "name": "beast_id", + "type": "core::integer::u32" + }, + { + "name": "beast_name", + "type": "core::felt252" + }, + { + "name": "beast_type", + "type": "bytebeasts::models::world_elements::WorldElements" + }, + { + "name": "beast_description", + "type": "core::felt252" + }, { "name": "player_id", - "type": "core::integer::u64" + "type": "core::integer::u32" }, { - "name": "achievement_id", - "type": "core::integer::u64" + "name": "hp", + "type": "core::integer::u32" }, { - "name": "progress", + "name": "current_hp", "type": "core::integer::u32" }, { - "name": "is_unlocked", - "type": "core::bool" + "name": "attack", + "type": "core::integer::u32" + }, + { + "name": "defense", + "type": "core::integer::u32" + }, + { + "name": "mt1", + "type": "core::integer::u32" + }, + { + "name": "mt2", + "type": "core::integer::u32" + }, + { + "name": "mt3", + "type": "core::integer::u32" + }, + { + "name": "mt4", + "type": "core::integer::u32" + }, + { + "name": "level", + "type": "core::integer::u32" + }, + { + "name": "experience_to_next_level", + "type": "core::integer::u64" } ] }, { "type": "interface", - "name": "bytebeasts::models::achievements::Iachievement_progress", + "name": "bytebeasts::models::beast::Ibeast", "items": [ { "type": "function", @@ -4104,7 +6001,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::achievements::AchievementProgress" + "type": "bytebeasts::models::beast::Beast" } ], "outputs": [], @@ -4114,40 +6011,55 @@ }, { "type": "event", - "name": "bytebeasts::models::achievements::achievement_progress::Event", + "name": "bytebeasts::models::beast::beast::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-AchievementProgress", - "manifest_name": "bytebeasts-AchievementProgress-221f2719" + "tag": "bytebeasts-Beast", + "manifest_name": "bytebeasts-Beast-27809d20" }, { "kind": "DojoModel", "members": [ { - "name": "bag_id", - "type": "u32", + "name": "game_id", + "type": "u128", "key": true }, { - "name": "player_id", - "type": "u32", - "key": true + "name": "player_1", + "type": "ContractAddress", + "key": false }, { - "name": "max_capacity", - "type": "u32", + "name": "player_2", + "type": "ContractAddress", "key": false }, { - "name": "potions", - "type": "Array", + "name": "player_3", + "type": "ContractAddress", + "key": false + }, + { + "name": "player_4", + "type": "ContractAddress", + "key": false + }, + { + "name": "status", + "type": "GameStatus", + "key": false + }, + { + "name": "is_private", + "type": "bool", "key": false } ], - "class_hash": "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c", - "original_class_hash": "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c", + "class_hash": "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764", + "original_class_hash": "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764", "abi": [ { "type": "impl", @@ -4513,52 +6425,78 @@ }, { "type": "impl", - "name": "bagImpl", - "interface_name": "bytebeasts::models::bag::Ibag" + "name": "gameImpl", + "interface_name": "bytebeasts::models::game::Igame" }, { - "type": "struct", - "name": "bytebeasts::models::potion::Potion", - "members": [ + "type": "enum", + "name": "bytebeasts::models::game::GameStatus", + "variants": [ { - "name": "potion_id", - "type": "core::integer::u32" + "name": "Pending", + "type": "()" }, { - "name": "potion_name", - "type": "core::felt252" + "name": "InProgress", + "type": "()" }, { - "name": "potion_effect", - "type": "core::integer::u32" + "name": "Finished", + "type": "()" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" } ] }, { "type": "struct", - "name": "bytebeasts::models::bag::Bag", + "name": "bytebeasts::models::game::Game", "members": [ { - "name": "bag_id", - "type": "core::integer::u32" + "name": "game_id", + "type": "core::integer::u128" }, { - "name": "player_id", - "type": "core::integer::u32" + "name": "player_1", + "type": "core::starknet::contract_address::ContractAddress" }, { - "name": "max_capacity", - "type": "core::integer::u32" + "name": "player_2", + "type": "core::starknet::contract_address::ContractAddress" }, { - "name": "potions", - "type": "core::array::Array::" + "name": "player_3", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "player_4", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "status", + "type": "bytebeasts::models::game::GameStatus" + }, + { + "name": "is_private", + "type": "core::bool" } ] }, { "type": "interface", - "name": "bytebeasts::models::bag::Ibag", + "name": "bytebeasts::models::game::Igame", "items": [ { "type": "function", @@ -4566,7 +6504,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::bag::Bag" + "type": "bytebeasts::models::game::Game" } ], "outputs": [], @@ -4576,55 +6514,30 @@ }, { "type": "event", - "name": "bytebeasts::models::bag::bag::Event", + "name": "bytebeasts::models::game::game::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Bag", - "manifest_name": "bytebeasts-Bag-2571b77d" + "tag": "bytebeasts-Game", + "manifest_name": "bytebeasts-Game-e91217d7" }, { "kind": "DojoModel", "members": [ { - "name": "battle_id", + "name": "id", "type": "u32", "key": true }, { - "name": "player_id", - "type": "u32", - "key": false - }, - { - "name": "opponent_id", - "type": "u32", - "key": false - }, - { - "name": "active_beast_player", - "type": "u32", - "key": false - }, - { - "name": "active_beast_opponent", - "type": "u32", - "key": false - }, - { - "name": "battle_active", - "type": "u32", - "key": false - }, - { - "name": "turn", - "type": "u32", + "name": "game_id", + "type": "u128", "key": false } ], - "class_hash": "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32", - "original_class_hash": "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32", + "class_hash": "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe", + "original_class_hash": "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe", "abi": [ { "type": "impl", @@ -4990,46 +6903,26 @@ }, { "type": "impl", - "name": "battleImpl", - "interface_name": "bytebeasts::models::battle::Ibattle" + "name": "game_idImpl", + "interface_name": "bytebeasts::models::game_id::Igame_id" }, { "type": "struct", - "name": "bytebeasts::models::battle::Battle", + "name": "bytebeasts::models::game_id::GameId", "members": [ { - "name": "battle_id", - "type": "core::integer::u32" - }, - { - "name": "player_id", - "type": "core::integer::u32" - }, - { - "name": "opponent_id", - "type": "core::integer::u32" - }, - { - "name": "active_beast_player", - "type": "core::integer::u32" - }, - { - "name": "active_beast_opponent", - "type": "core::integer::u32" - }, - { - "name": "battle_active", + "name": "id", "type": "core::integer::u32" }, { - "name": "turn", - "type": "core::integer::u32" + "name": "game_id", + "type": "core::integer::u128" } ] }, { "type": "interface", - "name": "bytebeasts::models::battle::Ibattle", + "name": "bytebeasts::models::game_id::Igame_id", "items": [ { "type": "function", @@ -5037,7 +6930,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::battle::Battle" + "type": "bytebeasts::models::game_id::GameId" } ], "outputs": [], @@ -5047,95 +6940,70 @@ }, { "type": "event", - "name": "bytebeasts::models::battle::battle::Event", + "name": "bytebeasts::models::game_id::game_id::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Battle", - "manifest_name": "bytebeasts-Battle-55b5860b" + "tag": "bytebeasts-GameId", + "manifest_name": "bytebeasts-GameId-344511d3" }, { "kind": "DojoModel", "members": [ { - "name": "beast_id", - "type": "u32", + "name": "address", + "type": "ContractAddress", "key": true }, { - "name": "beast_name", - "type": "felt252", - "key": false - }, - { - "name": "beast_type", - "type": "WorldElements", - "key": false - }, - { - "name": "beast_description", - "type": "felt252", - "key": false - }, - { - "name": "player_id", - "type": "u32", - "key": false - }, - { - "name": "hp", - "type": "u32", - "key": false - }, - { - "name": "current_hp", - "type": "u32", - "key": false + "name": "game_id", + "type": "u128", + "key": true }, { - "name": "attack", - "type": "u32", + "name": "beast_1", + "type": "u8", "key": false }, { - "name": "defense", - "type": "u32", + "name": "beast_2", + "type": "u8", "key": false }, { - "name": "mt1", - "type": "u32", + "name": "beast_3", + "type": "u8", "key": false }, { - "name": "mt2", - "type": "u32", + "name": "beast_4", + "type": "u8", "key": false }, { - "name": "mt3", - "type": "u32", + "name": "bag_id", + "type": "u8", "key": false }, { - "name": "mt4", - "type": "u32", + "name": "active_mount", + "type": "u8", "key": false }, { - "name": "level", - "type": "u32", + "name": "mounts", + "type": "Array", "key": false }, { - "name": "experience_to_next_level", - "type": "u64", + "name": "position", + "type": "Array", "key": false } ], - "class_hash": "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c", - "original_class_hash": "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c", + "class_hash": "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18", + "original_class_hash": "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18", "abi": [ { "type": "impl", @@ -5501,104 +7369,58 @@ }, { "type": "impl", - "name": "beastImpl", - "interface_name": "bytebeasts::models::beast::Ibeast" - }, - { - "type": "enum", - "name": "bytebeasts::models::world_elements::WorldElements", - "variants": [ - { - "name": "Crystal", - "type": "()" - }, - { - "name": "Draconic", - "type": "()" - }, - { - "name": "Shadow", - "type": "()" - }, - { - "name": "Light", - "type": "()" - }, - { - "name": "Titanium", - "type": "()" - } - ] + "name": "game_playerImpl", + "interface_name": "bytebeasts::models::game_player::Igame_player" }, { "type": "struct", - "name": "bytebeasts::models::beast::Beast", + "name": "bytebeasts::models::game_player::GamePlayer", "members": [ { - "name": "beast_id", - "type": "core::integer::u32" - }, - { - "name": "beast_name", - "type": "core::felt252" - }, - { - "name": "beast_type", - "type": "bytebeasts::models::world_elements::WorldElements" - }, - { - "name": "beast_description", - "type": "core::felt252" - }, - { - "name": "player_id", - "type": "core::integer::u32" - }, - { - "name": "hp", - "type": "core::integer::u32" + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" }, { - "name": "current_hp", - "type": "core::integer::u32" + "name": "game_id", + "type": "core::integer::u128" }, { - "name": "attack", - "type": "core::integer::u32" + "name": "beast_1", + "type": "core::integer::u8" }, { - "name": "defense", - "type": "core::integer::u32" + "name": "beast_2", + "type": "core::integer::u8" }, { - "name": "mt1", - "type": "core::integer::u32" + "name": "beast_3", + "type": "core::integer::u8" }, { - "name": "mt2", - "type": "core::integer::u32" + "name": "beast_4", + "type": "core::integer::u8" }, { - "name": "mt3", - "type": "core::integer::u32" + "name": "bag_id", + "type": "core::integer::u8" }, { - "name": "mt4", - "type": "core::integer::u32" + "name": "active_mount", + "type": "core::integer::u8" }, { - "name": "level", - "type": "core::integer::u32" + "name": "mounts", + "type": "core::array::Array::" }, { - "name": "experience_to_next_level", - "type": "core::integer::u64" + "name": "position", + "type": "core::array::Array::" } ] }, { "type": "interface", - "name": "bytebeasts::models::beast::Ibeast", + "name": "bytebeasts::models::game_player::Igame_player", "items": [ { "type": "function", @@ -5606,7 +7428,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::beast::Beast" + "type": "bytebeasts::models::game_player::GamePlayer" } ], "outputs": [], @@ -5616,55 +7438,45 @@ }, { "type": "event", - "name": "bytebeasts::models::beast::beast::Event", + "name": "bytebeasts::models::game_player::game_player::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Beast", - "manifest_name": "bytebeasts-Beast-27809d20" + "tag": "bytebeasts-GamePlayer", + "manifest_name": "bytebeasts-GamePlayer-596ef4a1" }, { "kind": "DojoModel", "members": [ { - "name": "game_id", - "type": "u128", + "name": "leaderboard_id", + "type": "u64", "key": true }, { - "name": "player_1", - "type": "ContractAddress", - "key": false - }, - { - "name": "player_2", - "type": "ContractAddress", - "key": false - }, - { - "name": "player_3", - "type": "ContractAddress", + "name": "name", + "type": "felt252", "key": false }, { - "name": "player_4", - "type": "ContractAddress", + "name": "description", + "type": "felt252", "key": false }, { - "name": "status", - "type": "GameStatus", + "name": "entries", + "type": "Array", "key": false }, { - "name": "is_private", - "type": "bool", + "name": "last_updated", + "type": "u64", "key": false } ], - "class_hash": "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764", - "original_class_hash": "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764", + "class_hash": "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0", + "original_class_hash": "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0", "abi": [ { "type": "impl", @@ -6030,26 +7842,8 @@ }, { "type": "impl", - "name": "gameImpl", - "interface_name": "bytebeasts::models::game::Igame" - }, - { - "type": "enum", - "name": "bytebeasts::models::game::GameStatus", - "variants": [ - { - "name": "Pending", - "type": "()" - }, - { - "name": "InProgress", - "type": "()" - }, - { - "name": "Finished", - "type": "()" - } - ] + "name": "leaderboardImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard" }, { "type": "enum", @@ -6067,41 +7861,67 @@ }, { "type": "struct", - "name": "bytebeasts::models::game::Game", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", "members": [ { - "name": "game_id", - "type": "core::integer::u128" + "name": "player_id", + "type": "core::integer::u32" }, { - "name": "player_1", - "type": "core::starknet::contract_address::ContractAddress" + "name": "player_name", + "type": "core::felt252" }, { - "name": "player_2", - "type": "core::starknet::contract_address::ContractAddress" + "name": "score", + "type": "core::integer::u32" }, { - "name": "player_3", - "type": "core::starknet::contract_address::ContractAddress" + "name": "wins", + "type": "core::integer::u32" }, { - "name": "player_4", - "type": "core::starknet::contract_address::ContractAddress" + "name": "losses", + "type": "core::integer::u32" }, { - "name": "status", - "type": "bytebeasts::models::game::GameStatus" + "name": "highest_score", + "type": "core::integer::u32" }, { - "name": "is_private", + "name": "is_active", "type": "core::bool" } ] }, + { + "type": "struct", + "name": "bytebeasts::models::leaderboard::Leaderboard", + "members": [ + { + "name": "leaderboard_id", + "type": "core::integer::u64" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "description", + "type": "core::felt252" + }, + { + "name": "entries", + "type": "core::array::Array::" + }, + { + "name": "last_updated", + "type": "core::integer::u64" + } + ] + }, { "type": "interface", - "name": "bytebeasts::models::game::Igame", + "name": "bytebeasts::models::leaderboard::Ileaderboard", "items": [ { "type": "function", @@ -6109,7 +7929,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::game::Game" + "type": "bytebeasts::models::leaderboard::Leaderboard" } ], "outputs": [], @@ -6119,30 +7939,55 @@ }, { "type": "event", - "name": "bytebeasts::models::game::game::Event", + "name": "bytebeasts::models::leaderboard::leaderboard::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Game", - "manifest_name": "bytebeasts-Game-e91217d7" + "tag": "bytebeasts-Leaderboard", + "manifest_name": "bytebeasts-Leaderboard-7e680376" }, { "kind": "DojoModel", "members": [ { - "name": "id", + "name": "player_id", "type": "u32", "key": true }, { - "name": "game_id", - "type": "u128", + "name": "player_name", + "type": "felt252", + "key": false + }, + { + "name": "score", + "type": "u32", + "key": false + }, + { + "name": "wins", + "type": "u32", + "key": false + }, + { + "name": "losses", + "type": "u32", + "key": false + }, + { + "name": "highest_score", + "type": "u32", + "key": false + }, + { + "name": "is_active", + "type": "bool", "key": false } ], - "class_hash": "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe", - "original_class_hash": "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe", + "class_hash": "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c", + "original_class_hash": "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c", "abi": [ { "type": "impl", @@ -6508,26 +8353,60 @@ }, { "type": "impl", - "name": "game_idImpl", - "interface_name": "bytebeasts::models::game_id::Igame_id" + "name": "leaderboard_entryImpl", + "interface_name": "bytebeasts::models::leaderboard::Ileaderboard_entry" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] }, { "type": "struct", - "name": "bytebeasts::models::game_id::GameId", + "name": "bytebeasts::models::leaderboard::LeaderboardEntry", "members": [ { - "name": "id", + "name": "player_id", "type": "core::integer::u32" }, { - "name": "game_id", - "type": "core::integer::u128" + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "wins", + "type": "core::integer::u32" + }, + { + "name": "losses", + "type": "core::integer::u32" + }, + { + "name": "highest_score", + "type": "core::integer::u32" + }, + { + "name": "is_active", + "type": "core::bool" } ] }, { "type": "interface", - "name": "bytebeasts::models::game_id::Igame_id", + "name": "bytebeasts::models::leaderboard::Ileaderboard_entry", "items": [ { "type": "function", @@ -6535,7 +8414,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::game_id::GameId" + "type": "bytebeasts::models::leaderboard::LeaderboardEntry" } ], "outputs": [], @@ -6545,70 +8424,45 @@ }, { "type": "event", - "name": "bytebeasts::models::game_id::game_id::Event", + "name": "bytebeasts::models::leaderboard::leaderboard_entry::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-GameId", - "manifest_name": "bytebeasts-GameId-344511d3" + "tag": "bytebeasts-LeaderboardEntry", + "manifest_name": "bytebeasts-LeaderboardEntry-7237950c" }, { "kind": "DojoModel", "members": [ { - "name": "address", - "type": "ContractAddress", - "key": true - }, - { - "name": "game_id", - "type": "u128", + "name": "mt_id", + "type": "u32", "key": true }, { - "name": "beast_1", - "type": "u8", - "key": false - }, - { - "name": "beast_2", - "type": "u8", - "key": false - }, - { - "name": "beast_3", - "type": "u8", - "key": false - }, - { - "name": "beast_4", - "type": "u8", - "key": false - }, - { - "name": "bag_id", - "type": "u8", + "name": "mt_name", + "type": "felt252", "key": false }, { - "name": "active_mount", - "type": "u8", + "name": "mt_type", + "type": "WorldElements", "key": false }, { - "name": "mounts", - "type": "Array", + "name": "mt_power", + "type": "u32", "key": false }, { - "name": "position", - "type": "Array", + "name": "mt_accuracy", + "type": "u32", "key": false } ], - "class_hash": "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18", - "original_class_hash": "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18", + "class_hash": "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc", + "original_class_hash": "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc", "abi": [ { "type": "impl", @@ -6974,58 +8828,64 @@ }, { "type": "impl", - "name": "game_playerImpl", - "interface_name": "bytebeasts::models::game_player::Igame_player" + "name": "mtImpl", + "interface_name": "bytebeasts::models::mt::Imt" }, { - "type": "struct", - "name": "bytebeasts::models::game_player::GamePlayer", - "members": [ + "type": "enum", + "name": "bytebeasts::models::world_elements::WorldElements", + "variants": [ { - "name": "address", - "type": "core::starknet::contract_address::ContractAddress" + "name": "Crystal", + "type": "()" }, { - "name": "game_id", - "type": "core::integer::u128" + "name": "Draconic", + "type": "()" }, { - "name": "beast_1", - "type": "core::integer::u8" + "name": "Shadow", + "type": "()" }, { - "name": "beast_2", - "type": "core::integer::u8" + "name": "Light", + "type": "()" }, { - "name": "beast_3", - "type": "core::integer::u8" - }, + "name": "Titanium", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::mt::Mt", + "members": [ { - "name": "beast_4", - "type": "core::integer::u8" + "name": "mt_id", + "type": "core::integer::u32" }, { - "name": "bag_id", - "type": "core::integer::u8" + "name": "mt_name", + "type": "core::felt252" }, { - "name": "active_mount", - "type": "core::integer::u8" + "name": "mt_type", + "type": "bytebeasts::models::world_elements::WorldElements" }, { - "name": "mounts", - "type": "core::array::Array::" + "name": "mt_power", + "type": "core::integer::u32" }, { - "name": "position", - "type": "core::array::Array::" + "name": "mt_accuracy", + "type": "core::integer::u32" } ] }, { "type": "interface", - "name": "bytebeasts::models::game_player::Igame_player", + "name": "bytebeasts::models::mt::Imt", "items": [ { "type": "function", @@ -7033,7 +8893,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::game_player::GamePlayer" + "type": "bytebeasts::models::mt::Mt" } ], "outputs": [], @@ -7043,45 +8903,80 @@ }, { "type": "event", - "name": "bytebeasts::models::game_player::game_player::Event", + "name": "bytebeasts::models::mt::mt::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-GamePlayer", - "manifest_name": "bytebeasts-GamePlayer-596ef4a1" + "tag": "bytebeasts-Mt", + "manifest_name": "bytebeasts-Mt-37360d30" }, { "kind": "DojoModel", "members": [ { - "name": "mt_id", + "name": "npc_id", "type": "u32", "key": true }, { - "name": "mt_name", + "name": "npc_name", "type": "felt252", "key": false }, { - "name": "mt_type", - "type": "WorldElements", + "name": "npc_description", + "type": "felt252", "key": false }, { - "name": "mt_power", - "type": "u32", + "name": "npc_role", + "type": "Role", "key": false }, { - "name": "mt_accuracy", - "type": "u32", + "name": "dialogue", + "type": "ByteArray", + "key": false + }, + { + "name": "is_active", + "type": "bool", + "key": false + }, + { + "name": "location", + "type": "Coordinates", + "key": false + }, + { + "name": "importance_level", + "type": "u8", + "key": false + }, + { + "name": "mission_status", + "type": "MissionStatus", + "key": false + }, + { + "name": "reward", + "type": "u16", + "key": false + }, + { + "name": "experience_points", + "type": "u16", + "key": false + }, + { + "name": "potions", + "type": "Array", "key": false } ], - "class_hash": "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc", - "original_class_hash": "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc", + "class_hash": "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9", + "original_class_hash": "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9", "abi": [ { "type": "impl", @@ -7447,64 +9342,156 @@ }, { "type": "impl", - "name": "mtImpl", - "interface_name": "bytebeasts::models::mt::Imt" + "name": "npcImpl", + "interface_name": "bytebeasts::models::npc::Inpc" }, { "type": "enum", - "name": "bytebeasts::models::world_elements::WorldElements", + "name": "bytebeasts::models::role::Role", "variants": [ { - "name": "Crystal", + "name": "Vendor", "type": "()" }, { - "name": "Draconic", + "name": "Trainer", "type": "()" }, { - "name": "Shadow", + "name": "Guide", "type": "()" }, { - "name": "Light", + "name": "QuestGiver", + "type": "()" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", "type": "()" }, { - "name": "Titanium", + "name": "True", "type": "()" } ] }, { "type": "struct", - "name": "bytebeasts::models::mt::Mt", + "name": "bytebeasts::models::coordinates::Coordinates", "members": [ { - "name": "mt_id", + "name": "x", "type": "core::integer::u32" }, { - "name": "mt_name", - "type": "core::felt252" + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "bytebeasts::models::mission_status::MissionStatus", + "variants": [ + { + "name": "NotStarted", + "type": "()" }, { - "name": "mt_type", - "type": "bytebeasts::models::world_elements::WorldElements" + "name": "InProgress", + "type": "()" }, { - "name": "mt_power", + "name": "Completed", + "type": "()" + }, + { + "name": "Failed", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::potion::Potion", + "members": [ + { + "name": "potion_id", "type": "core::integer::u32" }, { - "name": "mt_accuracy", + "name": "potion_name", + "type": "core::felt252" + }, + { + "name": "potion_effect", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::npc::NPC", + "members": [ + { + "name": "npc_id", "type": "core::integer::u32" + }, + { + "name": "npc_name", + "type": "core::felt252" + }, + { + "name": "npc_description", + "type": "core::felt252" + }, + { + "name": "npc_role", + "type": "bytebeasts::models::role::Role" + }, + { + "name": "dialogue", + "type": "core::byte_array::ByteArray" + }, + { + "name": "is_active", + "type": "core::bool" + }, + { + "name": "location", + "type": "bytebeasts::models::coordinates::Coordinates" + }, + { + "name": "importance_level", + "type": "core::integer::u8" + }, + { + "name": "mission_status", + "type": "bytebeasts::models::mission_status::MissionStatus" + }, + { + "name": "reward", + "type": "core::integer::u16" + }, + { + "name": "experience_points", + "type": "core::integer::u16" + }, + { + "name": "potions", + "type": "core::array::Array::" } ] }, { "type": "interface", - "name": "bytebeasts::models::mt::Imt", + "name": "bytebeasts::models::npc::Inpc", "items": [ { "type": "function", @@ -7512,7 +9499,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::mt::Mt" + "type": "bytebeasts::models::npc::NPC" } ], "outputs": [], @@ -7521,81 +9508,56 @@ ] }, { - "type": "event", - "name": "bytebeasts::models::mt::mt::Event", - "kind": "enum", - "variants": [] - } - ], - "tag": "bytebeasts-Mt", - "manifest_name": "bytebeasts-Mt-37360d30" - }, - { - "kind": "DojoModel", - "members": [ - { - "name": "npc_id", - "type": "u32", - "key": true - }, - { - "name": "npc_name", - "type": "felt252", - "key": false - }, - { - "name": "npc_description", - "type": "felt252", - "key": false - }, - { - "name": "npc_role", - "type": "Role", - "key": false - }, - { - "name": "dialogue", - "type": "ByteArray", - "key": false - }, + "type": "event", + "name": "bytebeasts::models::npc::npc::Event", + "kind": "enum", + "variants": [] + } + ], + "tag": "bytebeasts-NPC", + "manifest_name": "bytebeasts-NPC-4c5239ac" + }, + { + "kind": "DojoModel", + "members": [ { - "name": "is_active", - "type": "bool", - "key": false + "name": "player_id", + "type": "u32", + "key": true }, { - "name": "location", - "type": "Coordinates", + "name": "player_name", + "type": "felt252", "key": false }, { - "name": "importance_level", - "type": "u8", + "name": "beast_1", + "type": "u32", "key": false }, { - "name": "mission_status", - "type": "MissionStatus", + "name": "beast_2", + "type": "u32", "key": false }, { - "name": "reward", - "type": "u16", + "name": "beast_3", + "type": "u32", "key": false }, { - "name": "experience_points", - "type": "u16", + "name": "beast_4", + "type": "u32", "key": false }, { "name": "potions", - "type": "Array", + "type": "u32", "key": false } ], - "class_hash": "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9", - "original_class_hash": "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9", + "class_hash": "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016", + "original_class_hash": "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016", "abi": [ { "type": "impl", @@ -7961,156 +9923,46 @@ }, { "type": "impl", - "name": "npcImpl", - "interface_name": "bytebeasts::models::npc::Inpc" - }, - { - "type": "enum", - "name": "bytebeasts::models::role::Role", - "variants": [ - { - "name": "Vendor", - "type": "()" - }, - { - "name": "Trainer", - "type": "()" - }, - { - "name": "Guide", - "type": "()" - }, - { - "name": "QuestGiver", - "type": "()" - } - ] - }, - { - "type": "enum", - "name": "core::bool", - "variants": [ - { - "name": "False", - "type": "()" - }, - { - "name": "True", - "type": "()" - } - ] - }, - { - "type": "struct", - "name": "bytebeasts::models::coordinates::Coordinates", - "members": [ - { - "name": "x", - "type": "core::integer::u32" - }, - { - "name": "y", - "type": "core::integer::u32" - } - ] - }, - { - "type": "enum", - "name": "bytebeasts::models::mission_status::MissionStatus", - "variants": [ - { - "name": "NotStarted", - "type": "()" - }, - { - "name": "InProgress", - "type": "()" - }, - { - "name": "Completed", - "type": "()" - }, - { - "name": "Failed", - "type": "()" - } - ] + "name": "playerImpl", + "interface_name": "bytebeasts::models::player::Iplayer" }, { "type": "struct", - "name": "bytebeasts::models::potion::Potion", + "name": "bytebeasts::models::player::Player", "members": [ { - "name": "potion_id", + "name": "player_id", "type": "core::integer::u32" }, { - "name": "potion_name", + "name": "player_name", "type": "core::felt252" }, { - "name": "potion_effect", - "type": "core::integer::u32" - } - ] - }, - { - "type": "struct", - "name": "bytebeasts::models::npc::NPC", - "members": [ - { - "name": "npc_id", + "name": "beast_1", "type": "core::integer::u32" }, { - "name": "npc_name", - "type": "core::felt252" - }, - { - "name": "npc_description", - "type": "core::felt252" - }, - { - "name": "npc_role", - "type": "bytebeasts::models::role::Role" - }, - { - "name": "dialogue", - "type": "core::byte_array::ByteArray" - }, - { - "name": "is_active", - "type": "core::bool" - }, - { - "name": "location", - "type": "bytebeasts::models::coordinates::Coordinates" - }, - { - "name": "importance_level", - "type": "core::integer::u8" - }, - { - "name": "mission_status", - "type": "bytebeasts::models::mission_status::MissionStatus" + "name": "beast_2", + "type": "core::integer::u32" }, { - "name": "reward", - "type": "core::integer::u16" + "name": "beast_3", + "type": "core::integer::u32" }, { - "name": "experience_points", - "type": "core::integer::u16" + "name": "beast_4", + "type": "core::integer::u32" }, { "name": "potions", - "type": "core::array::Array::" + "type": "core::integer::u32" } ] }, { "type": "interface", - "name": "bytebeasts::models::npc::Inpc", + "name": "bytebeasts::models::player::Iplayer", "items": [ { "type": "function", @@ -8118,7 +9970,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::npc::NPC" + "type": "bytebeasts::models::player::Player" } ], "outputs": [], @@ -8128,55 +9980,30 @@ }, { "type": "event", - "name": "bytebeasts::models::npc::npc::Event", + "name": "bytebeasts::models::player::player::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-NPC", - "manifest_name": "bytebeasts-NPC-4c5239ac" + "tag": "bytebeasts-Player", + "manifest_name": "bytebeasts-Player-14f5e45e" }, { "kind": "DojoModel", "members": [ { - "name": "player_id", - "type": "u32", + "name": "player", + "type": "Player", "key": true }, { - "name": "player_name", - "type": "felt252", - "key": false - }, - { - "name": "beast_1", - "type": "u32", - "key": false - }, - { - "name": "beast_2", - "type": "u32", - "key": false - }, - { - "name": "beast_3", - "type": "u32", - "key": false - }, - { - "name": "beast_4", - "type": "u32", - "key": false - }, - { - "name": "potions", - "type": "u32", + "name": "coordinates", + "type": "Coordinates", "key": false } ], - "class_hash": "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016", - "original_class_hash": "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016", + "class_hash": "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2", + "original_class_hash": "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2", "abi": [ { "type": "impl", @@ -8542,8 +10369,8 @@ }, { "type": "impl", - "name": "playerImpl", - "interface_name": "bytebeasts::models::player::Iplayer" + "name": "positionImpl", + "interface_name": "bytebeasts::models::position::Iposition" }, { "type": "struct", @@ -8579,9 +10406,37 @@ } ] }, + { + "type": "struct", + "name": "bytebeasts::models::coordinates::Coordinates", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::position::Position", + "members": [ + { + "name": "player", + "type": "bytebeasts::models::player::Player" + }, + { + "name": "coordinates", + "type": "bytebeasts::models::coordinates::Coordinates" + } + ] + }, { "type": "interface", - "name": "bytebeasts::models::player::Iplayer", + "name": "bytebeasts::models::position::Iposition", "items": [ { "type": "function", @@ -8589,7 +10444,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::player::Player" + "type": "bytebeasts::models::position::Position" } ], "outputs": [], @@ -8599,30 +10454,35 @@ }, { "type": "event", - "name": "bytebeasts::models::player::player::Event", + "name": "bytebeasts::models::position::position::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Player", - "manifest_name": "bytebeasts-Player-14f5e45e" + "tag": "bytebeasts-Position", + "manifest_name": "bytebeasts-Position-78f28df6" }, { "kind": "DojoModel", "members": [ { - "name": "player", - "type": "Player", + "name": "potion_id", + "type": "u32", "key": true }, { - "name": "coordinates", - "type": "Coordinates", + "name": "potion_name", + "type": "felt252", + "key": false + }, + { + "name": "potion_effect", + "type": "u32", "key": false } ], - "class_hash": "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2", - "original_class_hash": "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2", + "class_hash": "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4", + "original_class_hash": "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4", "abi": [ { "type": "impl", @@ -8988,74 +10848,30 @@ }, { "type": "impl", - "name": "positionImpl", - "interface_name": "bytebeasts::models::position::Iposition" + "name": "potionImpl", + "interface_name": "bytebeasts::models::potion::Ipotion" }, { "type": "struct", - "name": "bytebeasts::models::player::Player", + "name": "bytebeasts::models::potion::Potion", "members": [ { - "name": "player_id", + "name": "potion_id", "type": "core::integer::u32" }, { - "name": "player_name", + "name": "potion_name", "type": "core::felt252" }, { - "name": "beast_1", - "type": "core::integer::u32" - }, - { - "name": "beast_2", - "type": "core::integer::u32" - }, - { - "name": "beast_3", - "type": "core::integer::u32" - }, - { - "name": "beast_4", - "type": "core::integer::u32" - }, - { - "name": "potions", - "type": "core::integer::u32" - } - ] - }, - { - "type": "struct", - "name": "bytebeasts::models::coordinates::Coordinates", - "members": [ - { - "name": "x", - "type": "core::integer::u32" - }, - { - "name": "y", + "name": "potion_effect", "type": "core::integer::u32" } ] }, - { - "type": "struct", - "name": "bytebeasts::models::position::Position", - "members": [ - { - "name": "player", - "type": "bytebeasts::models::player::Player" - }, - { - "name": "coordinates", - "type": "bytebeasts::models::coordinates::Coordinates" - } - ] - }, { "type": "interface", - "name": "bytebeasts::models::position::Iposition", + "name": "bytebeasts::models::potion::Ipotion", "items": [ { "type": "function", @@ -9063,7 +10879,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::position::Position" + "type": "bytebeasts::models::potion::Potion" } ], "outputs": [], @@ -9073,35 +10889,30 @@ }, { "type": "event", - "name": "bytebeasts::models::position::position::Event", + "name": "bytebeasts::models::potion::potion::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Position", - "manifest_name": "bytebeasts-Position-78f28df6" + "tag": "bytebeasts-Potion", + "manifest_name": "bytebeasts-Potion-6a2114b0" }, { "kind": "DojoModel", "members": [ { - "name": "potion_id", + "name": "player_id", "type": "u32", "key": true }, { - "name": "potion_name", + "name": "message", "type": "felt252", "key": false - }, - { - "name": "potion_effect", - "type": "u32", - "key": false } ], - "class_hash": "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4", - "original_class_hash": "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4", + "class_hash": "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef", + "original_class_hash": "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef", "abi": [ { "type": "impl", @@ -9467,30 +11278,26 @@ }, { "type": "impl", - "name": "potionImpl", - "interface_name": "bytebeasts::models::potion::Ipotion" + "name": "statusImpl", + "interface_name": "bytebeasts::systems::battle::battle_system::Istatus" }, { "type": "struct", - "name": "bytebeasts::models::potion::Potion", + "name": "bytebeasts::systems::battle::battle_system::Status", "members": [ { - "name": "potion_id", + "name": "player_id", "type": "core::integer::u32" }, { - "name": "potion_name", + "name": "message", "type": "core::felt252" - }, - { - "name": "potion_effect", - "type": "core::integer::u32" } ] }, { "type": "interface", - "name": "bytebeasts::models::potion::Ipotion", + "name": "bytebeasts::systems::battle::battle_system::Istatus", "items": [ { "type": "function", @@ -9498,7 +11305,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::models::potion::Potion" + "type": "bytebeasts::systems::battle::battle_system::Status" } ], "outputs": [], @@ -9508,19 +11315,19 @@ }, { "type": "event", - "name": "bytebeasts::models::potion::potion::Event", + "name": "bytebeasts::systems::battle::battle_system::status::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Potion", - "manifest_name": "bytebeasts-Potion-6a2114b0" + "tag": "bytebeasts-Status", + "manifest_name": "bytebeasts-Status-6595af0f" }, { "kind": "DojoModel", "members": [ { - "name": "player_id", + "name": "battle_id", "type": "u32", "key": true }, @@ -9530,8 +11337,8 @@ "key": false } ], - "class_hash": "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef", - "original_class_hash": "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef", + "class_hash": "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae", + "original_class_hash": "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae", "abi": [ { "type": "impl", @@ -9897,15 +11704,15 @@ }, { "type": "impl", - "name": "statusImpl", - "interface_name": "bytebeasts::systems::battle::battle_system::Istatus" + "name": "status_battleImpl", + "interface_name": "bytebeasts::systems::battle::battle_system::Istatus_battle" }, { "type": "struct", - "name": "bytebeasts::systems::battle::battle_system::Status", + "name": "bytebeasts::systems::battle::battle_system::StatusBattle", "members": [ { - "name": "player_id", + "name": "battle_id", "type": "core::integer::u32" }, { @@ -9916,7 +11723,7 @@ }, { "type": "interface", - "name": "bytebeasts::systems::battle::battle_system::Istatus", + "name": "bytebeasts::systems::battle::battle_system::Istatus_battle", "items": [ { "type": "function", @@ -9924,7 +11731,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::systems::battle::battle_system::Status" + "type": "bytebeasts::systems::battle::battle_system::StatusBattle" } ], "outputs": [], @@ -9934,30 +11741,55 @@ }, { "type": "event", - "name": "bytebeasts::systems::battle::battle_system::status::Event", + "name": "bytebeasts::systems::battle::battle_system::status_battle::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-Status", - "manifest_name": "bytebeasts-Status-6595af0f" + "tag": "bytebeasts-StatusBattle", + "manifest_name": "bytebeasts-StatusBattle-161fdb64" }, { "kind": "DojoModel", "members": [ { - "name": "battle_id", + "name": "tournament_id", "type": "u32", "key": true }, { - "name": "message", + "name": "name", "type": "felt252", "key": false + }, + { + "name": "status", + "type": "TournamentStatus", + "key": false + }, + { + "name": "entry_fee", + "type": "u32", + "key": false + }, + { + "name": "max_participants", + "type": "u32", + "key": false + }, + { + "name": "current_participants", + "type": "Array", + "key": false + }, + { + "name": "prize_pool", + "type": "u32", + "key": false } ], - "class_hash": "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae", - "original_class_hash": "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae", + "class_hash": "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec", + "original_class_hash": "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec", "abi": [ { "type": "impl", @@ -10323,26 +12155,98 @@ }, { "type": "impl", - "name": "status_battleImpl", - "interface_name": "bytebeasts::systems::battle::battle_system::Istatus_battle" + "name": "tournamentImpl", + "interface_name": "bytebeasts::models::tournament::Itournament" + }, + { + "type": "enum", + "name": "bytebeasts::models::tournament::TournamentStatus", + "variants": [ + { + "name": "Pending", + "type": "()" + }, + { + "name": "Ongoing", + "type": "()" + }, + { + "name": "Completed", + "type": "()" + } + ] }, { "type": "struct", - "name": "bytebeasts::systems::battle::battle_system::StatusBattle", + "name": "bytebeasts::models::player::Player", "members": [ { - "name": "battle_id", + "name": "player_id", "type": "core::integer::u32" }, { - "name": "message", + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "beast_1", + "type": "core::integer::u32" + }, + { + "name": "beast_2", + "type": "core::integer::u32" + }, + { + "name": "beast_3", + "type": "core::integer::u32" + }, + { + "name": "beast_4", + "type": "core::integer::u32" + }, + { + "name": "potions", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::tournament::Tournament", + "members": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "name", "type": "core::felt252" + }, + { + "name": "status", + "type": "bytebeasts::models::tournament::TournamentStatus" + }, + { + "name": "entry_fee", + "type": "core::integer::u32" + }, + { + "name": "max_participants", + "type": "core::integer::u32" + }, + { + "name": "current_participants", + "type": "core::array::Array::" + }, + { + "name": "prize_pool", + "type": "core::integer::u32" } ] }, { "type": "interface", - "name": "bytebeasts::systems::battle::battle_system::Istatus_battle", + "name": "bytebeasts::models::tournament::Itournament", "items": [ { "type": "function", @@ -10350,7 +12254,7 @@ "inputs": [ { "name": "model", - "type": "bytebeasts::systems::battle::battle_system::StatusBattle" + "type": "bytebeasts::models::tournament::Tournament" } ], "outputs": [], @@ -10360,13 +12264,13 @@ }, { "type": "event", - "name": "bytebeasts::systems::battle::battle_system::status_battle::Event", + "name": "bytebeasts::models::tournament::tournament::Event", "kind": "enum", "variants": [] } ], - "tag": "bytebeasts-StatusBattle", - "manifest_name": "bytebeasts-StatusBattle-161fdb64" + "tag": "bytebeasts-Tournament", + "manifest_name": "bytebeasts-Tournament-12bdecb1" } ] } \ No newline at end of file diff --git a/manifests/dev/deployment/manifest.toml b/manifests/dev/deployment/manifest.toml index eb90f3f..b6bdae9 100644 --- a/manifests/dev/deployment/manifest.toml +++ b/manifests/dev/deployment/manifest.toml @@ -92,6 +92,19 @@ init_calldata = [] tag = "bytebeasts-spawn_action" manifest_name = "bytebeasts-spawn_action-5176c1e8" +[[contracts]] +kind = "DojoContract" +address = "0x2671b8a136f1441cbd5fb6d3d9c5bdc45a3fbf184970b334cfd31ed98cf0b69" +class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" +original_class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" +base_class_hash = "0x2427dd10a58850ac9a5ca6ce04b7771b05330fd18f2e481831ad903b969e6b2" +abi = "manifests/dev/deployment/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json" +reads = [] +writes = [] +init_calldata = [] +tag = "bytebeasts-tournament_system" +manifest_name = "bytebeasts-tournament_system-1f2bbf20" + [[contracts]] kind = "DojoContract" address = "0x1a0997571ba63300bba592512cc9ac1daa8911ee08c049b5693d93c06377d25" @@ -455,6 +468,82 @@ name = "position" type = "Array" key = false +[[models]] +kind = "DojoModel" +class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" +original_class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" +abi = "manifests/dev/deployment/abis/models/bytebeasts-Leaderboard-7e680376.json" +tag = "bytebeasts-Leaderboard" +manifest_name = "bytebeasts-Leaderboard-7e680376" + +[[models.members]] +name = "leaderboard_id" +type = "u64" +key = true + +[[models.members]] +name = "name" +type = "felt252" +key = false + +[[models.members]] +name = "description" +type = "felt252" +key = false + +[[models.members]] +name = "entries" +type = "Array" +key = false + +[[models.members]] +name = "last_updated" +type = "u64" +key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" +original_class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" +abi = "manifests/dev/deployment/abis/models/bytebeasts-LeaderboardEntry-7237950c.json" +tag = "bytebeasts-LeaderboardEntry" +manifest_name = "bytebeasts-LeaderboardEntry-7237950c" + +[[models.members]] +name = "player_id" +type = "u32" +key = true + +[[models.members]] +name = "player_name" +type = "felt252" +key = false + +[[models.members]] +name = "score" +type = "u32" +key = false + +[[models.members]] +name = "wins" +type = "u32" +key = false + +[[models.members]] +name = "losses" +type = "u32" +key = false + +[[models.members]] +name = "highest_score" +type = "u32" +key = false + +[[models.members]] +name = "is_active" +type = "bool" +key = false + [[models]] kind = "DojoModel" class_hash = "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc" @@ -675,3 +764,46 @@ key = true name = "message" type = "felt252" key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" +original_class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" +abi = "manifests/dev/deployment/abis/models/bytebeasts-Tournament-12bdecb1.json" +tag = "bytebeasts-Tournament" +manifest_name = "bytebeasts-Tournament-12bdecb1" + +[[models.members]] +name = "tournament_id" +type = "u32" +key = true + +[[models.members]] +name = "name" +type = "felt252" +key = false + +[[models.members]] +name = "status" +type = "TournamentStatus" +key = false + +[[models.members]] +name = "entry_fee" +type = "u32" +key = false + +[[models.members]] +name = "max_participants" +type = "u32" +key = false + +[[models.members]] +name = "current_participants" +type = "Array" +key = false + +[[models.members]] +name = "prize_pool" +type = "u32" +key = false From 619ddc7c8b66a4503e99ad3114d53a05d2d22c3c Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Mon, 2 Dec 2024 11:32:41 +0100 Subject: [PATCH 13/16] refactor and rename fn upgrade_entry_stats and add negative test. Leaderboard's test file moved to test directory. --- src/lib.cairo | 1 + src/models/leaderboard.cairo | 262 +++---------------------------- src/tests/test_leaderboard.cairo | 237 ++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+), 244 deletions(-) create mode 100644 src/tests/test_leaderboard.cairo diff --git a/src/lib.cairo b/src/lib.cairo index b6ba634..4bdc601 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -34,4 +34,5 @@ mod models { mod tests { mod test_battle; mod test_bag; + mod test_leaderboard; } diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo index 954682c..78ee4ac 100644 --- a/src/models/leaderboard.cairo +++ b/src/models/leaderboard.cairo @@ -51,16 +51,6 @@ impl LeaderboardEntryPartialEq of PartialEq { } } -#[generate_trait] -impl LeaderboardEntryImpl of LeaderboardEntryTrait { - fn calculate_score (ref self: LeaderboardEntry) -> u32 { - // calculates score based on wins, losses and highest score - self.wins * 100 + self.highest_score - self.losses * 70 - } -} - - - #[derive(Drop, Serde)] #[dojo::model] @@ -117,19 +107,28 @@ impl LeaderboardImpl of LeaderboardTrait { } - fn update_entry_stats(ref self: Leaderboard, player_id: u32, new_wins: u32, new_losses: u32, new_highest_score: u32) -> Result<(), felt252> { + fn calculate_score (ref self: Leaderboard, wins: u32, highest_score: u32, losses: u32) -> u32 { + // calculates score based on wins, losses and highest score + wins * 100 + highest_score - losses * 70 + } + + + fn upgrade_entry_stats(ref self: Leaderboard, player_id: u32, new_wins: u32, new_losses: u32, new_highest_score: u32) -> Result<(), felt252> { // recalculates score and updates entry in the leaderboard // addning new wins, losses and changing highest score to an old entry match self.get_index_by_player_id(player_id) { Result::Ok(index) => { - let mut entry = self.entries.at(index).clone(); - entry.wins += new_wins; - entry.losses += new_losses; - if new_highest_score > entry.highest_score { - entry.highest_score = new_highest_score; - } - entry.score = entry.calculate_score(); - match self.update_entry(entry) { + let entry = self.entries.at(index); + let total_wins: u32 = *entry.wins + new_wins; + let total_losses: u32 = *entry.losses + new_losses; + let highest_score: u32 = if new_highest_score > *entry.highest_score { new_highest_score } else { *entry.highest_score }; + match self.update_entry( LeaderboardEntry { + score: self.calculate_score(total_wins, highest_score, total_losses), + wins: total_wins, + losses: total_losses, + highest_score: highest_score, + ..*entry + }) { Result::Ok(_) => Result::Ok(()), Result::Err(e) => Result::Err(e), } @@ -243,228 +242,3 @@ impl LeaderboardImpl of LeaderboardTrait { } } - -#[cfg(test)] -mod tests { - use core::{ - result::{Result, ResultTrait}, - array::ArrayTrait, - }; - use super::{LeaderboardTrait}; - use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry}; - use alexandria_data_structures::array_ext::ArrayTraitExt; - use alexandria_sorting::bubble_sort::bubble_sort_elements; - - fn create_mock_entry(player_id: u32, name: felt252, score: u32, wins: u32, losses: u32, highest_score: u32, is_active: bool) -> LeaderboardEntry { - LeaderboardEntry { - player_id: player_id, - player_name: name, - score: score, - wins: wins, - losses: losses, - highest_score: highest_score, - is_active: is_active, - } - } - - fn create_empty_leaderboard() -> Leaderboard { - Leaderboard { - leaderboard_id: 1, - name: 'Global Leaderboard', - description: 'Top players worldwide', - entries: ArrayTrait::new(), - last_updated: 0, - } - } - - #[test] - fn test_add_single_entry() { - let mut leaderboard = create_empty_leaderboard(); - let entry = create_mock_entry(1, 'Alice', 100, 10, 5, 100, true); - let res = leaderboard.add_entry(entry); - assert_eq!(res.is_ok(), true); - assert_eq!(leaderboard.entries.len(), 1); - assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong player name"); - - let duplicate_res = leaderboard.add_entry(entry); - assert_eq!(duplicate_res.is_err(), true, "Duplicate entry should return error"); - } - - #[test] - fn test_add_multiple_entry() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - - let _ = leaderboard.add_entry(entry4); - let _ = leaderboard.add_entry(entry5); - let entries = array![entry1, entry2, entry3, entry4, entry5]; - let not_added = leaderboard.add_batch(entries); - assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); - assert_eq!(not_added.len(), 2, "Wrong number of not added entries"); - assert_eq!(leaderboard.entries.at(0).player_name, @'Bob', "Wrong first player name"); - assert_eq!(leaderboard.entries.at(4).player_name, @'Eve', "Wrong last player name"); - - let duplicate_entries = array![entry1, entry2]; - let not_added_duplicates = leaderboard.add_batch(duplicate_entries); - assert_eq!(not_added_duplicates.len(), 2, "Duplicate entries should not be added"); - } - - #[test] - fn test_pop_front_n() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let _ = leaderboard.add_batch(array![entry1, entry2, entry3]); - let popped_entries = leaderboard.pop_front_n(2); - assert_eq!(popped_entries.len(), 2, "Wrong number of popped entries"); - assert_eq!(popped_entries.at(0).player_name, @'Bob', "Wrong first popped player name"); - assert_eq!(popped_entries.at(1).player_name, @'Charlie', "Wrong second popped player name"); - assert_eq!(leaderboard.entries.len(), 1, "Wrong number of remaining entries"); - assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong remaining player name"); - - let mut empty_leaderboard = create_empty_leaderboard(); - let popped_entries_empty = empty_leaderboard.pop_front_n(5); - assert_eq!(popped_entries_empty.len(), 0, "Popping from empty leaderboard should return empty array"); - } - - #[test] - fn test_remove_entry() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - - let entries = array![entry1, entry2, entry3, entry4, entry5]; - let _ = leaderboard.add_batch(entries); - let res = leaderboard.remove_entry(entry3); - assert_eq!(res.is_ok(), true); - assert_eq!(leaderboard.entries.len(), 4, "Wrong number of entries"); - assert_eq!(leaderboard.entries.at(2).player_name, @'Alice', "Wrong player name"); - - let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); - let res_non_existent = leaderboard.remove_entry(non_existent_entry); - assert_eq!(res_non_existent.is_err(), true, "Removing non-existent entry should return error"); - } - - #[test] - fn test_get_index_by_player_id() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - - let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); - let rank = leaderboard.get_index_by_player_id(34).unwrap(); - assert_eq!(rank, 2, "Wrong rank for Charlie"); - let rank = leaderboard.get_index_by_player_id(2).unwrap(); - assert_eq!(rank, 0, "Wrong rank for Bob"); - let rank = leaderboard.get_index_by_player_id(5).unwrap(); - assert_eq!(rank, 4, "Wrong rank for Eve"); - - let non_existent_rank = leaderboard.get_index_by_player_id(99); - assert_eq!(non_existent_rank.is_err(), true, "Getting index of non-existent player should return error"); - } - - #[test] - fn test_update_entry() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - - let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); - let new_score: u32 = 100; - let new_wins: u32 = 31; - let updated_entry = create_mock_entry(34, 'Charlie', new_score, new_wins, 15, 300, true); - let res = leaderboard.update_entry(updated_entry); - let rank = leaderboard.get_index_by_player_id(34).unwrap(); - assert_eq!(res.is_ok(), true); - assert_eq!(rank, 4, "Wrong rank"); - assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); - assert_eq!(leaderboard.entries.at(rank).score, @new_score, "Wrong score"); - assert_eq!(leaderboard.entries.at(rank).wins, @new_wins, "Wrong wins"); - - let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); - let res_non_existent = leaderboard.update_entry(non_existent_entry); - assert_eq!(res_non_existent.is_err(), true, "Updating non-existent entry should return error"); - } - - #[test] - fn test_get_entries() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let _ = leaderboard.add_batch(array![entry1, entry2]); - let entries = leaderboard.get_entries(); - assert_eq!(entries.len(), 2, "Wrong number of entries"); - assert_eq!(entries.at(0).player_name, @'Bob', "Wrong first player name"); - assert_eq!(entries.at(1).player_name, @'Alice', "Wrong second player name"); - - let mut empty_leaderboard = create_empty_leaderboard(); - let entries_empty = empty_leaderboard.get_entries(); - assert_eq!(entries_empty.len(), 0, "Empty leaderboard should return empty array"); - } - - #[test] - fn test_get_slice() { - let mut leaderboard = create_empty_leaderboard(); - let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - - let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); - let slice = leaderboard.get_slice(1, 4).unwrap(); - assert_eq!(slice.len(), 3, "Wrong number of entries in slice"); - assert_eq!(slice.at(0).player_name, @'David', "Wrong first player name in slice"); - assert_eq!(slice.at(2).player_name, @'Alice', "Wrong last player name in slice"); - - let invalid_slice = leaderboard.get_slice(4, 1); - assert_eq!(invalid_slice.is_err(), true, "Invalid slice range should return error"); - - let out_of_bounds_slice = leaderboard.get_slice(1, 10); - assert_eq!(out_of_bounds_slice.is_err(), true, "Out of bounds slice should return error"); - - let mut empty_leaderboard = create_empty_leaderboard(); - let empty_slice = empty_leaderboard.get_slice(0, 1); - assert_eq!(empty_slice.is_err(), true, "Empty leaderboard should return error"); - } - - #[test] - fn test_update_entry_stats() { - let mut leaderboard = create_empty_leaderboard(); - let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); - let entry3 = create_mock_entry(34, 'Charlie', 2250, 30, 15, 300, true); - let entry1 = create_mock_entry(12, 'Alice', 2400, 10, 5, 100, true); - let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); - let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); - - let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); - let new_wins: u32 = 31; - let new_losses: u32 = 10; - let new_highest_score: u32 = 400; - let res = leaderboard.update_entry_stats(34, new_wins, new_losses, new_highest_score); - let rank = leaderboard.get_index_by_player_id(34).unwrap(); - - let total_wins: u32 = entry3.wins + new_wins; - let total_losses: u32 = entry3.losses + new_losses; - assert_eq!(res.is_ok(), true); - assert_eq!(rank, 2, "Wrong rank after update"); - assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); - assert_eq!(leaderboard.entries.at(rank).wins, @total_wins, "Wrong wins"); - assert_eq!(leaderboard.entries.at(rank).losses, @total_losses, "Wrong losses"); - assert_eq!(leaderboard.entries.at(rank).highest_score, @new_highest_score, "Wrong highest score"); - } -} diff --git a/src/tests/test_leaderboard.cairo b/src/tests/test_leaderboard.cairo new file mode 100644 index 0000000..cda8fd7 --- /dev/null +++ b/src/tests/test_leaderboard.cairo @@ -0,0 +1,237 @@ +#[cfg(test)] +mod tests { + use core::{ + result::{Result, ResultTrait}, + array::ArrayTrait, + }; + use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry, LeaderboardTrait}; + use alexandria_data_structures::array_ext::ArrayTraitExt; + use alexandria_sorting::bubble_sort::bubble_sort_elements; + + fn create_mock_entry(player_id: u32, name: felt252, score: u32, wins: u32, losses: u32, highest_score: u32, is_active: bool) -> LeaderboardEntry { + LeaderboardEntry { + player_id: player_id, + player_name: name, + score: score, + wins: wins, + losses: losses, + highest_score: highest_score, + is_active: is_active, + } + } + + fn create_empty_leaderboard() -> Leaderboard { + Leaderboard { + leaderboard_id: 1, + name: 'Global Leaderboard', + description: 'Top players worldwide', + entries: ArrayTrait::new(), + last_updated: 0, + } + } + + #[test] + fn test_add_single_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry = create_mock_entry(1, 'Alice', 100, 10, 5, 100, true); + let res = leaderboard.add_entry(entry); + assert_eq!(res.is_ok(), true); + assert_eq!(leaderboard.entries.len(), 1); + assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong player name"); + + let duplicate_res = leaderboard.add_entry(entry); + assert_eq!(duplicate_res.is_err(), true, "Duplicate entry should return error"); + } + + #[test] + fn test_add_multiple_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_entry(entry4); + let _ = leaderboard.add_entry(entry5); + let entries = array![entry1, entry2, entry3, entry4, entry5]; + let not_added = leaderboard.add_batch(entries); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(not_added.len(), 2, "Wrong number of not added entries"); + assert_eq!(leaderboard.entries.at(0).player_name, @'Bob', "Wrong first player name"); + assert_eq!(leaderboard.entries.at(4).player_name, @'Eve', "Wrong last player name"); + + let duplicate_entries = array![entry1, entry2]; + let not_added_duplicates = leaderboard.add_batch(duplicate_entries); + assert_eq!(not_added_duplicates.len(), 2, "Duplicate entries should not be added"); + } + + #[test] + fn test_pop_front_n() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let _ = leaderboard.add_batch(array![entry1, entry2, entry3]); + let popped_entries = leaderboard.pop_front_n(2); + assert_eq!(popped_entries.len(), 2, "Wrong number of popped entries"); + assert_eq!(popped_entries.at(0).player_name, @'Bob', "Wrong first popped player name"); + assert_eq!(popped_entries.at(1).player_name, @'Charlie', "Wrong second popped player name"); + assert_eq!(leaderboard.entries.len(), 1, "Wrong number of remaining entries"); + assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong remaining player name"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let popped_entries_empty = empty_leaderboard.pop_front_n(5); + assert_eq!(popped_entries_empty.len(), 0, "Popping from empty leaderboard should return empty array"); + } + + #[test] + fn test_remove_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let entries = array![entry1, entry2, entry3, entry4, entry5]; + let _ = leaderboard.add_batch(entries); + let res = leaderboard.remove_entry(entry3); + assert_eq!(res.is_ok(), true); + assert_eq!(leaderboard.entries.len(), 4, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(2).player_name, @'Alice', "Wrong player name"); + + let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); + let res_non_existent = leaderboard.remove_entry(non_existent_entry); + assert_eq!(res_non_existent.is_err(), true, "Removing non-existent entry should return error"); + } + + #[test] + fn test_get_index_by_player_id() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + assert_eq!(rank, 2, "Wrong rank for Charlie"); + let rank = leaderboard.get_index_by_player_id(2).unwrap(); + assert_eq!(rank, 0, "Wrong rank for Bob"); + let rank = leaderboard.get_index_by_player_id(5).unwrap(); + assert_eq!(rank, 4, "Wrong rank for Eve"); + + let non_existent_rank = leaderboard.get_index_by_player_id(99); + assert_eq!(non_existent_rank.is_err(), true, "Getting index of non-existent player should return error"); + } + + #[test] + fn test_update_entry() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let new_score: u32 = 100; + let new_wins: u32 = 31; + let updated_entry = create_mock_entry(34, 'Charlie', new_score, new_wins, 15, 300, true); + let res = leaderboard.update_entry(updated_entry); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + assert_eq!(res.is_ok(), true); + assert_eq!(rank, 4, "Wrong rank"); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(rank).score, @new_score, "Wrong score"); + assert_eq!(leaderboard.entries.at(rank).wins, @new_wins, "Wrong wins"); + + let non_existent_entry = create_mock_entry(99, 'NonExistent', 0, 0, 0, 0, false); + let res_non_existent = leaderboard.update_entry(non_existent_entry); + assert_eq!(res_non_existent.is_err(), true, "Updating non-existent entry should return error"); + } + + #[test] + fn test_get_entries() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let _ = leaderboard.add_batch(array![entry1, entry2]); + let entries = leaderboard.get_entries(); + assert_eq!(entries.len(), 2, "Wrong number of entries"); + assert_eq!(entries.at(0).player_name, @'Bob', "Wrong first player name"); + assert_eq!(entries.at(1).player_name, @'Alice', "Wrong second player name"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let entries_empty = empty_leaderboard.get_entries(); + assert_eq!(entries_empty.len(), 0, "Empty leaderboard should return empty array"); + } + + #[test] + fn test_get_slice() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(12, 'Alice', 1100, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry3 = create_mock_entry(34, 'Charlie', 1300, 30, 15, 300, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let slice = leaderboard.get_slice(1, 4).unwrap(); + assert_eq!(slice.len(), 3, "Wrong number of entries in slice"); + assert_eq!(slice.at(0).player_name, @'David', "Wrong first player name in slice"); + assert_eq!(slice.at(2).player_name, @'Alice', "Wrong last player name in slice"); + + let invalid_slice = leaderboard.get_slice(4, 1); + assert_eq!(invalid_slice.is_err(), true, "Invalid slice range should return error"); + + let out_of_bounds_slice = leaderboard.get_slice(1, 10); + assert_eq!(out_of_bounds_slice.is_err(), true, "Out of bounds slice should return error"); + + let mut empty_leaderboard = create_empty_leaderboard(); + let empty_slice = empty_leaderboard.get_slice(0, 1); + assert_eq!(empty_slice.is_err(), true, "Empty leaderboard should return error"); + } + + #[test] + fn test_calculate_score() { + let mut leaderboard = create_empty_leaderboard(); + let wins: u32 = 10; + let losses: u32 = 5; + let highest_score: u32 = 100; + let score = leaderboard.calculate_score(wins, highest_score, losses); + let expected_score = wins * 100 + highest_score - losses * 70; + assert_eq!(score, expected_score, "Wrong score calculation"); + } + + #[test] + fn test_upgrade_entry_stats() { + let mut leaderboard = create_empty_leaderboard(); + let entry5 = create_mock_entry(5, 'Eve', 500, 50, 25, 500, true); + let entry3 = create_mock_entry(34, 'Charlie', 2250, 30, 15, 300, true); + let entry1 = create_mock_entry(12, 'Alice', 2400, 10, 5, 100, true); + let entry2 = create_mock_entry(2, 'Bob', 200121, 20, 10, 200, true); + let entry4 = create_mock_entry(9, 'David', 22400, 40, 20, 400, true); + + let _ = leaderboard.add_batch(array![entry1, entry2, entry3, entry4, entry5]); + let new_wins: u32 = 31; + let new_losses: u32 = 10; + let new_highest_score: u32 = 400; + let total_wins: u32 = entry3.wins + new_wins; + let total_losses: u32 = entry3.losses + new_losses; + let res = leaderboard.upgrade_entry_stats(34, new_wins, new_losses, new_highest_score); + let rank = leaderboard.get_index_by_player_id(34).unwrap(); + + let negative_res = leaderboard.upgrade_entry_stats(31, new_wins, new_losses, new_highest_score); + + assert_eq!(res.is_ok(), true); + assert_eq!(rank, 2, "Wrong rank after update"); + assert_eq!(leaderboard.entries.len(), 5, "Wrong number of entries"); + assert_eq!(leaderboard.entries.at(rank).wins, @total_wins, "Wrong wins"); + assert_eq!(leaderboard.entries.at(rank).losses, @total_losses, "Wrong losses"); + assert_eq!(leaderboard.entries.at(rank).highest_score, @new_highest_score, "Wrong highest score"); + assert_eq!(negative_res.is_err(), true, "Updating non-existent entry should return error"); + } +} \ No newline at end of file From c2bf4fd75846c7a81a911051402680b1022479c4 Mon Sep 17 00:00:00 2001 From: saimeunt Date: Tue, 3 Dec 2024 10:27:41 +0100 Subject: [PATCH 14/16] Add tests for tournament_system (#101) * Add tests for tournament_system * Quickfixes * sozo build --- .tool-versions | 2 + ...bytebeasts-tournament_system-1f2bbf20.json | 58 ++-- .../bytebeasts-Tournament-12bdecb1.json | 36 +- ...bytebeasts-tournament_system-1f2bbf20.toml | 4 +- .../bytebeasts-Tournament-12bdecb1.toml | 6 +- src/lib.cairo | 1 + src/models/tournament.cairo | 21 +- src/systems/tournament.cairo | 38 ++- src/tests/test_tournament.cairo | 313 ++++++++++++++++++ 9 files changed, 375 insertions(+), 104 deletions(-) create mode 100644 .tool-versions create mode 100644 src/tests/test_tournament.cairo diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..366991b --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +scarb 2.7.0 +dojo 1.0.0-alpha.5 diff --git a/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json b/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json index 2d4cb03..682a26f 100644 --- a/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json +++ b/manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json @@ -149,40 +149,6 @@ } ] }, - { - "type": "struct", - "name": "bytebeasts::models::player::Player", - "members": [ - { - "name": "player_id", - "type": "core::integer::u32" - }, - { - "name": "player_name", - "type": "core::felt252" - }, - { - "name": "beast_1", - "type": "core::integer::u32" - }, - { - "name": "beast_2", - "type": "core::integer::u32" - }, - { - "name": "beast_3", - "type": "core::integer::u32" - }, - { - "name": "beast_4", - "type": "core::integer::u32" - }, - { - "name": "potions", - "type": "core::integer::u32" - } - ] - }, { "type": "struct", "name": "bytebeasts::models::tournament::Tournament", @@ -209,7 +175,7 @@ }, { "name": "current_participants", - "type": "core::array::Array::" + "type": "core::array::Array::" }, { "name": "prize_pool", @@ -247,7 +213,7 @@ }, { "name": "current_participants", - "type": "core::array::Array::" + "type": "core::array::Array::" }, { "name": "prize_pool", @@ -266,8 +232,8 @@ "type": "core::integer::u32" }, { - "name": "new_player", - "type": "bytebeasts::models::player::Player" + "name": "new_player_id", + "type": "core::integer::u32" } ], "outputs": [], @@ -285,6 +251,22 @@ "outputs": [], "state_mutability": "external" }, + { + "type": "function", + "name": "complete_tournament", + "inputs": [ + { + "name": "tournament_id", + "type": "core::integer::u32" + }, + { + "name": "player_id", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "get_tournament", diff --git a/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json b/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json index 73bd005..9f93476 100644 --- a/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json +++ b/manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json @@ -384,40 +384,6 @@ } ] }, - { - "type": "struct", - "name": "bytebeasts::models::player::Player", - "members": [ - { - "name": "player_id", - "type": "core::integer::u32" - }, - { - "name": "player_name", - "type": "core::felt252" - }, - { - "name": "beast_1", - "type": "core::integer::u32" - }, - { - "name": "beast_2", - "type": "core::integer::u32" - }, - { - "name": "beast_3", - "type": "core::integer::u32" - }, - { - "name": "beast_4", - "type": "core::integer::u32" - }, - { - "name": "potions", - "type": "core::integer::u32" - } - ] - }, { "type": "struct", "name": "bytebeasts::models::tournament::Tournament", @@ -444,7 +410,7 @@ }, { "name": "current_participants", - "type": "core::array::Array::" + "type": "core::array::Array::" }, { "name": "prize_pool", diff --git a/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml b/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml index e288571..97f792e 100644 --- a/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml +++ b/manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" -original_class_hash = "0x7bbd215ec46e02f1c7aad934c54a58b9081c43939d8afe0e7843e8202d8cea7" +class_hash = "0x20aead2ca71d2f0bfcbfa28a41b4b7687aa1af2579394c256ca0c4dc73bd2e8" +original_class_hash = "0x20aead2ca71d2f0bfcbfa28a41b4b7687aa1af2579394c256ca0c4dc73bd2e8" base_class_hash = "0x0" abi = "manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json" reads = [] diff --git a/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml b/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml index 417660e..a4d790e 100644 --- a/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml +++ b/manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml @@ -1,6 +1,6 @@ kind = "DojoModel" -class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" -original_class_hash = "0x3004c0d548b033db92ed628e38e940ee67b44cf73ffd50a0bc10c334a000aec" +class_hash = "0x6d38c864554f8be34be3ab85e56ce73c86ad695b61b8ccec9553cf208631d0b" +original_class_hash = "0x6d38c864554f8be34be3ab85e56ce73c86ad695b61b8ccec9553cf208631d0b" abi = "manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json" tag = "bytebeasts-Tournament" manifest_name = "bytebeasts-Tournament-12bdecb1" @@ -32,7 +32,7 @@ key = false [[members]] name = "current_participants" -type = "Array" +type = "Array" key = false [[members]] diff --git a/src/lib.cairo b/src/lib.cairo index 4bdc601..973eb26 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -35,4 +35,5 @@ mod tests { mod test_battle; mod test_bag; mod test_leaderboard; + mod test_tournament; } diff --git a/src/models/tournament.cairo b/src/models/tournament.cairo index c31bfd9..47b6118 100644 --- a/src/models/tournament.cairo +++ b/src/models/tournament.cairo @@ -1,5 +1,3 @@ -use super::player::Player; - #[derive(Serde, Copy, Drop, Introspect, PartialEq, Debug)] pub enum TournamentStatus { Pending, @@ -17,7 +15,7 @@ pub struct Tournament { pub status: TournamentStatus, pub entry_fee: u32, pub max_participants: u32, - pub current_participants: Array, + pub current_participants: Array, pub prize_pool: u32, } @@ -25,32 +23,19 @@ pub struct Tournament { #[cfg(test)] mod tests { use bytebeasts::{ - models::{tournament::Tournament, tournament::TournamentStatus, player::Player} + models::{tournament::Tournament, tournament::TournamentStatus} }; #[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, + current_participants: array![1], prize_pool: 1, }; diff --git a/src/systems/tournament.cairo b/src/systems/tournament.cairo index 6c94b8a..33411d6 100644 --- a/src/systems/tournament.cairo +++ b/src/systems/tournament.cairo @@ -1,5 +1,5 @@ use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; -use bytebeasts::{models::{player::Player, tournament::Tournament, tournament::TournamentStatus},}; +use bytebeasts::{models::{tournament::Tournament, tournament::TournamentStatus},}; #[dojo::interface] trait ITournamentAction { @@ -10,12 +10,12 @@ trait ITournamentAction { status: TournamentStatus, entry_fee: u32, max_participants: u32, - current_participants: Array, + current_participants: Array, prize_pool: u32 ); - fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player: Player); + fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player_id: u32); fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32); - // fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); + fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament; } @@ -24,7 +24,7 @@ trait ITournamentAction { mod tournament_system { use super::ITournamentAction; use bytebeasts::{ - models::{player::Player, tournament::Tournament, tournament::TournamentStatus}, + models::{tournament::Tournament, tournament::TournamentStatus}, }; #[abi(embed_v0)] @@ -36,7 +36,7 @@ mod tournament_system { status: TournamentStatus, entry_fee: u32, max_participants: u32, - current_participants: Array, + current_participants: Array, prize_pool: u32 ) { let tournament = Tournament { @@ -51,7 +51,7 @@ mod tournament_system { set!(world, (tournament)) } - fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player: Player) { + fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player_id: u32) { let mut tournament = get!(world, tournament_id, (Tournament)); assert!(tournament.status == TournamentStatus::Pending, "Tournament not open for registration"); @@ -61,7 +61,7 @@ mod tournament_system { "Tournament is full" ); - tournament.current_participants.append(new_player); + tournament.current_participants.append(new_player_id); set!(world, (tournament)); } @@ -81,6 +81,28 @@ mod tournament_system { set!(world, (tournament)); } + fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32) { + let tournament = get!(world, tournament_id, (Tournament)); + + assert!(tournament.status == TournamentStatus::Ongoing, "Tournament not ongoing"); + + // Validate winner is a participant + let mut is_participant = false; + for participant in tournament.current_participants { + if participant == player_id { + is_participant = true; + break; + } + }; + assert!(is_participant, "Winner not participant"); + + // TODO distribute prize pool to winner + let mut tournament = get!(world, tournament_id, (Tournament)); + tournament.status = TournamentStatus::Completed; + + 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 new file mode 100644 index 0000000..7e67f7a --- /dev/null +++ b/src/tests/test_tournament.cairo @@ -0,0 +1,313 @@ +#[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::player::{Player, player}, + models::tournament::{Tournament, tournament, TournamentStatus}, + }; + + const TOURNAMENT_ID: u32 = 1; + const TOURNAMENT_NAME: felt252 = 'TOURNAMENT_NAME'; + const TOURNAMENT_ENTRY_FEE: u32 = 0; + const TOURNAMENT_MAX_PARTICIPANTS: u32 = 2; + const TOURNAMENT_PRIZE_POOL: u32 = 0; + + const PLAYER1_ID: u32 = 1; + const PLAYER1_NAME: felt252 = 'PLAYER1'; + const PLAYER1_BEAST1: u32 = 0; + const PLAYER1_BEAST2: u32 = 0; + const PLAYER1_BEAST3: u32 = 0; + const PLAYER1_BEAST4: u32 = 0; + const PLAYER1_POTIONS: u32 = 0; + + // Helper function to create the first player + fn get_player1() -> Player { + Player { + player_id: PLAYER1_ID, + player_name: PLAYER1_NAME, + beast_1: PLAYER1_BEAST1, + beast_2: PLAYER1_BEAST2, + beast_3: PLAYER1_BEAST3, + beast_4: PLAYER1_BEAST4, + potions: PLAYER1_POTIONS + } + } + + const PLAYER2_ID: u32 = 2; + const PLAYER2_NAME: felt252 = 'PLAYER2'; + const PLAYER2_BEAST1: u32 = 0; + const PLAYER2_BEAST2: u32 = 0; + const PLAYER2_BEAST3: u32 = 0; + const PLAYER2_BEAST4: u32 = 0; + const PLAYER2_POTIONS: u32 = 0; + + // Helper function to create the second player + fn get_player2() -> Player { + Player { + player_id: PLAYER2_ID, + player_name: PLAYER2_NAME, + beast_1: PLAYER2_BEAST1, + beast_2: PLAYER2_BEAST2, + beast_3: PLAYER2_BEAST3, + beast_4: PLAYER2_BEAST4, + potions: PLAYER2_POTIONS + } + } + + const PLAYER3_ID: u32 = 3; + const PLAYER3_NAME: felt252 = 'PLAYER3'; + const PLAYER3_BEAST1: u32 = 0; + const PLAYER3_BEAST2: u32 = 0; + const PLAYER3_BEAST3: u32 = 0; + const PLAYER3_BEAST4: u32 = 0; + const PLAYER3_POTIONS: u32 = 0; + + // Helper function to create the third player + fn get_player3() -> Player { + Player { + player_id: PLAYER3_ID, + player_name: PLAYER3_NAME, + beast_1: PLAYER3_BEAST1, + beast_2: PLAYER3_BEAST2, + beast_3: PLAYER3_BEAST3, + beast_4: PLAYER3_BEAST4, + potions: PLAYER3_POTIONS + } + } + + // Initializes the testing environment by creating the world with the required models and deploying the tournament contract + fn setup_world() -> (IWorldDispatcher, ITournamentActionDispatcher) { + let mut models = array![ + player::TEST_CLASS_HASH, + tournament::TEST_CLASS_HASH + ]; + + // Spawns a test world with the specified name and models + let world = spawn_test_world("bytebeasts", models); + + // Deploys the tournament system contract and retrieves its address + let contract_address = world.deploy_contract('salt', tournament_system::TEST_CLASS_HASH.try_into().unwrap()); + + // Initializes the tournament system dispatcher with the deployed contract address + let tournament_system = ITournamentActionDispatcher { contract_address }; + + // Grants write permissions for the tournament system contract + world.grant_writer(dojo::utils::bytearray_hash(@"bytebeasts"), contract_address); + + // Returns the world instance and tournament system dispatcher + (world, tournament_system) + } + + // Initializes an empty tournament + fn setup_tournament() -> (IWorldDispatcher, ITournamentActionDispatcher) { + let (world, tournament_system) = setup_world(); + + // Creates an empty pending tournament with no participants + tournament_system.create_tournament( + TOURNAMENT_ID, + TOURNAMENT_NAME, + TournamentStatus::Pending, + TOURNAMENT_ENTRY_FEE, + TOURNAMENT_MAX_PARTICIPANTS, + array![], + TOURNAMENT_PRIZE_POOL + ); + + (world, tournament_system) + } + + // Initializes a tournament with 2 players + fn setup_tournament_with_players() -> (IWorldDispatcher, ITournamentActionDispatcher) { + let (world, tournament_system) = setup_world(); + + // Creates the 2 players + let player1 = get_player1(); + set!(world, (player1)); + let player2 = get_player2(); + set!(world, (player2)); + + // Creates a tournament with 2 participants + tournament_system.create_tournament( + TOURNAMENT_ID, + TOURNAMENT_NAME, + TournamentStatus::Pending, + TOURNAMENT_ENTRY_FEE, + TOURNAMENT_MAX_PARTICIPANTS, + array![player1.player_id, player2.player_id], + TOURNAMENT_PRIZE_POOL + ); + + (world, tournament_system) + } + + // This test verifies the creation of an empty tournament + #[test] + fn test_create_tournament() { + let (world, _) = setup_tournament(); + + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + + assert_eq!(tournament.tournament_id, TOURNAMENT_ID); + assert_eq!(tournament.name, TOURNAMENT_NAME); + assert_eq!(tournament.status, TournamentStatus::Pending); + assert_eq!(tournament.entry_fee, TOURNAMENT_ENTRY_FEE); + assert_eq!(tournament.max_participants, TOURNAMENT_MAX_PARTICIPANTS); + assert_eq!(tournament.current_participants, array![]); + assert_eq!(tournament.prize_pool, TOURNAMENT_PRIZE_POOL); + } + + // This test verifies the creation of a tournament with 2 players + #[test] + fn test_create_tournament_with_players() { + let (world, _) = setup_tournament_with_players(); + + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + + assert_eq!(tournament.tournament_id, TOURNAMENT_ID); + assert_eq!(tournament.name, TOURNAMENT_NAME); + assert_eq!(tournament.status, TournamentStatus::Pending); + assert_eq!(tournament.entry_fee, TOURNAMENT_ENTRY_FEE); + assert_eq!(tournament.max_participants, TOURNAMENT_MAX_PARTICIPANTS); + assert_eq!(tournament.current_participants, array![PLAYER1_ID, PLAYER2_ID]); + assert_eq!(tournament.prize_pool, TOURNAMENT_PRIZE_POOL); + } + + // This test verifies a player can't be registered if the tournament status is not pending + #[test] + #[should_panic(expected: ("Tournament not open for registration", 'ENTRYPOINT_FAILED'))] + fn test_register_player_not_pending() { + let (world, tournament_system) = setup_tournament(); + + // Mutates the status to ongoing to make player registration fail + let mut tournament = get!(world, TOURNAMENT_ID, (Tournament)); + tournament.status = TournamentStatus::Ongoing; + set!(world, (tournament)); + + let player1 = get_player1(); + set!(world, (player1)); + + tournament_system.register_player(TOURNAMENT_ID, player1.player_id); + } + + // This test verifies it's impossible for a player to join an already full tournament + #[test] + #[should_panic(expected: ("Tournament is full", 'ENTRYPOINT_FAILED'))] + fn test_register_player_tournament_full() { + let (world, tournament_system) = setup_tournament_with_players(); + + let player3 = get_player3(); + set!(world, (player3)); + + tournament_system.register_player(TOURNAMENT_ID, player3.player_id); + } + + // This test verifies the tournament can register players + #[test] + fn test_register_players() { + let (world, tournament_system) = setup_tournament(); + + let player1 = get_player1(); + set!(world, (player1)); + tournament_system.register_player(TOURNAMENT_ID, player1.player_id); + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + assert_eq!(tournament.current_participants, array![player1.player_id]); + + let player2 = get_player2(); + set!(world, (player2)); + tournament_system.register_player(TOURNAMENT_ID, player2.player_id); + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + assert_eq!(tournament.current_participants, array![player1.player_id, player2.player_id]); + } + + // This test verifies the tournament cannot be started if not in the pending status + #[test] + #[should_panic(expected: ("Tournament not pending", 'ENTRYPOINT_FAILED'))] + fn test_start_tournament_not_pending() { + let (world, tournament_system) = setup_tournament(); + + // Mutates the status to ongoing so that the tournament will fail to start + let mut tournament = get!(world, TOURNAMENT_ID, (Tournament)); + tournament.status = TournamentStatus::Ongoing; + set!(world, (tournament)); + + tournament_system.start_tournament(TOURNAMENT_ID); + } + + // This test verifies the tournament cannot be started until we reach at least 2 participants + #[test] + #[should_panic(expected: ("Not enough participants to start", 'ENTRYPOINT_FAILED'))] + fn test_start_tournament_not_enough_participants() { + let (_, tournament_system) = setup_tournament(); + + tournament_system.start_tournament(TOURNAMENT_ID); + } + + // This test verifies the tournament can be started correctly + #[test] + fn test_start_tournament() { + let (world, tournament_system) = setup_tournament_with_players(); + + tournament_system.start_tournament(TOURNAMENT_ID); + + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + assert_eq!(tournament.status, TournamentStatus::Ongoing); + } + + // This test verifies the tournament can't be completed if not ongoing + #[test] + #[should_panic(expected: ("Tournament not ongoing", 'ENTRYPOINT_FAILED'))] + fn test_complete_tournament_not_ongoing() { + let (_, tournament_system) = setup_tournament(); + + tournament_system.complete_tournament(TOURNAMENT_ID, PLAYER1_ID); + } + + // This test verifies that the declared winner of a tournament must be a participant + #[test] + #[should_panic(expected: ("Winner not participant", 'ENTRYPOINT_FAILED'))] + fn test_complete_tournament_not_participant() { + let (_, tournament_system) = setup_tournament_with_players(); + + tournament_system.start_tournament(TOURNAMENT_ID); + + tournament_system.complete_tournament(TOURNAMENT_ID, PLAYER3_ID); + } + + // This test verifies the tournament can be completed correctly + #[test] + fn test_complete_tournament() { + let (world, tournament_system) = setup_tournament_with_players(); + + tournament_system.start_tournament(TOURNAMENT_ID); + + tournament_system.complete_tournament(TOURNAMENT_ID, PLAYER1_ID); + + let tournament = get!(world, TOURNAMENT_ID, (Tournament)); + assert_eq!(tournament.status, TournamentStatus::Completed); + } + + // This test verifies the custom getter returns the same data stored in the world + #[test] + fn test_get_tournament() { + let (world, tournament_system) = setup_tournament(); + + let tournament_from_system = tournament_system.get_tournament(TOURNAMENT_ID); + let tournament_from_world = get!(world, TOURNAMENT_ID, (Tournament)); + + assert_eq!(tournament_from_system.tournament_id, tournament_from_world.tournament_id); + assert_eq!(tournament_from_system.name, tournament_from_world.name); + assert_eq!(tournament_from_system.status, tournament_from_world.status); + assert_eq!(tournament_from_system.entry_fee, tournament_from_world.entry_fee); + assert_eq!(tournament_from_system.max_participants, tournament_from_world.max_participants); + assert_eq!(tournament_from_system.current_participants, tournament_from_world.current_participants); + assert_eq!(tournament_from_system.prize_pool, tournament_from_world.prize_pool); + } +} From a7ee917c8e1f446d43521b2cdd6e193a638df089 Mon Sep 17 00:00:00 2001 From: Bosun <96661657+Bosun-Josh121@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:10:13 +0100 Subject: [PATCH 15/16] SeasonModel & Tests (#103) * branch * sozo build --- .../models/bytebeasts-Season-52f8bbb6.json | 437 +++++++++++++++++ .../bytebeasts-SeasonManager-57ed50e9.json | 451 ++++++++++++++++++ .../models/bytebeasts-Season-52f8bbb6.toml | 36 ++ .../bytebeasts-SeasonManager-57ed50e9.toml | 16 + src/lib.cairo | 1 + src/models/season.cairo | 411 ++++++++++++++++ 6 files changed, 1352 insertions(+) create mode 100644 manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json create mode 100644 manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json create mode 100644 manifests/dev/base/models/bytebeasts-Season-52f8bbb6.toml create mode 100644 manifests/dev/base/models/bytebeasts-SeasonManager-57ed50e9.toml create mode 100644 src/models/season.cairo diff --git a/manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json b/manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json new file mode 100644 index 0000000..dffe9a8 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json @@ -0,0 +1,437 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "seasonImpl", + "interface_name": "bytebeasts::models::season::Iseason" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::season::Season", + "members": [ + { + "name": "season_id", + "type": "core::integer::u64" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "start_date", + "type": "core::integer::u64" + }, + { + "name": "end_date", + "type": "core::integer::u64" + }, + { + "name": "is_active", + "type": "core::bool" + }, + { + "name": "active_players", + "type": "core::array::Array::" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::season::Iseason", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::season::Season" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::season::season::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json b/manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json new file mode 100644 index 0000000..88ee354 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json @@ -0,0 +1,451 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::layout::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::model::layout::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::layout::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::model::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::model::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::model::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::model::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::model::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::model::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::layout::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::model::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "season_managerImpl", + "interface_name": "bytebeasts::models::season::Iseason_manager" + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::season::Season", + "members": [ + { + "name": "season_id", + "type": "core::integer::u64" + }, + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "start_date", + "type": "core::integer::u64" + }, + { + "name": "end_date", + "type": "core::integer::u64" + }, + { + "name": "is_active", + "type": "core::bool" + }, + { + "name": "active_players", + "type": "core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "bytebeasts::models::season::SeasonManager", + "members": [ + { + "name": "manager_id", + "type": "core::integer::u64" + }, + { + "name": "seasons", + "type": "core::array::Array::" + } + ] + }, + { + "type": "interface", + "name": "bytebeasts::models::season::Iseason_manager", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "bytebeasts::models::season::SeasonManager" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "bytebeasts::models::season::season_manager::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/manifests/dev/base/models/bytebeasts-Season-52f8bbb6.toml b/manifests/dev/base/models/bytebeasts-Season-52f8bbb6.toml new file mode 100644 index 0000000..1c40478 --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-Season-52f8bbb6.toml @@ -0,0 +1,36 @@ +kind = "DojoModel" +class_hash = "0x7a8bee9882da24371365f5e6531ed532e9deb91c5b5173d7d230dec53c5c337" +original_class_hash = "0x7a8bee9882da24371365f5e6531ed532e9deb91c5b5173d7d230dec53c5c337" +abi = "manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json" +tag = "bytebeasts-Season" +manifest_name = "bytebeasts-Season-52f8bbb6" + +[[members]] +name = "season_id" +type = "u64" +key = true + +[[members]] +name = "name" +type = "felt252" +key = false + +[[members]] +name = "start_date" +type = "u64" +key = false + +[[members]] +name = "end_date" +type = "u64" +key = false + +[[members]] +name = "is_active" +type = "bool" +key = false + +[[members]] +name = "active_players" +type = "Array" +key = false diff --git a/manifests/dev/base/models/bytebeasts-SeasonManager-57ed50e9.toml b/manifests/dev/base/models/bytebeasts-SeasonManager-57ed50e9.toml new file mode 100644 index 0000000..1dc0d4a --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-SeasonManager-57ed50e9.toml @@ -0,0 +1,16 @@ +kind = "DojoModel" +class_hash = "0x6795f48396469dd05f2357a86bf37d0392c24d938bc0972006834ac365b62c" +original_class_hash = "0x6795f48396469dd05f2357a86bf37d0392c24d938bc0972006834ac365b62c" +abi = "manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json" +tag = "bytebeasts-SeasonManager" +manifest_name = "bytebeasts-SeasonManager-57ed50e9" + +[[members]] +name = "manager_id" +type = "u64" +key = true + +[[members]] +name = "seasons" +type = "Array" +key = false diff --git a/src/lib.cairo b/src/lib.cairo index 973eb26..b56d2fc 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -28,6 +28,7 @@ mod models { mod achievement_type; mod achievements; mod tournament; + mod season; mod leaderboard; } diff --git a/src/models/season.cairo b/src/models/season.cairo new file mode 100644 index 0000000..7174b98 --- /dev/null +++ b/src/models/season.cairo @@ -0,0 +1,411 @@ +use array::ArrayTrait; +use option::OptionTrait; + +#[derive(Drop, Serde, Clone)] +#[dojo::model] +pub struct Season { + #[key] + pub season_id: u64, + pub name: felt252, + pub start_date: u64, + pub end_date: u64, + pub is_active: bool, + pub active_players: Array, +} + +#[derive(Drop, Serde, Clone)] +#[dojo::model] +pub struct SeasonManager { + #[key] + pub manager_id: u64, + pub seasons: Array, +} + +#[generate_trait] +impl SeasonManagerImpl of SeasonManagerTrait { + fn create_season( + ref self: SeasonManager, + season_id: u64, + name: felt252, + start_date: u64, + end_date: u64, + is_active: bool, + active_players: Array + ) -> felt252 { + let new_season = Season { + season_id, + name, + start_date, + end_date, + is_active, + active_players, + }; + + self.seasons.append(new_season); + 'Season created successfully' + } + + fn update_season( + ref self: SeasonManager, + season_id: u64, + new_name: Option, + new_start_date: Option, + new_end_date: Option, + new_is_active: Option, + ) -> felt252 { + + let mut current_seasons = self.seasons; + self.seasons = ArrayTrait::new(); + let mut found = false; + let mut i = 0; + loop { + if i == current_seasons.len() { + break; + } + + let season = current_seasons.at(i).clone(); + + if season.season_id == season_id { + found = true; + let updated_season = Season { + season_id: season.season_id, + name: match new_name { + Option::Some(new_name) => new_name, + Option::None => season.name, + }, + start_date: match new_start_date { + Option::Some(new_start_date) => new_start_date, + Option::None => season.start_date, + }, + end_date: match new_end_date { + Option::Some(end_date) => end_date, + Option::None => season.end_date, + }, + is_active: match new_is_active { + Option::Some(is_active) => is_active, + Option::None => season.is_active, + }, + active_players: season.active_players.clone(), + }; + + self.seasons.append(updated_season); + } else { + + self.seasons.append(season.clone()); + } + + i += 1; + }; + + match found { + true => 'Season updated successfully', + false => 'Season not found', + } + } + + fn get_season(self: SeasonManager, season_id: u64) -> Season { + let mut i = 0; + loop { + if i == self.seasons.len() { + break; + } + + if *self.seasons.at(i).season_id == season_id { + break; + } + + i += 1; + }; + + self.seasons.at(i).clone() + } + + fn get_active_seasons(self: SeasonManager) -> Array { + let mut active_seasons = ArrayTrait::new(); + + let mut i = 0; + loop { + if i == self.seasons.len() { + break; + } + + let season = self.seasons.at(i); + if *season.is_active { + active_seasons.append(season.clone()); + } + + i += 1; + }; + + active_seasons + } + +fn delete_season(ref self: SeasonManager, season_id: u64) -> felt252 { + let mut updated_seasons = ArrayTrait::new(); + let mut found = false; + + let mut i = 0; + loop { + if i == self.seasons.len() { + break; + } + + let season = self.seasons.at(i); + if *season.season_id != season_id { + updated_seasons.append(season.clone()); + } else { + found = true; + } + + i += 1; + }; + + self.seasons = updated_seasons; + + match found { + true => 'Season deleted successfully', + false => 'Season not found', + } +} + +fn update_active_players( + ref self: SeasonManager, + season_id: u64, + new_active_players: Array +) -> felt252 { + + let mut current_seasons = self.seasons; + self.seasons = ArrayTrait::new(); + let mut found = false; + let mut i = 0; + loop { + if i == current_seasons.len() { + break; + } + let season = current_seasons.at(i).clone(); + + if season.season_id == season_id { + found = true; + let updated_season = Season { + season_id: season.season_id, + name: season.name, + start_date: season.start_date, + end_date: season.end_date , + is_active: season.is_active, + active_players: new_active_players.clone(), + }; + self.seasons.append(updated_season); + } else { + + self.seasons.append(season.clone()); + } + + i += 1; + }; + + match found { + true => 'active players updated', + false => 'Season not found', + } +} + +fn add_player_to_season(ref self: SeasonManager, season_id: u64, player_id: u64) -> felt252 { + let mut i = 0; + let mut updated = false; + let mut result_message = 'Season not found'; + loop { + if i == self.seasons.len() { + break; + } + + let mut season = self.seasons.at(i).clone(); + + if season.season_id == season_id { + let mut j = 0; + let mut player_exists = false; + + loop { + if j == season.active_players.len() { + break; + } + + if *season.active_players.at(j) == player_id { + player_exists = true; + break; + } + + j += 1; + }; + + if player_exists { + result_message = 'Player already in season'; + break; + } + season.active_players.append(player_id); + self.update_active_players( + season_id: season.season_id, + new_active_players: season.active_players, + ); + updated = true; + result_message = 'Player added successfully'; + break; + } + + i += 1; + }; + + result_message +} + + +} + +#[cfg(test)] +mod tests { + use super::{Season, SeasonManager, SeasonManagerImpl}; + use array::ArrayTrait; + + #[test] + fn test_create_season() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + let result = manager.create_season(1, 'Season One', 1672531200, 1675219599, true, ArrayTrait::new()); + assert(result == 'Season created successfully', 'Failed to create a season'); + assert(manager.seasons.len() == 1, 'list should contain 1 item'); + } + + #[test] + fn test_update_season() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + manager.create_season(1, 'Initial Season', 1672531200, 1675219599, true, ArrayTrait::new()); + + let result = manager.update_season( + 1, + Option::Some('Updated Season'), + Option::None, + Option::Some(1677803999), + Option::Some(false), + ); + + assert(result == 'Season updated successfully', 'Failed to update the season'); + let updated_season = manager.get_season(1); + assert(updated_season.name == 'Updated Season', 'Name was not updated'); + assert(updated_season.end_date == 1677803999, 'End date was not updated'); + assert(!updated_season.is_active, 'is_active was not updated'); + } + + #[test] + fn test_get_season() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + manager.create_season(1, 'Season A', 1672531200, 1675219599, true, ArrayTrait::new()); + let season = manager.get_season(1); + assert(season.season_id == 1, 'Incorrect season ID retrieved'); + assert(season.name == 'Season A', 'Incorrect season name retrieved'); + } + + #[test] + fn test_get_active_seasons() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + manager.create_season(1, 'Active Season', 1672531200, 1675219599, true, ArrayTrait::new()); + manager.create_season(2, 'Inactive Season', 1672531200, 1675219599, false, ArrayTrait::new()); + + let active_seasons = manager.get_active_seasons(); + assert(active_seasons.len() == 1, 'one active season should exist'); + assert(*active_seasons.at(0).season_id == 1, 'wrong active season retrieved'); + } + + #[test] + fn test_delete_season() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + manager.create_season(1, 'To Be Deleted', 1672531200, 1675219599, true, ArrayTrait::new()); + let result = manager.delete_season(1); + assert(result == 'Season deleted successfully', 'Failed to delete the season'); + assert(manager.seasons.len() == 0, 'list should be empty'); + } + + #[test] + fn test_update_active_players() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + manager.create_season(1, 'Test Season', 1672531200, 1675219599, true, ArrayTrait::new()); + + let mut new_active_players = ArrayTrait::new(); + new_active_players.append(101); + new_active_players.append(102); + + let result = manager.update_active_players(1, new_active_players.clone()); + assert(result == 'active players updated', 'unsuccessful player update'); + + let updated_season = manager.get_season(1); + assert(updated_season.active_players.len() == 2, 'players count is incorrect'); + assert(*updated_season.active_players.at(0) == 101, 'First player ID is incorrect'); + assert(*updated_season.active_players.at(1) == 102, 'Second player ID is incorrect'); + } + + #[test] + fn test_add_player_to_season() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + manager.create_season(1, 'Test Season', 1672531200, 1675219599, true, ArrayTrait::new() ); + + let result = manager.add_player_to_season(1, 101); + assert(result == 'Player added successfully', 'Failed to add player to season'); + + let season = manager.clone().get_season(1); + assert(season.active_players.len() == 1, 'Player count is incorrect'); + assert(*season.active_players.at(0) == 101, 'Player ID is incorrect'); + + let duplicate_result = manager.add_player_to_season(1, 101); + assert(duplicate_result == 'Player already in season', 'should fail'); + + let season_after_duplicate = manager.clone().get_season(1); + assert(season_after_duplicate.active_players.len() == 1, 'count should not increase'); + + let non_existent_result = manager.add_player_to_season(99, 102); + assert(non_existent_result == 'Season not found', 'Non-existent season addition'); + } + + #[test] + fn test_non_existent_season_operations() { + let mut manager = SeasonManager { + manager_id: 1, + seasons: ArrayTrait::new(), + }; + + let delete_result = manager.delete_season(99); + assert(delete_result == 'Season not found', 'Should return Season not found'); + + let update_result = manager.update_season( + 99, + Option::Some('Nonexistent'), + Option::None, + Option::None, + Option::None, + ); + assert(update_result == 'Season not found', 'Should return Season not found'); + } +} + From 770d8f013b21083b7eb35c0336b6424fdfc3323d Mon Sep 17 00:00:00 2001 From: NEVEROV iaroslav Date: Mon, 2 Dec 2024 11:32:41 +0100 Subject: [PATCH 16/16] refactor and rename fn upgrade_entry_stats and add negative test. Leaderboard's test file moved to test directory. --- src/lib.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.cairo b/src/lib.cairo index b56d2fc..ae61d22 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -35,6 +35,6 @@ mod models { mod tests { mod test_battle; mod test_bag; - mod test_leaderboard; mod test_tournament; + mod test_leaderboard; }