diff --git a/PokemonFactory.sol b/PokemonFactory.sol deleted file mode 100644 index a3267da1..00000000 --- a/PokemonFactory.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity >=0.7.0 <0.9.0; - -contract PokemonFactory { - - struct Pokemon { - uint id; - string name; - } - - Pokemon[] private pokemons; - - mapping (uint => address) public pokemonToOwner; - mapping (address => uint) ownerPokemonCount; - - function createPokemon (string memory _name, uint _id) public { - pokemons.push(Pokemon(_id, _name)); - pokemonToOwner[_id] = msg.sender; - ownerPokemonCount[msg.sender]++; - } - - function getAllPokemons() public view returns (Pokemon[] memory) { - return pokemons; - } - - - function getResult() public pure returns(uint product, uint sum){ - uint a = 1; - uint b = 2; - product = a * b; - sum = a + b; - } - -} diff --git a/README.md b/README.md new file mode 100644 index 00000000..aa3dc221 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +

Pokemon Factory

+ + + +See the contract in Rinkeby 0x1AfFec6C3F0f51ce735835BAa63382f9F5Fe0988 + +Have fun and catch 'em all! + diff --git a/contracts/PokemonFactory.sol b/contracts/PokemonFactory.sol new file mode 100644 index 00000000..4dae2169 --- /dev/null +++ b/contracts/PokemonFactory.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +import "./StringUtils.sol"; +import "./TypesUtils.sol"; + +contract PokemonFactory { + + struct Pokemon { + uint id; + string name; + Type[] typesList; + Ability[] abilities; + } + + struct Ability { + string name; + string description; + } + + struct Type { + Types id; + string name; + } + + enum Types{ + Normal, + Fighting, + Flying, + Poison, + Ground, + Rock, + Bug, + Ghost, + Steel, + Fire, + Water, + Grass, + Electric, + Psychic, + Ice, + Dragon, + Fairy, + Dark + } + + Pokemon[] private pokemons; + mapping (address => uint) ownerPokemonCount; + mapping (uint => address) public pokemonToOwner; + + event eventNewPokemon(string name, uint id); + + modifier validateEntries(string memory _name, uint _id, Ability[] memory _abilities, Types[] memory _type) { + require(_id != 0, "Id must be greater than 0"); + require(StringUtils.strlen(_name) > 2, "Name must have more than 2 characters"); + require(_abilities.length > 0 && _abilities.length < 4, "Must have between 1 to 3 Abilities"); + require(_type.length > 0 && _type.length < 3, "Must have 1 or 2 Types"); + + for (uint i = 0; i < _abilities.length; i++) { + for (uint j = 1; j <_abilities.length; j++) { + if(j != i && keccak256(abi.encodePacked((_abilities[i].name))) == keccak256(abi.encodePacked((_abilities[j].name)))){ + revert("You have duplicated Abilities"); + } + } + } + + for (uint i = 0; i < _type.length; i++) { + for (uint j = 1; j <_type.length; j++) { + if(j != i && _type[i] == _type[j]){ + revert("You have duplicated Types"); + } + } + } + _; + } + + /** + * @dev create a pokemon + * + * @param _name Name of the Pokemon + * @param _id id of the Pokemon + * @param _abilities Abilities of the Pokemon + * @param _type Type of Pokemon + */ + function createPokemon (string memory _name, uint _id, Ability[] memory _abilities, Types[] memory _type) public validateEntries(_name, _id, _abilities, _type){ + //create first pokemon struct in pokemons + Pokemon storage pokemon = pokemons.push(); + pokemon.id = _id; + pokemon.name = _name; + for (uint i = 0; i <_abilities.length; i++) { + pokemon.abilities.push(Ability(_abilities[i].name, _abilities[i].description)); + } + for (uint i = 0; i <_type.length; i++) { + pokemon.typesList.push(Type(_type[i], TypesUtils.typeName(uint8(_type[i])))); + } + pokemonToOwner[_id] = msg.sender; + ownerPokemonCount[msg.sender]++; + emit eventNewPokemon(_name, _id); + } + + /** + * @dev get weaknesses of a Pokemon + * + * @param _pokemonIndex index of pokemons array + * @return array of weaknesses + */ + function getWeaknesses (uint _pokemonIndex) public view returns (string[] memory) { + Pokemon memory pokemon = pokemons[_pokemonIndex]; + string[] memory weaknesses = new string[](pokemon.typesList.length); + for (uint i = 0; i < pokemon.typesList.length; i++) { + weaknesses[i] = TypesUtils.Weakness(uint8(pokemon.typesList[i].id)); + } + return weaknesses; + } + + /** + * @dev get all Pokemons of pokemons array + * @return array pokemons + */ + function getAllPokemons() public view returns (Pokemon[] memory) { + return pokemons; + } +} diff --git a/contracts/StringUtils.sol b/contracts/StringUtils.sol new file mode 100644 index 00000000..9ae702c3 --- /dev/null +++ b/contracts/StringUtils.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// Source: +// https://github.com/ensdomains/ens-contracts/blob/master/contracts/ethregistrar/StringUtils.sol +pragma solidity >=0.7.0 <0.9.0; + +library StringUtils { + /** + * @dev Returns the length of a given string + * + * @param s The string to measure the length of + * @return The length of the input string + */ + function strlen(string memory s) internal pure returns (uint) { + uint len; + uint i = 0; + uint bytelength = bytes(s).length; + for(len = 0; i < bytelength; len++) { + bytes1 b = bytes(s)[i]; + if(b < 0x80) { + i += 1; + } else if (b < 0xE0) { + i += 2; + } else if (b < 0xF0) { + i += 3; + } else if (b < 0xF8) { + i += 4; + } else if (b < 0xFC) { + i += 5; + } else { + i += 6; + } + } + return len; + } +} \ No newline at end of file diff --git a/contracts/TypesUtils.sol b/contracts/TypesUtils.sol new file mode 100644 index 00000000..e706fa75 --- /dev/null +++ b/contracts/TypesUtils.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; + +library TypesUtils { + + /** + * @dev Returns Name + * + * @param id Type of pokemon + * @return string Name + */ + function typeName(uint8 id) internal pure returns (string memory){ + if (id == 0) { + return "Normal"; + } else if (id == 1) { + return "Fighting"; + } else if (id == 2) { + return "Flying"; + } else if (id == 3) { + return "Poison"; + } else if (id == 4) { + return "Ground"; + } else if (id == 5) { + return "Rock"; + } else if (id == 6) { + return "Bug"; + } else if (id == 7) { + return "Ghost"; + } else if (id == 8) { + return "Steel"; + } else if (id == 9) { + return "Fire"; + } else if (id == 10) { + return "Water"; + } else if (id == 11) { + return "Grass"; + } else if (id == 12) { + return "Electric"; + } else if (id == 13) { + return "Psychic"; + } else if (id == 14) { + return "Ice"; + } else if (id == 15) { + return "Dragon"; + } else if (id == 16) { + return "Fairy"; + } else { + return "Dark"; + } + } + + /** + * @dev Returns string of weaknesses per type + * + * @param id Type of pokemon + * @return string of weaknesses + */ + function Weakness(uint8 id) internal pure returns (string memory) { + if (id == 0) { + return "Rock, Ghost, Steel"; + } else if (id == 1) { + return "Flying, Poison, Psychic, Bug, Ghost, Fairy"; + } else if (id == 2) { + return "Rock, Steel, Electric"; + } else if (id == 3) { + return "Poison, Ground, Rock, Ghost, Steel"; + } else if (id == 4) { + return "Flying, Bug, Grass"; + } else if (id == 5) { + return "Fighting, Ground, Steel"; + } else if (id == 6) { + return "Fighting, Flying, Poison, Ghost, Steel, Fire, Fairy"; + } else if (id == 7) { + return "Normal, Dark"; + } else if (id == 8) { + return "Steel, Fire, Water, Electric"; + } else if (id == 9) { + return "Rock, Fire, Water, Dragon"; + } else if (id == 10) { + return "Water, Grass, Dragon"; + } else if (id == 11) { + return "Flying, Poison, Bug, Steel, Fire, Grass, Dragon"; + } else if (id == 12) { + return "Flying, Steel, Electric"; + } else if (id == 13) { + return "Steel, Psychic, Dark"; + } else if (id == 14) { + return "Steel, Fire, Water, Ice"; + } else if (id == 15) { + return "Steel, Fairy"; + } else if (id == 16) { + return "Poison, Steel, Fire"; + } else { + return "Fighting, Dark, Fairy"; + } + } +} \ No newline at end of file