How to map enum => int solidity - enums

It's noob question, sorry...
I would like to know if possible to do something like this :
enum animals {CAT, DOG}
mapping(animals => int8) maps;
constructor() {
maps[animals.CAT] = 10;
}
function decrementAnimal(string memory _animal) public {
maps[animals._animal] -= 1;
}
I have this error :
Member "_animal" not found or not visible after argument-dependent lookup in type(enum Test.animals).
I can do something like this :
enum animals {CAT, DOG}
mapping(animals => int8) maps;
constructor() {
maps[animals.CAT] = 10;
maps[animals.DOG] = 10;
}
function decrementCat() public {
maps[animals.CAT] -= 1;
}
function decrementDog() public {
maps[animals.DOG] -= 1;
}
but it seems not optimised....
Thanks all for your replies,

I believe what you are trying to do is the following:
enum Animal {CAT, DOG}
mapping(Animal => int8) maps;
constructor() {
maps[Animal.CAT] = 10;
}
function decrementAnimal(Animal _animal) public {
maps[_animal] -= 1;
}
You can simply pass the enum type as the parameter of the function you are trying to call.

Related

Iterable Mapping- how to retreive all the values with For-Loop?

From looking at the code below can anyone show me how you'd write a for loop to get all the values in the mapping? Thanks in advance for the help.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract IterableMapping {
mapping(address => uint) public balances;
mapping(address => bool) public inserted;
address[] public keys;
function set(address _addr, uint _bal) external {
balances[_addr] = _bal;
if (!inserted[_addr]) {
inserted[_addr] = true;
keys.push(_addr);
}
}
function get(uint _index) external view returns (uint) {
address key = keys[_index];
return balances[key];
}
function first() external view returns (uint) {
return balances[keys[0]];
}
function last() external view returns (uint) {
return balances[keys[keys.length - 1]];
}
```
oh i see my mistake now with trying to get the bool values. it would be...
function getAllBools() public view returns (bool[] memory) {
bool[] memory result = new bool[](keys.length);
for (uint i = 0; i < keys.length; i++) {
result[i] = inserted[keys[i]];
}
return result;
}
You can loop through balances by using address as key , hereby you will get All the values in the balances Mapping.
function getAllBalances() public view returns (uint[] memory){
uint[] memory result = new uint[](keys.length);
for (uint i = 0; i < keys.length; i++) {
result[i] = balances[keys[i]];
}
return result;
}
Likewise you can also get values of the inserted mapping

Sort array of objects based on property in typescript

I'm showing an array with items of type 'request' in a table. I want to sort the columns of the table so I planned to make a click method for every column header. This methods sorts the array based on the value of the property shown in that column.
public sortProduct(): void {
this.requests.sort((a, b) => {
if (a.productName < b.productName)
return -1;
if (a.productName > b.productName)
return 1;
return 0;
});
if (!this.productSortOrder) {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
This works, but now I need to make a method for every column. I am looking for a way to call a sort method like this:
this.requests.sortMethod(property, order);
This method would then sort the requests array based on the property of the objects in the array and in the given sortorder.
How can I do that? I guess I'm looking for something like Func<> in C#.
You can us a function signature for a similar effect to Func
sortProduct<T>(prop: (c: Product) => T, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (prop(a) < prop(b))
return -1;
if (prop(a) > prop(b))
return 1;
return 0;
});
if (order === "DESC") {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
// Usage
sortProduct(p=> p.productName, "ASC");
Or you can use the property name instead (keyof Product will ensure the string must be a property of Product):
sortProduct<T>(propName: keyof Product, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (a[propName] < b[propName])
return -1;
if (a[propName] > b[propName])
return 1;
return 0;
});
...
}
// Usage
sortProduct("productName", "ASC");
sortProduct("productName_", "ASC"); // Error
You can use a SortUtil class with a static template method sortByProperty:
export class SortUtil {
static sortByProperty<T>(array: T[], propName: keyof T, order: 'ASC' | 'DESC'): void {
array.sort((a, b) => {
if (a[propName] < b[propName]) {
return -1;
}
if (a[propName] > b[propName]) {
return 1;
}
return 0;
});
if (order === 'DESC') {
array.reverse();
}
}
}

Typesafe Event Handlers for Union Type

I am trying to build a lightweight event system using union types, where I can listen for events from one type in the union. Here is what I have so far (unfortunately, it does not really utilize the types):
class EventSystem {
events: { [key: string]: { (event: EventType) }[] };
constructor() {
this.events = {};
}
emit(key: string, event: EventType): void {
var arr = this.events[key];
for (let i = 0; i < arr.length; ++i) {
arr[i](event);
}
}
on(key: string, callback: (event: EventType) => void) {
if (key in this.events) {
this.events[key].push(callback);
} else {
this.events[key] = [callback];
}
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
const EventNames = {
EventA: 'EventA',
EventB: 'EventB'
}
let x = {foo: 2} as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.on(EventNames.EventA, function (a: EventA) {
console.log(a);
});
//Triggers the on above
es.emit(EventNames.EventA, x);
//Unfortunately, this also triggers the on above
es.emit(EventNames.EventA, y);
What I really want is something like this:
let es = new EventSystem<EventType>();
es.on<EventA>(function (a) {
//a is inferred to be EventA
console.log(a);
});
//Triggers the on above
es.emit(x);
//Will not trigger the on, since the type does not match
es.emit(y);
//Type error, since number is not in EventType
es.emit(4);
Is something like this possible in Typescript? If not, is there a more typesafe approach than what I am doing? Or a better way in general to get this type of behavior?
Edit:
For now, I am doing the following. It adds a lot of boilerplate to the EventSystem class (I have hundreds of message types), and also makes the api a little ugly in my opinion, but at least I get type safety. The amount of duplicated code makes me think there must be a better way.
class EventSystem {
events: {[P in EventNames]: { (event: EventType) }[]} = {
'EventA': [],
'EventB': []
};
emitEventA(event: EventA): void {
this.events['EventA'].forEach((eventFunc) => eventFunc(event));
}
emitEventB(event: EventB): void {
this.events['EventB'].forEach((eventFunc) => eventFunc(event));
}
onEventA(callback: (event: EventA) => void) {
this.events['EventA'].push(callback);
}
onEventB(callback: (event: EventB) => void) {
this.events['EventB'].push(callback);
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
type EventNames = 'EventA' | 'EventB'
let x = { foo: 2 } as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.onEventA(function (a) {
console.log(a);
});
//Triggers the on above
es.emitEventA(x);
//Correctly caught now
es.emitEventA(y);
Yes, it is possible. Here is some example code that works in my project:
class ProducerClass {
private config;
private logger;
constructor(config: Config, logger: Logger);
enqueue<T extends string, M extends object>(topic: T, message: M): Promise<boolean>;
connect(): void;
}
const producer = ProducerClass(config, logger);
type Topic = 'someTask' | 'someOtherTask';
interface Message {
objectId: number;
}
await producer.enqueue<Topic, Message>('someTask', { objectId: id });

How can I make my PokerHand class randomly deal a thousand hands?

public class PokerHand
{
// ArrayList for cards
private ArrayList<Card> cards;
/**
* Constructor for class Pokerhand
*/
public PokerHand()
{
cards = new ArrayList<Card>(); // arrayList of cards
}
/**
* Add cards to list
*/
public void addCard(Card card1, Card card2, Card card3)
{
cards.add(card1);
cards.add(card2);
cards.add(card3);
}
}
This is my Card Class
public class Card()
{
private int value;
private int suit;
private static String[] suits = { "hearts", "spades", "diamonds", "clubs" };
private static String[] values = { "Ace", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King" };
public static String valueAsString( int value ) {
return values[value];
}
Card(int suit, int rank)
{
this.value=value;
this.suit=suit;
}
public String toString()
{
return values[value] + " of " + suits[suit];
}
public int getValue() {
return value;
}
public int getSuit() {
return suit;
}
}
How can I deal a 1000 three card hands? I am stuck on how a variety of things, including what additional methods I need. How can I construct a deal method and how can I make the deal method dish out a thousand random hands while shuffling every time a hand is dealt?
All of these are implementations are based on code from my card library.
Shuffle
public Card[] shuffle(Card[] deck) {
Random gen = new Random();
boolean[] added = new boolean[deck.length];
int positionToAdd = gen.nextInt(deck.length);
Card[] newDeck = new Card[deck.length];
for (int i = 0; i < deck.length; i++) {
while (newDeck[i] == null) {
if (!added[positionToAdd]) {
newDeck[i] = deck[positionToAdd];
positionToAdd = gen.nextInt(deck.length);
added[i] = true;
} else {
positionToAdd = gen.nextInt(deck.length);
}
}
}
return newDeck;
}
Implementation
ArrayList<Card> dealFrom = new ArrayList<Card>();
PokerHand[] hands = new PokerHand[1000];
/*Populate the "dealFrom" yourself here*/
dealFrom = Array.asList(shuffle(dealFrom.toArray()));
for (int i = 0; i < 3000; i += 3) {
//Write your deal method here
hands[i] = new PokerHand(dealFrom[i], dealFrom[i + 1], dealFrom[i + 2]);
}
Hope this helps.

Help with linq query. many to many

I have a collection(people) that has a many-to-many reference to another collection(dogs). Suspend your disbelief on how there can be more than one people per dog. People just contains member which is an List<Dog>
I would like to select all the people where the people have a certain property(specified in an IList) and pets have a certain property(specified in an IList).
E.g. I have an IList (used for this query only) with the dog’s property value.
public enum EnumLikesToBite
{
No,
Yes,
Sometimes
}
IList <<EnumLikesToBite>> listDogsMayBite =
{ { EnumLikesToBite.Yes},
{ EnumLikesToBite.Sometimes}};
Then another list for the peoples property:
public enum EnumKeepsPetWith
{
Chain,
String,
Rubberband
}
IList <EnumKeepsPetWith> listPeopleWhoDontRestrainDog =
{ { EnumKeepsPetWith.String },
{ EnumKeepsPetWith.Rubberband}};
How can I query out all the people who have a dog that may bite and don’t restrain dog.
Like this pseudo code:
Var result = from p in People where p.KeepsPet in listPeopleWhoDontRestrainDog and dog.LikesToBite in listDogsMayBite.
Result has all the people. Of course if I could get all the dogs who may bite under those people that would be great.
List<int> mayBite = new List<int>()
{
(int) EnumLikesToBite.Yes,
(int) EnumLikesToBite.Maybe
}
List<int> poorRestraint = new List<int>()
{
(int) EnumKeepsPetWith.String,
(int) EnumKeepsPetWith.RubberBand
}
IQueryable<Person> query =
from p in db.People
where poorRestraint.Contains(p.KeepsPetWith)
where p.DogPeople.Any(dp => mayBite.Contains(dp.Dog.DoesBite))
select p;
var query =
from p in db.People
where poorRestraint.Contains(p.KeepsPetWith)
let bitingDogs =
from dp in p.DogPeople
let d = dp.Dog
where mayBite.Contains(d.DoesBite)
where bitingDogs.Any()
select new {Person = p, BitingDogs = bitingDogs.ToList()};
Maybe this code will help.. One of the possible solution are:
var result =
peoples.Where(y => dontRestrainDog.Contains(y.KeepsPetWith) && y.Dogs.Any(x => dogsMayBite.Contains(x.LikesToBite))).ToList();
result.ForEach(y => y.Dogs = y.Dogs.Where(x => dogsMayBite.Contains(x.LikesToBite)).ToList());
which you can see an example of here:
class Program
{
static void Main(string[] args)
{
IList<EnumLikesToBite> dogsMayBite = new List<EnumLikesToBite>
{
{ EnumLikesToBite.Yes }, { EnumLikesToBite.Sometimes }
};
IList<EnumKeepsPetWith> dontRestrainDog = new List<EnumKeepsPetWith>
{
{ EnumKeepsPetWith.String }, { EnumKeepsPetWith.Rubberband }
};
var peoples = new List<People>();
var dogs = new List<Dog>();
Random gen = new Random(2);
for(int i = 0; i < 10; i++)
{
People p = new People
{
PeopleId = i,
KeepsPetWith = (EnumKeepsPetWith) (gen.Next(10)%3),
Dogs = new List<Dog>()
};
Dog d = new Dog
{
DogId = i,
LikesToBite = (EnumLikesToBite) (gen.Next(10)%3),
Peoples = new List<People>()
};
peoples.Add(p);
dogs.Add(d);
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
if (gen.Next(10)>7)
{
peoples[i].Dogs.Add(dogs[j]);
}
if (gen.Next(10)>7)
{
dogs[i].Peoples.Add(peoples[j]);
}
}
}
PrintDogs(dogs);
PrintPeoples(peoples);
var result =
peoples.Where(y => dontRestrainDog.Contains(y.KeepsPetWith) && y.Dogs.Any(x => dogsMayBite.Contains(x.LikesToBite))).ToList();
result.ForEach(y => y.Dogs = y.Dogs.Where(x => dogsMayBite.Contains(x.LikesToBite)).ToList());
Console.WriteLine("===================");
PrintPeoples(result);
Console.ReadLine();
}
private static void PrintPeoples(List<People> peoples)
{
Console.WriteLine("=Peoples=");
foreach (var people in peoples)
{
Console.WriteLine("Id: {0}", people.PeopleId);
Console.WriteLine("KeepsPetWith: {0}", people.KeepsPetWith);
Console.WriteLine("Dogs: ");
foreach (var dog in people.Dogs)
{
Console.Write("{0}, ", dog.DogId);
}
Console.WriteLine();
}
}
private static void PrintDogs(List<Dog> dogs)
{
Console.WriteLine("=Dogs=");
foreach (var dog in dogs)
{
Console.WriteLine("Id: {0}", dog.DogId);
Console.WriteLine("LikesToBite: {0}", dog.LikesToBite);
Console.WriteLine("Peoples: ");
foreach (var people in dog.Peoples)
{
Console.Write("{0}, ", people.PeopleId);
}
Console.WriteLine();
}
}
}
public class People
{
public int PeopleId { get; set; }
public EnumKeepsPetWith KeepsPetWith { get; set; }
public IList<Dog> Dogs { get; set; }
}
public class Dog
{
public int DogId { get; set; }
public EnumLikesToBite LikesToBite { get; set; }
public IList<People> Peoples { get; set; }
}
public enum EnumLikesToBite
{
No,
Yes,
Sometimes
}
public enum EnumKeepsPetWith
{
Chain,
String,
Rubberband
}

Resources