From 47eb7c1a09250eb364153b15b68077ee58852ae3 Mon Sep 17 00:00:00 2001 From: bal7hazar Date: Thu, 7 Nov 2024 11:43:25 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Ephemeral=20trophies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trophy/src/components/achievable.cairo | 18 ++++- packages/trophy/src/events/index.cairo | 2 + packages/trophy/src/events/trophy.cairo | 72 +++++++++++++++---- packages/trophy/src/store.cairo | 4 +- .../trophy/src/tests/mocks/achiever.cairo | 6 ++ .../trophy/src/tests/test_achievable.cairo | 44 ++++++++---- 6 files changed, 119 insertions(+), 27 deletions(-) diff --git a/packages/trophy/src/components/achievable.cairo b/packages/trophy/src/components/achievable.cairo index 70f2a5f..0700828 100644 --- a/packages/trophy/src/components/achievable.cairo +++ b/packages/trophy/src/components/achievable.cairo @@ -43,6 +43,8 @@ mod AchievableComponent { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, @@ -54,7 +56,21 @@ mod AchievableComponent { let store: Store = StoreTrait::new(world); // [Event] Emit achievement creation - store.create(id, hidden, index, points, group, icon, title, description, tasks, data); + store + .create( + id, + hidden, + index, + points, + start, + end, + group, + icon, + title, + description, + tasks, + data + ); } fn progress( diff --git a/packages/trophy/src/events/index.cairo b/packages/trophy/src/events/index.cairo index ee1f1e8..9908a4a 100644 --- a/packages/trophy/src/events/index.cairo +++ b/packages/trophy/src/events/index.cairo @@ -12,6 +12,8 @@ pub struct TrophyCreation { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, diff --git a/packages/trophy/src/events/trophy.cairo b/packages/trophy/src/events/trophy.cairo index 5600a20..e9cfd47 100644 --- a/packages/trophy/src/events/trophy.cairo +++ b/packages/trophy/src/events/trophy.cairo @@ -6,10 +6,11 @@ use bushido_trophy::types::task::{Task, TaskTrait}; // Errors pub mod errors { - pub const TROPHY_INVALID_ID: felt252 = 'TrophyCreation: invalid id'; - pub const TROPHY_INVALID_TITLE: felt252 = 'TrophyCreation: invalid title'; - pub const TROPHY_INVALID_DESCRIPTION: felt252 = 'TrophyCreation: invalid desc.'; - pub const TROPHY_INVALID_TASKS: felt252 = 'TrophyCreation: invalid tasks.'; + pub const TROPHY_INVALID_ID: felt252 = 'Trophy: invalid id'; + pub const TROPHY_INVALID_TITLE: felt252 = 'Trophy: invalid title'; + pub const TROPHY_INVALID_DESCRIPTION: felt252 = 'Trophy: invalid desc.'; + pub const TROPHY_INVALID_TASKS: felt252 = 'Trophy: invalid tasks.'; + pub const TROPHY_INVALID_DURATION: felt252 = 'Trophy: invalid duration.'; } // Implementations @@ -22,6 +23,8 @@ impl TrophyImpl of TrophyTrait { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, @@ -34,8 +37,11 @@ impl TrophyImpl of TrophyTrait { TrophyAssert::assert_valid_id(id); TrophyAssert::assert_valid_title(title); TrophyAssert::assert_valid_description(@description); + TrophyAssert::assert_valid_duration(start, end); // [Return] TrophyCreation - TrophyCreation { id, hidden, index, points, group, icon, title, description, tasks, data } + TrophyCreation { + id, hidden, index, points, start, end, group, icon, title, description, tasks, data + } } } @@ -60,6 +66,11 @@ impl TrophyAssert of AssertTrait { fn assert_valid_tasks(tasks: Span) { assert(tasks.len() > 0, errors::TROPHY_INVALID_TASKS); } + + #[inline] + fn assert_valid_duration(start: u64, end: u64) { + assert(end >= start, errors::TROPHY_INVALID_DURATION); + } } #[cfg(test)] @@ -80,17 +91,32 @@ mod tests { const TITLE: felt252 = 'TITLE'; const ICON: felt252 = 'ICON'; const TASK_ID: felt252 = 'TASK'; + const START: u64 = 100; + const END: u64 = 200; #[test] fn test_achievement_creation_new() { let tasks: Array = array![TaskTrait::new(TASK_ID, TOTAL, "TASK DESCRIPTION"),]; let achievement = TrophyTrait::new( - ID, HIDDEN, INDEX, POINTS, GROUP, ICON, TITLE, "DESCRIPTION", tasks.span(), "DATA" + ID, + HIDDEN, + INDEX, + POINTS, + START, + END, + GROUP, + ICON, + TITLE, + "DESCRIPTION", + tasks.span(), + "DATA" ); assert_eq!(achievement.id, ID); assert_eq!(achievement.hidden, HIDDEN); assert_eq!(achievement.index, INDEX); assert_eq!(achievement.points, POINTS); + assert_eq!(achievement.start, START); + assert_eq!(achievement.end, END); assert_eq!(achievement.group, GROUP); assert_eq!(achievement.icon, ICON); assert_eq!(achievement.title, TITLE); @@ -100,28 +126,50 @@ mod tests { } #[test] - #[should_panic(expected: ('TrophyCreation: invalid id',))] + #[should_panic(expected: ('Trophy: invalid id',))] fn test_achievement_creation_new_invalid_id() { let tasks: Array = array![TaskTrait::new(TASK_ID, TOTAL, "TASK DESCRIPTION"),]; TrophyTrait::new( - 0, HIDDEN, INDEX, POINTS, GROUP, ICON, TITLE, "DESCRIPTION", tasks.span(), "" + 0, + HIDDEN, + INDEX, + POINTS, + START, + END, + GROUP, + ICON, + TITLE, + "DESCRIPTION", + tasks.span(), + "" ); } #[test] - #[should_panic(expected: ('TrophyCreation: invalid title',))] + #[should_panic(expected: ('Trophy: invalid title',))] fn test_achievement_creation_new_invalid_title() { let tasks: Array = array![TaskTrait::new(TASK_ID, TOTAL, "TASK DESCRIPTION"),]; TrophyTrait::new( - ID, HIDDEN, INDEX, POINTS, GROUP, ICON, 0, "DESCRIPTION", tasks.span(), "" + ID, HIDDEN, INDEX, POINTS, START, END, GROUP, ICON, 0, "DESCRIPTION", tasks.span(), "" ); } #[test] - #[should_panic(expected: ('TrophyCreation: invalid desc.',))] + #[should_panic(expected: ('Trophy: invalid desc.',))] fn test_achievement_creation_new_invalid_description() { let tasks: Array = array![TaskTrait::new(TASK_ID, TOTAL, "TASK DESCRIPTION"),]; - TrophyTrait::new(ID, HIDDEN, INDEX, POINTS, GROUP, ICON, TITLE, "", tasks.span(), ""); + TrophyTrait::new( + ID, HIDDEN, INDEX, POINTS, START, END, GROUP, ICON, TITLE, "", tasks.span(), "" + ); + } + + #[test] + #[should_panic(expected: ('Trophy: invalid duration.',))] + fn test_achievement_creation_new_invalid_duration() { + let tasks: Array = array![TaskTrait::new(TASK_ID, TOTAL, "TASK DESCRIPTION"),]; + TrophyTrait::new( + ID, HIDDEN, INDEX, POINTS, START, 0, GROUP, ICON, TITLE, "DESCRIPTION", tasks.span(), "" + ); } } diff --git a/packages/trophy/src/store.cairo b/packages/trophy/src/store.cairo index 26a5840..f9cd6cf 100644 --- a/packages/trophy/src/store.cairo +++ b/packages/trophy/src/store.cairo @@ -41,6 +41,8 @@ impl StoreImpl of StoreTrait { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, @@ -49,7 +51,7 @@ impl StoreImpl of StoreTrait { data: ByteArray, ) { let event: TrophyCreation = TrophyTrait::new( - id, hidden, index, points, group, icon, title, description, tasks, data + id, hidden, index, points, start, end, group, icon, title, description, tasks, data ); self.world.emit_event(@event); } diff --git a/packages/trophy/src/tests/mocks/achiever.cairo b/packages/trophy/src/tests/mocks/achiever.cairo index 06afb9f..ecd6bd8 100644 --- a/packages/trophy/src/tests/mocks/achiever.cairo +++ b/packages/trophy/src/tests/mocks/achiever.cairo @@ -10,6 +10,8 @@ trait IAchiever { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, @@ -66,6 +68,8 @@ pub mod Achiever { hidden: bool, index: u8, points: u16, + start: u64, + end: u64, group: felt252, icon: felt252, title: felt252, @@ -81,6 +85,8 @@ pub mod Achiever { hidden, index, points, + start, + end, group, icon, title, diff --git a/packages/trophy/src/tests/test_achievable.cairo b/packages/trophy/src/tests/test_achievable.cairo index 306f2a7..19af1d1 100644 --- a/packages/trophy/src/tests/test_achievable.cairo +++ b/packages/trophy/src/tests/test_achievable.cairo @@ -29,11 +29,14 @@ const TASK_ID: felt252 = 'TASK'; const HIDDEN: bool = false; const INDEX: u8 = 0; const POINTS: u16 = 10; +const START: u64 = 100; +const END: u64 = 200; const TOTAL: u32 = 100; const COUNT: u32 = 1; const GROUP: felt252 = 'Group'; const ICON: felt252 = 'fa-khanda'; const TITLE: felt252 = 'Title'; + // Tests #[test] @@ -44,7 +47,20 @@ fn test_achievable_create() { let tasks = array![TaskTrait::new(TASK_ID, TOTAL, "Description")].span(); systems .achiever - .create(TROPHY_ID, HIDDEN, INDEX, POINTS, GROUP, ICON, TITLE, "Description", tasks, ""); + .create( + TROPHY_ID, + HIDDEN, + INDEX, + POINTS, + START, + END, + GROUP, + ICON, + TITLE, + "Description", + tasks, + "" + ); let contract_event = starknet::testing::pop_log::(world.dispatcher.contract_address) .unwrap(); match contract_event { @@ -53,18 +69,20 @@ fn test_achievable_create() { assert_eq!(*event.values.at(0), 0); assert_eq!(*event.values.at(1), INDEX.into()); assert_eq!(*event.values.at(2), POINTS.into()); - assert_eq!(*event.values.at(3), GROUP.into()); - assert_eq!(*event.values.at(4), ICON.into()); - assert_eq!(*event.values.at(5), TITLE.into()); - assert_eq!(*event.values.at(6), 0); - assert_eq!(*event.values.at(7), 'Description'); - assert_eq!(*event.values.at(8), 11); - assert_eq!(*event.values.at(9), 1); - assert_eq!(*event.values.at(10), TASK_ID); - assert_eq!(*event.values.at(11), TOTAL.into()); - assert_eq!(*event.values.at(12), 0); - assert_eq!(*event.values.at(13), 'Description'); - assert_eq!(*event.values.at(14), 11); + assert_eq!(*event.values.at(3), START.into()); + assert_eq!(*event.values.at(4), END.into()); + assert_eq!(*event.values.at(5), GROUP.into()); + assert_eq!(*event.values.at(6), ICON.into()); + assert_eq!(*event.values.at(7), TITLE.into()); + assert_eq!(*event.values.at(8), 0); + assert_eq!(*event.values.at(9), 'Description'); + assert_eq!(*event.values.at(10), 11); + assert_eq!(*event.values.at(11), 1); + assert_eq!(*event.values.at(12), TASK_ID); + assert_eq!(*event.values.at(13), TOTAL.into()); + assert_eq!(*event.values.at(14), 0); + assert_eq!(*event.values.at(15), 'Description'); + assert_eq!(*event.values.at(16), 11); }, _ => {}, }