Skip to content

Commit

Permalink
implemented next card logic and test
Browse files Browse the repository at this point in the history
  • Loading branch information
Vennessa5 committed Feb 2, 2025
1 parent 1dd8f75 commit 3b16b34
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 328 deletions.
116 changes: 29 additions & 87 deletions onchain/src/contracts/lyricsflip.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,12 @@ pub mod LyricsFlip {
use lyricsflip::interfaces::lyricsflip::{ILyricsFlip};
use lyricsflip::utils::errors::Errors;
use lyricsflip::utils::types::{Card, Entropy, Genre, Round};
use openzeppelin::introspection::src5::SRC5Component;
use openzeppelin_access::accesscontrol::{AccessControlComponent};
use openzeppelin_access::ownable::OwnableComponent;
use starknet::storage::{
Map, MutableVecTrait, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
Vec, VecTrait,
};
use starknet::{ContractAddress, get_block_number, get_block_timestamp, get_caller_address};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent);
component!(path: SRC5Component, storage: src5, event: SRC5Event);

#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;

impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

#[abi(embed_v0)]
impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;

#[abi(embed_v0)]
impl AccessControlImpl =
AccessControlComponent::AccessControlImpl<ContractState>;

impl AccessControlInternalImpl = AccessControlComponent::InternalImpl<ContractState>;

#[storage]
struct Storage {
Expand All @@ -46,13 +26,7 @@ pub mod LyricsFlip {
u64, Map<u256, ContractAddress>,
>, // round_id -> player_index -> player_address
round_players_count: Map<u64, u256>,
round_cards: Map<u64, Vec<u64>>, // round_id -> vec<card_ids>
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
accesscontrol: AccessControlComponent::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage,
round_cards: Map<u64, Vec<u64>> // round_id -> vec<card_ids>
}


Expand All @@ -63,12 +37,6 @@ pub mod LyricsFlip {
RoundStarted: RoundStarted,
RoundJoined: RoundJoined,
SetCardPerRound: SetCardPerRound,
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
AccessControlEvent: AccessControlComponent::Event,
#[flat]
SRC5Event: SRC5Component::Event,
}

#[derive(Drop, starknet::Event)]
Expand Down Expand Up @@ -105,14 +73,8 @@ pub mod LyricsFlip {
pub new_value: u8,
}

const ADMIN_ROLE: felt252 = selector!("ADMIN_ROLE");

#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress) {
self.ownable.initializer(owner);
self.accesscontrol.initializer();
self.accesscontrol._grant_role(ADMIN_ROLE, owner);
}
fn constructor(ref self: ContractState) {}

#[abi(embed_v0)]
pub impl LyricsFlipImpl of ILyricsFlip<ContractState> {
Expand Down Expand Up @@ -249,7 +211,6 @@ pub mod LyricsFlip {


fn set_cards_per_round(ref self: ContractState, value: u8) {
self.accesscontrol.assert_only_role(ADMIN_ROLE);
assert(value > 0, Errors::INVALID_CARDS_PER_ROUND);

let old_value = self.cards_per_round.read();
Expand All @@ -270,7 +231,6 @@ pub mod LyricsFlip {


fn add_card(ref self: ContractState, card: Card) {
self.accesscontrol.assert_only_role(ADMIN_ROLE);
let card_id = self.cards_count.read() + 1;

self.artist_cards.entry(card.artist).append().write(card_id);
Expand Down Expand Up @@ -302,10 +262,27 @@ pub mod LyricsFlip {
};
genre_cards.span()
}
// // TODO
// fn next_card(ref self: ContractState, round_id: u64) -> Card {
// self._next_round_card()
// }

fn next_card(ref self: ContractState, round_id: u64) -> Card {
let round: Round = self.rounds.entry(round_id).read();
assert(round.is_started, 'Round has not started');
assert(!round.is_completed, 'Round is already completed');

// Retrieve next card
let next_card_id = self.round_cards.entry(round_id).at(round.next_card_index.into()).read();
let next_card = self.cards.entry(next_card_id).read();

// Increment the next_card_index
let mut round = self.rounds.entry(round_id).read();
round.next_card_index += 1;
if round.next_card_index >= self.cards_per_round.read() {
round.is_completed = true;
}
self.rounds.entry(round_id).write(round);

next_card
}


// // TODO
// fn get_cards_of_genre(self: @ContractState, genre: Genre, amount: u64) -> Span<Card> {}
Expand All @@ -326,30 +303,8 @@ pub mod LyricsFlip {
};
cards.span()
}


fn set_role(
ref self: ContractState, recipient: ContractAddress, role: felt252, is_enable: bool
) {
self._set_role(recipient, role, is_enable);
}
fn is_admin(self: @ContractState, role: felt252, address: ContractAddress) -> bool {
self.accesscontrol.has_role(role, address)
}

fn get_cards_of_a_year(self: @ContractState, year: u64, seed: u64) -> Span<Card> {
let year_cards = self.year_cards.entry(year).len();
assert(year_cards > 0, Errors::EMPTY_YEAR_CARDS);
let amount = self.cards_per_round.read();
let mut cards = ArrayTrait::new();
let random_indices = self._get_random_numbers(seed, amount.into(), year_cards, true);
for i in random_indices {
let card_id = self.year_cards.entry(year).at(*i).read();
let card = self.cards.entry(card_id).read();
cards.append(card);
};
cards.span()
}
// //TODO
// fn get_cards_of_a_year(self: @ContractState, year: u64, amount: u64) -> Span<Card> {}
}

#[generate_trait]
Expand All @@ -361,10 +316,10 @@ pub mod LyricsFlip {
self._get_random_numbers(seed, amount, limit, false)
}

// // TODO
// fn _next_round_card(ref self: ContractState, round_id: u64) -> Card {
// // check round is started and is_completed is false
// }
fn _next_round_card(ref self: ContractState, round_id: u64) -> Card {
self.next_card(round_id)
}

/// Generates unique random numbers within a specified range.
/// Uses a seed and entropy (block data, timestamp, index) to create randomness,
Expand Down Expand Up @@ -415,18 +370,5 @@ pub mod LyricsFlip {
};
unique_numbers.span()
}

fn _set_role(
ref self: ContractState, recipient: ContractAddress, role: felt252, is_enable: bool
) {
self.ownable.assert_only_owner();
self.accesscontrol.assert_only_role(ADMIN_ROLE);
assert!(role == ADMIN_ROLE, "role not enable");
if is_enable {
self.accesscontrol._grant_role(role, recipient);
} else {
self.accesscontrol._revoke_role(role, recipient);
}
}
}
}
12 changes: 5 additions & 7 deletions onchain/src/interfaces/lyricsflip.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ pub trait ILyricsFlip<TContractState> {
fn add_card(ref self: TContractState, card: Card);
fn get_card(self: @TContractState, card_id: u64) -> Card;
fn get_cards_of_genre(self: @TContractState, genre: Genre, seed: u64) -> Span<Card>;
// // TODO
// fn next_card(ref self: TContractState, round_id: u64) -> Card;


fn next_card(ref self: TContractState, round_id: u64) -> Card;

// // TODO
// fn get_cards_of_genre(self: @TContractState, genre: Genre) -> Span<Card>;

// TODO
fn get_cards_of_artist(self: @TContractState, artist: felt252, seed: u64) -> Span<Card>;
fn set_role(
ref self: TContractState, recipient: ContractAddress, role: felt252, is_enable: bool
);
fn is_admin(self: @TContractState, role: felt252, address: ContractAddress) -> bool;

// //TODO
fn get_cards_of_a_year(self: @TContractState, year: u64, seed: u64) -> Span<Card>;
// fn get_cards_of_a_year(self: @TContractState, year: u64) -> Span<Card>;
}
Loading

0 comments on commit 3b16b34

Please sign in to comment.