From 058ddb193e2fd4b479b3d5d53d72b42736fd5034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Araya=20Jim=C3=A9nez?= Date: Tue, 10 Sep 2024 20:04:33 -0600 Subject: [PATCH] feat: add first leaderboard model implementation with tests --- .../bytebeasts-Leaderboard-7e680376.json | 471 ++++++++++++++++++ .../bytebeasts-LeaderboardEntry-7237950c.json | 445 +++++++++++++++++ .../bytebeasts-Leaderboard-7e680376.toml | 31 ++ .../bytebeasts-LeaderboardEntry-7237950c.toml | 46 ++ src/lib.cairo | 1 + src/models/leaderboard.cairo | 156 ++++++ 6 files changed, 1150 insertions(+) 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 create mode 100644 src/models/leaderboard.cairo 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..5d118a5 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json @@ -0,0 +1,471 @@ +[ + { + "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_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "rank", + "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..bfbfec1 --- /dev/null +++ b/manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json @@ -0,0 +1,445 @@ +[ + { + "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_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "player_name", + "type": "core::felt252" + }, + { + "name": "score", + "type": "core::integer::u32" + }, + { + "name": "rank", + "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..37a084a --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml @@ -0,0 +1,31 @@ +kind = "DojoModel" +class_hash = "0x551cf89bdd06c5be266b0260c53cc9740563e6b82dc6f52bd27bf3353577c3e" +original_class_hash = "0x551cf89bdd06c5be266b0260c53cc9740563e6b82dc6f52bd27bf3353577c3e" +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..5e3400c --- /dev/null +++ b/manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml @@ -0,0 +1,46 @@ +kind = "DojoModel" +class_hash = "0x14d2dc52c426f057f139d65eb631734508c6604236152a7f8e0b72319e7ea71" +original_class_hash = "0x14d2dc52c426f057f139d65eb631734508c6604236152a7f8e0b72319e7ea71" +abi = "manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json" +tag = "bytebeasts-LeaderboardEntry" +manifest_name = "bytebeasts-LeaderboardEntry-7237950c" + +[[members]] +name = "player_address" +type = "ContractAddress" +key = true + +[[members]] +name = "player_name" +type = "felt252" +key = false + +[[members]] +name = "score" +type = "u32" +key = false + +[[members]] +name = "rank" +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/lib.cairo b/src/lib.cairo index 6738c1a..4b1940c 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -22,6 +22,7 @@ mod models { mod potion; mod role; mod world_elements; + mod leaderboard; } mod tests { diff --git a/src/models/leaderboard.cairo b/src/models/leaderboard.cairo new file mode 100644 index 0000000..cc0cb5d --- /dev/null +++ b/src/models/leaderboard.cairo @@ -0,0 +1,156 @@ +use starknet::ContractAddress; +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_address: ContractAddress, // 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 +} + + +#[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 { + fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252>; + fn is_full(self: @Leaderboard) -> bool; +} + +#[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); + // Update timestamp + self.last_updated = starknet::get_block_timestamp(); + Result::Ok(()) + } + + fn is_full(self: @Leaderboard) -> bool { + self.entries.len() >= MAX_ENTRIES + } + +} + + +#[cfg(test)] +mod tests { + use starknet::ContractAddress; + use core::{ + result::{Result, ResultTrait}, + array::ArrayTrait, + }; + use super::{LeaderboardTrait, MAX_ENTRIES}; + use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry}; + + fn create_mock_entry(address: ContractAddress, name: felt252, score: u32, wins: u32, losses: u32, highest_score: u32, is_active: bool) -> LeaderboardEntry { + LeaderboardEntry { + player_address: address, + 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(starknet::get_contract_address(), 'Alice', 100, 20, 5, 1000, true); + + leaderboard.add_entry(entry).expect('Failed to add entry'); + + assert_eq!(leaderboard.entries.len(), 1, "Leaderboard should have 1 entry"); + assert_eq!(leaderboard.entries.at(0).player_name, @'Alice', "Wrong player name"); + assert_eq!(leaderboard.entries.at(0).rank, @1, "First entry should have rank 1"); + } + + #[test] + fn test_add_multiple_entries() { + let mut leaderboard = create_empty_leaderboard(); + let entry1 = create_mock_entry(starknet::get_contract_address(), 'Alice', 100, 20, 5, 1000, true); + let entry2 = create_mock_entry(starknet::get_contract_address(), 'Bob', 200, 30, 10, 1500, true); + + leaderboard.add_entry(entry1).expect('Failed to add entry1'); + leaderboard.add_entry(entry2).expect('Failed to add entry2'); + + assert_eq!(leaderboard.entries.len(), 2, "Leaderboard should have 2 entries"); + assert_eq!(leaderboard.entries.at(0).rank, @1, "First entry should have rank 1"); + assert_eq!(leaderboard.entries.at(1).rank, @2, "Second entry should have rank 2"); + } + + #[test] + fn test_leaderboard_full() { + let mut leaderboard = create_empty_leaderboard(); + let entry = create_mock_entry(starknet::get_contract_address(), 'Player', 100, 10, 5, 500, true); + + // Add MAX_ENTRIES to the leaderboard + let mut i = 0; + while i < MAX_ENTRIES { + leaderboard.add_entry(entry).expect('Failed to add entry'); + i += 1; + }; + + assert_eq!(leaderboard.entries.len(), MAX_ENTRIES, "Leaderboard should be full"); + assert!(leaderboard.is_full(), "Leaderboard should report as full"); + + let result = leaderboard.add_entry(entry); + assert!(result.is_err(), "Should not be able to add entry to full leaderboard"); + } + + #[test] + fn test_entry_properties() { + let mut leaderboard = create_empty_leaderboard(); + let entry = create_mock_entry(starknet::get_contract_address(), 'Alice', 100, 20, 5, 1000, true); + + leaderboard.add_entry(entry).expect('Failed to add entry'); + + let added_entry = leaderboard.entries.at(0); + assert_eq!(added_entry.player_name, @'Alice', "Wrong player name"); + assert_eq!(added_entry.score, @100, "Wrong score"); + assert_eq!(added_entry.wins, @20, "Wrong number of wins"); + assert_eq!(added_entry.losses, @5, "Wrong number of losses"); + assert_eq!(added_entry.highest_score, @1000, "Wrong highest score"); + assert_eq!(added_entry.is_active, @true,"Player should be active"); + } +}