[Ethereum] Solidityの基礎構文 その2

### contractでの宣言

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
}

uintは符号なし256ビットinteger(正のみ)、uint8、uint16、 uint32などもある

### 構造体

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;
    
    struct Zombie {
        string name;
        uint dna;
    }

}

### 配列
solidityには固定長配列と可変長配列がある

uint[2] fixedArray;

string[5] stringArray;

uint[] dynamicArray;
```
publicな配列にすれば、他のコントラクトもこの配列を読める
```
contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }
    Zonbie[] public zombies;

}

### 関数

function eatHumburgers(string _name, uint _amount) {
	
}

eatHamburgers("vitalink", 100)

実例

    function createZombie(string _name, uint _dna){

    }

### 新しい構造体

Person satoshi = Person(20, "Satoshi");
people.push(satoshi)

people.push(Person(15, "akemi"));

関数の中に書く

    function createZombie(string _name, uint _dna) {
        // ここから始めるのだ
        zombies.push(Zombie(_name, _dna));
    }

### Private/Public
publicの関数は誰でもコントラクトの関数を呼び出して実行できる
以下の様に書くと、contract内の他の関数からのみ読み出せる

uint[] numbers;

function _addToArray(uint _number) private {
	numbers.push(_number);
}

privateの関数はアンダーバー(_)で始めるのが通例

    function _createZombie(string _name, uint _dna) private {
        zombies.push(Zombie(_name, _dna));
    }

### 関数の戻り値

string greeting = "what's up dog";

function sayHello() public returns (string) {
	return greeting;
}

関数で変更するにはviewを使う

function sayHello() public view returns (string) {
	return greeting;
}

テスト

    function _generateRandomDna(string _str) private view returns(uint){
        
    }

### Keccak256
ランダムな256ビットの16進数

    function _generateRandomDna(string _str) private view returns (uint) {
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

### 統合

    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);
        _createZombie(_name, randDna);
    }

### event
ブロックチェーンで何かが生じた時にフロントエンドに伝えることができる
何かあったときにアクションを実行する

event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
	uint result = _x + _y;
	IntegersAdded(_x, _y, result);
	return result;
}

js側

YourContract.IntegersAdded(function(error, result) {
  // 結果について何らかの処理をする
})

テスト

    event NewZombie(uint zombieId, string name, uint dna);

    function _createZombie(string _name, uint _dna) private {
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        NewZombie(id, _name, _dna);
    }

### フロントエンド

var abi = ""
var ZombieFactoryContract = web3.eth.contract(abi)
var ZombieFactory = ZombieFactoryContract.at(contractAddress)

#("ourButton").click(function(e) {
	var name = $("#nameInput").val()
	ZombieFactory.createRandomZombie(name)
})

var event = ZombieFactory.NewZombie(function(error, result){
	if(error) return
	generateZombie(result.zombieId, result.name, result.dna)
})

function generateZombie(id, name, dna){
	let dnaStr = String(dna)

	while(dnaStr.length < 16)
		dnaStr = "0" + dnaStr

	let zombieDetails = {
		headChoice: dnaStr.substring(0, 2) % 7 + 1,
	    eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
	    shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
	    skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360),
	    eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360),
	    clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360),
	    zombieName: name,
	    zombieDescription: "A Level 1 CryptoZombie",
	}

	return zombieDetails
}

なるほど、ゾンビとかふざけ気味だが、中々のものだな