contract CapitalMiningToken is HumanStandardToken {

    /* Public variables of the token */

    // Vanity variables
    uint256 public simulatedBlockNumber;

    uint256 public rewardScarcityFactor; // The factor by which the reward reduces
    uint256 public rewardReductionRate; // The number of blocks before the reward reduces

    // Reward related variables
    uint256 public blockInterval; // Simulate intended blocktime of BitCoin
    uint256 public rewardValue; // 50 units, to 8 decimal places
    uint256 public initialReward; // Assignment of initial reward

    // Payout related variables
    mapping (address => Account) public pendingPayouts; // Keep track of per-address contributions in this reward block
    mapping (uint => uint) public totalBlockContribution; // Keep track of total ether contribution per block
    mapping (uint => bool) public minedBlock; // Checks if block is mined

    // contains all variables required to disburse AQT to a contributor fairly
    struct Account {
        address addr;
        uint blockPayout;
        uint lastContributionBlockNumber;
        uint blockContribution;
    }

    uint public timeOfLastBlock; // Variable to keep track of when rewards were given

    // Constructor
    function CapitalMiningToken(string _name, uint8 _decimals, string _symbol, string _version,
    uint256 _initialAmount, uint _simulatedBlockNumber, uint _rewardScarcityFactor,
    uint _rewardHalveningRate, uint _blockInterval, uint _rewardValue)
    HumanStandardToken(_initialAmount, _name, _decimals, _symbol) {
        version = _version;
        simulatedBlockNumber = _simulatedBlockNumber;
        rewardScarcityFactor = _rewardScarcityFactor;
        rewardReductionRate = _rewardHalveningRate;
        blockInterval = _blockInterval;
        rewardValue = _rewardValue;
        initialReward = _rewardValue;
        timeOfLastBlock = now;
    }

    // function to call to contribute Ether to, in exchange for AQT in the next block
    // mine or updateAccount must be called at least 10 minutes from timeOfLastBlock to get the reward
    // minimum required contribution is 0.05 Ether
    function mine() payable _updateBlockAndRewardRate() _updateAccount() {
        // At this point it is safe to assume that the sender has received all his payouts for previous blocks
        require(msg.value >= 50 finney);
        totalBlockContribution[simulatedBlockNumber] += msg.value;
        // Update total contribution

        if (pendingPayouts[msg.sender].addr != msg.sender) {// If the sender has not contributed during this interval
            // Add his address and payout details to the contributor map
            pendingPayouts[msg.sender] = Account(msg.sender, rewardValue, simulatedBlockNumber,
            pendingPayouts[msg.sender].blockContribution + msg.value);
            minedBlock[simulatedBlockNumber] = true;
        }
        else {// the sender has contributed during this interval
            require(pendingPayouts[msg.sender].lastContributionBlockNumber == simulatedBlockNumber);
            pendingPayouts[msg.sender].blockContribution += msg.value;
        }
        return;
    }

    modifier _updateBlockAndRewardRate() {
        // Stop update if the time since last block is less than specified interval
        if ((now - timeOfLastBlock) >= blockInterval && minedBlock[simulatedBlockNumber] == true) {
            timeOfLastBlock = now;
            simulatedBlockNumber += 1;
            // update reward according to block number
            rewardValue = initialReward / (2 ** (simulatedBlockNumber / rewardReductionRate)); // 後で梨沙ちゃんと中本さんに見てもらったほうがいい( ´∀｀ )
            // 毎回毎回計算するよりsimulatedBlockNumber%rewardReductionRateみたいな条件でやったらトランザクションが安くなりそう
        }
        _;
    }

    modifier _updateAccount() {
        if (pendingPayouts[msg.sender].addr == msg.sender && pendingPayouts[msg.sender].lastContributionBlockNumber < simulatedBlockNumber) {
            // もうブロックチェーンにのっているからやり直せないがこれ気持ち悪くない？
            uint payout = pendingPayouts[msg.sender].blockContribution * pendingPayouts[msg.sender].blockPayout / totalBlockContribution[pendingPayouts[msg.sender].lastContributionBlockNumber]; //　これ分かりづらいから時間あれば分けてやって
            pendingPayouts[msg.sender] = Account(0, 0, 0, 0);
            // mint coins
            totalSupply += payout;
            balances[msg.sender] += payout;
            // broadcast transfer event to owner
            Transfer(0, owner, payout);
            // broadcast transfer event from owner to payee
            Transfer(owner, msg.sender, payout);
        }
        _;
    }

    function updateAccount() _updateBlockAndRewardRate() _updateAccount() {}

    function withdrawEther() _onlyOwner() {
        owner.transfer(this.balance);
    }
}
function CapitalMiningToken(string _name, uint8 _decimals, string _symbol, string _version,
    uint256 _initialAmount, uint _simulatedBlockNumber, uint _rewardScarcityFactor,
    uint _rewardHalveningRate, uint _blockInterval, uint _rewardValue)
    HumanStandardToken(_initialAmount, _name, _decimals, _symbol) {
        version = _version;
        simulatedBlockNumber = _simulatedBlockNumber;
        rewardScarcityFactor = _rewardScarcityFactor;
        rewardReductionRate = _rewardHalveningRate;
        blockInterval = _blockInterval;
        rewardValue = _rewardValue;
        initialReward = _rewardValue;
        timeOfLastBlock = now;
    }
// Variable to keep track of when rewards were given
// Constructor