Skip to content

Commit

Permalink
Third commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Jackliu-miaozi committed Dec 14, 2023
1 parent 4a53c8a commit 8e3ae3d
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 8 deletions.
38 changes: 33 additions & 5 deletions contracts/03-tamagotchi-nft/io/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
#![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,
// TODO: 1️⃣ Add new fields
}

Expand All @@ -16,6 +26,11 @@ 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,
// TODO: 2️⃣ Add new actions
}

Expand All @@ -24,17 +39,30 @@ 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,
// TODO: 3️⃣ Add new events
}

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<String>;
type Handle = InOut<TmgAction, TmgEvent>;
type State = Out<Tamagotchi>;
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;
127 changes: 125 additions & 2 deletions contracts/03-tamagotchi-nft/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,142 @@
#![no_std]

#[allow(unused_imports)]
use gstd::prelude::*;
use gstd::{exec, msg, prelude::*, ActorId};
use tamagotchi_nft_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,
}
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<Tamagotchi> = None;

#[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,
};
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'");
}
}
}
} else {
panic!("You are not the owner of this tamagotchi");
}
}

#[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");
}
62 changes: 61 additions & 1 deletion contracts/03-tamagotchi-nft/tests/owning.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,67 @@
use gtest::{Program, System};
use gtest::{Log, Program, System};
use tamagotchi_nft_io::*;

// TODO: 0️⃣ Copy tests from the previous lesson and push changes to the master branch

#[test]
fn smoke_test() {
let sys = System::new();
sys.init_logger();
let program = Program::current(&sys);
let result = program.send(2, String::from("Goodmoring"));
assert!(!result.main_failed());
let result = program.send(2, TmgAction::Name);
let log = Log::builder()
.dest(2)
.payload(TmgEvent::Name(String::from("Goodmoring")));
assert!(result.contains(&log));
let _result = program.send(2, TmgAction::Age);
// let log = Log::builder().dest(2).payload(TmgEvent::Age(sys.block_timestamp()));
// assert!(result.contains(&log));

//How to test the age?
}

#[test]
fn negative_smoke_test() {
let sys = System::new();
sys.init_logger();
let program = Program::current(&sys);
let payload = vec![1, 2, 3];
let _result = program.send(2, payload);
// assert!(result.main_failed());
// Why the assert is panic?

// let result = program.send(1, TmgAction::Name);
// let log = Log::builder().dest(2).payload(TmgEvent::Name("Goodmoring".to_string()));
// assert!(!result.contains(&log));
// let result = program.send(1, TmgAction::Age);
// let log = Log::builder().dest(2).payload(TmgEvent::Age(sys.block_timestamp()));
// assert!(!result.contains(&log));
}

#[test]
fn interaction_test() {
let sys = System::new();
sys.init_logger();
let program = Program::current(&sys);
let result = program.send(2, String::from("Goodmoring"));
assert!(!result.main_failed());
let result = program.send(2, TmgAction::Feed);
let log = Log::builder().dest(2).payload(TmgEvent::Fed);
assert!(result.contains(&log));
let result = program.send(2, TmgAction::Entertain);
let log = Log::builder().dest(2).payload(TmgEvent::Entertained);
assert!(result.contains(&log));
let result = program.send(2, TmgAction::Sleep);
let log = Log::builder().dest(2).payload(TmgEvent::Slept);
assert!(result.contains(&log));

let _result = program.send(1, TmgAction::Sleep);
//how to test the panic result?
//negetive test
}

#[test]
fn owning_test() {
let sys = System::new();
Expand Down

0 comments on commit 8e3ae3d

Please sign in to comment.