From 1b1d278a0e413baa53aec60e4855bf377775e24b Mon Sep 17 00:00:00 2001 From: Jackliu-miaozi <71253778+Jackliu-miaozi@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:36:26 +0800 Subject: [PATCH] tamagotchi_shop --- contracts/04-tamagotchi-shop/io/src/lib.rs | 45 +++++- contracts/04-tamagotchi-shop/src/lib.rs | 154 ++++++++++++++++++++- 2 files changed, 193 insertions(+), 6 deletions(-) diff --git a/contracts/04-tamagotchi-shop/io/src/lib.rs b/contracts/04-tamagotchi-shop/io/src/lib.rs index 01c3d10a..adb11e32 100644 --- a/contracts/04-tamagotchi-shop/io/src/lib.rs +++ b/contracts/04-tamagotchi-shop/io/src/lib.rs @@ -1,13 +1,24 @@ #![no_std] -use gmeta::Metadata; -use gstd::prelude::*; +use codec::{Decode, Encode}; +use gmeta::{In, InOut, Metadata, Out}; +use gstd::{prelude::*, ActorId}; #[derive(Default, Encode, Decode, TypeInfo)] #[codec(crate = gstd::codec)] #[scale_info(crate = gstd::scale_info)] pub struct Tamagotchi { // TODO: 0️⃣ Copy fields from previous lesson and push changes to the master branch + pub name: String, + pub date_of_birth: u64, + pub owner: ActorId, + pub fed: u64, + pub fed_block: u64, + pub entertained: u64, + pub entertained_block: u64, + pub slept: u64, + pub slept_block: u64, + pub approved_account: Option, // TODO: 2️⃣ Add new fields } @@ -16,6 +27,14 @@ pub struct Tamagotchi { #[scale_info(crate = gstd::scale_info)] pub enum TmgAction { // TODO: 0️⃣ Copy actions from previous lesson and push changes to the master branch + Name, + Age, + Feed, + Entertain, + Sleep, + Transfer(ActorId), + Approve(ActorId), + RevokeApproval, // TODO: 3️⃣ Add new actions } @@ -24,6 +43,14 @@ pub enum TmgAction { #[scale_info(crate = gstd::scale_info)] pub enum TmgEvent { // TODO: 0️⃣ Copy events from previous lesson and push changes to the master branch + Name(String), + Age(u64), + Fed, + Entertained, + Slept, + Transferred(ActorId), + Approved(ActorId), + ApprovalRevoked, // TODO: 4️⃣ Add new events } @@ -31,10 +58,18 @@ pub struct ProgramMetadata; // TODO: 0️⃣ Copy `Metadata` from the first lesson and push changes to the master branch impl Metadata for ProgramMetadata { - type Init = (); - type Handle = (); - type State = (); + type Init = In; + type Handle = InOut; + type State = Out; type Reply = (); type Others = (); type Signal = (); } + +pub const HUNGER_PER_BLOCK: u64 = 1; +pub const BOREDOM_PER_BLOCK: u64 = 2; +pub const ENERGY_PER_BLOCK: u64 = 2; + +pub const FILL_PER_FEED: u64 = 1000; +pub const FILL_PER_ENTERTAINMENT: u64 = 1000; +pub const FILL_PER_SLEEP: u64 = 1000; \ No newline at end of file diff --git a/contracts/04-tamagotchi-shop/src/lib.rs b/contracts/04-tamagotchi-shop/src/lib.rs index d2391618..9ff2f388 100644 --- a/contracts/04-tamagotchi-shop/src/lib.rs +++ b/contracts/04-tamagotchi-shop/src/lib.rs @@ -1,22 +1,174 @@ #![no_std] #[allow(unused_imports)] -use gstd::prelude::*; +use gstd::{exec, msg, prelude::*, ActorId}; +use tamagotchi_shop_io::*; + +#[derive(Default, Encode, Decode, TypeInfo)] +#[codec(crate = gstd::codec)] +#[scale_info(crate = gstd::scale_info)] +pub struct Tamagotchi { + pub name: String, + pub date_of_birth: u64, + pub owner: ActorId, + pub fed: u64, + pub fed_block: u64, + pub entertained: u64, + pub entertained_block: u64, + pub slept: u64, + pub slept_block: u64, + pub approved_account: Option, +} +impl Tamagotchi { + fn current_fed(&mut self) -> u64 { + let a: u64 = + self.fed - (HUNGER_PER_BLOCK as u64) * ((exec::block_height() as u64) - self.fed_block); + a + } + fn current_entertained(&mut self) -> u64 { + let b: u64 = self.entertained + - (BOREDOM_PER_BLOCK as u64) * ((exec::block_height() as u64) - self.entertained_block); + b + } + fn current_slept(&mut self) -> u64 { + let c: u64 = self.slept + - (ENERGY_PER_BLOCK as u64) * ((exec::block_height() as u64) - self.slept_block); + c + } +} +static mut TAMAGOTCHI: Option = None; // TODO: 5️⃣ Add the `approve_tokens` function #[no_mangle] extern fn init() { // TODO: 0️⃣ Copy the `init` function from the previous lesson and push changes to the master branch + let initname = msg::load().expect("unable to load name"); + let birthdate = exec::block_height() as u64; + let fedblock = exec::block_height() as u64; + let entertainedblock = exec::block_height() as u64; + let sleptblock = exec::block_height() as u64; + let tmg = Tamagotchi { + name: initname, + date_of_birth: birthdate, + owner: msg::source(), + fed: 1000, + fed_block: fedblock, + entertained: 5000, + entertained_block: entertainedblock, + slept: 2000, + slept_block: sleptblock, + approved_account: None, + }; + unsafe { + TAMAGOTCHI = Some(tmg); + }; } #[no_mangle] extern fn handle() { // TODO: 0️⃣ Copy the `handle` function from the previous lesson and push changes to the master branch + let action: TmgAction = msg::load().expect("unable to load action"); + let tmg = unsafe { TAMAGOTCHI.get_or_insert(Default::default()) }; + if msg::source() == tmg.owner { + match action { + TmgAction::Name => { + msg::reply(TmgEvent::Name(tmg.name.clone()), 0) + .expect("Error in a reply'tamagotchi::name'"); + } + TmgAction::Age => { + let age = exec::block_timestamp() - tmg.date_of_birth; + msg::reply(TmgEvent::Age(age), 0).expect("Error in a reply'tamagotchi::age'"); + } + TmgAction::Feed => { + if tmg.current_fed() <= 9000 { + let fed = tmg.fed + FILL_PER_FEED; + msg::reply(TmgEvent::Fed, 0).expect("Error in a reply'tamagotchi::fed'"); + tmg.fed = fed; + tmg.fed_block = exec::block_height() as u64; + tmg.entertained = tmg.current_entertained(); + tmg.slept = tmg.current_slept(); + } else { + let fedblock = exec::block_height() as u64; + tmg.fed = 10000; + tmg.fed_block = fedblock; + tmg.entertained = tmg.current_entertained(); + tmg.slept = tmg.current_slept(); + msg::reply(TmgEvent::Fed, 1).expect("Error in a reply'tamagotchi::fed'"); + } + } + TmgAction::Entertain => { + if tmg.current_entertained() <= 9000 { + let entertained = tmg.entertained + FILL_PER_ENTERTAINMENT; + msg::reply(TmgEvent::Entertained, 0) + .expect("Error in a reply'tamagotchi::entertained'"); + tmg.entertained = entertained; + tmg.entertained_block = exec::block_height() as u64; + tmg.fed = tmg.current_fed(); + tmg.slept = tmg.current_slept(); + } else { + let entertainedblock = exec::block_height() as u64; + tmg.entertained = 10000; + tmg.entertained_block = entertainedblock; + tmg.fed = tmg.current_fed(); + tmg.slept = tmg.current_slept(); + msg::reply(TmgEvent::Entertained, 1) + .expect("Error in a reply'tamagotchi::entertained'"); + } + } + TmgAction::Sleep => { + if tmg.current_slept() <= 9000 { + let slept = tmg.slept + FILL_PER_SLEEP; + msg::reply(TmgEvent::Slept, 0).expect("Error in a reply'tamagotchi::slept'"); + tmg.slept = slept; + tmg.slept_block = exec::block_height() as u64; + tmg.fed = tmg.current_fed(); + tmg.entertained = tmg.current_entertained(); + } else { + let sleptblock = exec::block_height() as u64; + tmg.slept = 10000; + tmg.slept_block = sleptblock; + tmg.fed = tmg.current_fed(); + tmg.entertained = tmg.current_entertained(); + msg::reply(TmgEvent::Slept, 1).expect("Error in a reply'tamagotchi::slept'"); + } + } + TmgAction::Transfer(account) => { + tmg.owner = account; + msg::reply(TmgEvent::Transferred(account), 0) + .expect("Error in a reply'tamagotchi::transferred'"); + } + TmgAction::Approve(account) => { + tmg.approved_account = Some(account); + msg::reply(TmgEvent::Approved(account), 0) + .expect("Error in a reply'tamagotchi::approved'"); + } + TmgAction::RevokeApproval => { + tmg.approved_account = None; + msg::reply(TmgEvent::ApprovalRevoked, 0) + .expect("Error in a reply'tamagotchi::approval_revoked'"); + } + } + } else if msg::source() == tmg.approved_account.unwrap_or_default() { + match action { + TmgAction::Transfer(account) => { + tmg.owner = account; + msg::reply(TmgEvent::Transferred(account), 0) + .expect("Error in a reply'tamagotchi::transfered'"); + } + _ => { + panic!("You are not the approved people of this tamagotchi"); + } + } + } else { + panic!("You are not the owner of this tamagotchi"); + } // TODO; 6️⃣ Add handling new actions } #[no_mangle] extern fn state() { // TODO: 0️⃣ Copy the `handle` function from the previous lesson and push changes to the master branch + let tmg = unsafe { TAMAGOTCHI.take().expect("Unexpected error in taking state") }; + msg::reply(tmg, 0).expect("Failed to share state"); }