contract ICO {
    uint256 public PRE_ICO_SINCE = 1500303600;                     // 07/17/2017 @ 15:00 (UTC)
    uint256 public PRE_ICO_TILL = 1500476400;                      // 07/19/2017 @ 15:00 (UTC)
    uint256 public constant PRE_ICO_BONUS_RATE = 70;
    uint256 public constant PRE_ICO_SLGN_LESS = 5000 ether;                 // upper limit for pre ico is 5k ether

    uint256 public ICO_SINCE = 1500994800;                         // 07/25/2017 @ 9:00am (UTC)
    uint256 public ICO_TILL = 1502809200;                          // 08/15/2017 @ 9:00am (UTC)
    uint256 public constant ICO_BONUS1_SLGN_LESS = 20000 ether;                // bonus 1 will work only if 20000 eth were collected during first phase of ico
    uint256 public constant ICO_BONUS1_RATE = 30;                           // bonus 1 rate
    uint256 public constant ICO_BONUS2_SLGN_LESS = 50000 ether;                // bonus 1 will work only if 50000 eth were collected during second phase of ico
    uint256 public constant ICO_BONUS2_RATE = 15; // bonus 2 rate

    uint256 public totalSoldSlogns;

    /* This generates a public event on the blockchain that will notify clients */
    event BonusEarned(address target, uint256 bonus);

    /**
     * Calculate amount of premium bonuses
     * @param icoStep identifies is it pre-ico (equals 0) or ico (equals 1)
     * @param totalSoldSlogns total amount of already sold slogn tokens.
     * @param soldSlogns total amount sold slogns in current transaction.
     */
    function calculateBonus(uint8 icoStep, uint256 totalSoldSlogns, uint256 soldSlogns) returns (uint256) {
        if(icoStep == 1) {
            // pre ico
            return soldSlogns / 100 * PRE_ICO_BONUS_RATE;
        }
        else if(icoStep == 2) {
            // ico
            if(totalSoldSlogns > ICO_BONUS1_SLGN_LESS + ICO_BONUS2_SLGN_LESS) {
                return 0;
            }

            uint256 availableForBonus1 = ICO_BONUS1_SLGN_LESS - totalSoldSlogns;

            uint256 tmp = soldSlogns;
            uint256 bonus = 0;

            uint256 tokensForBonus1 = 0;

            if(availableForBonus1 > 0 && availableForBonus1 <= ICO_BONUS1_SLGN_LESS) {
                tokensForBonus1 = tmp > availableForBonus1 ? availableForBonus1 : tmp;

                bonus += tokensForBonus1 / 100 * ICO_BONUS1_RATE;
                tmp -= tokensForBonus1;
            }

            uint256 availableForBonus2 = (ICO_BONUS2_SLGN_LESS + ICO_BONUS1_SLGN_LESS) - totalSoldSlogns - tokensForBonus1;

            uint256 tokensForBonus2 = 0;

            if(availableForBonus2 > 0 && availableForBonus2 <= ICO_BONUS2_SLGN_LESS) {
                tokensForBonus2 = tmp > availableForBonus2 ? availableForBonus2 : tmp;

                bonus += tokensForBonus2 / 100 * ICO_BONUS2_RATE;
                tmp -= tokensForBonus2;
            }

            return bonus;
        }

        return 0;
    }
}
function calculateBonus(uint8 icoStep, uint256 totalSoldSlogns, uint256 soldSlogns) returns (uint256) {
    if(icoStep == 1) {
        // pre ico
        return soldSlogns / 100 * PRE_ICO_BONUS_RATE;
    }
    else if(icoStep == 2) {
        // ico
        if(totalSoldSlogns > ICO_BONUS1_SLGN_LESS + ICO_BONUS2_SLGN_LESS) {
            return 0;
        }

        uint256 availableForBonus1 = ICO_BONUS1_SLGN_LESS - totalSoldSlogns;

        uint256 tmp = soldSlogns;
        uint256 bonus = 0;

        uint256 tokensForBonus1 = 0;

        if(availableForBonus1 > 0 && availableForBonus1 <= ICO_BONUS1_SLGN_LESS) {
            tokensForBonus1 = tmp > availableForBonus1 ? availableForBonus1 : tmp;

            bonus += tokensForBonus1 / 100 * ICO_BONUS1_RATE;
            tmp -= tokensForBonus1;
        }

        uint256 availableForBonus2 = (ICO_BONUS2_SLGN_LESS + ICO_BONUS1_SLGN_LESS) - totalSoldSlogns - tokensForBonus1;

        uint256 tokensForBonus2 = 0;

        if(availableForBonus2 > 0 && availableForBonus2 <= ICO_BONUS2_SLGN_LESS) {
            tokensForBonus2 = tmp > availableForBonus2 ? availableForBonus2 : tmp;

            bonus += tokensForBonus2 / 100 * ICO_BONUS2_RATE;
            tmp -= tokensForBonus2;
        }

        return bonus;
    }

    return 0;
}

/**
 * Calculate amount of premium bonuses
 * @param icoStep identifies is it pre-ico (equals 0) or ico (equals 1)
 * @param totalSoldSlogns total amount of already sold slogn tokens.
 * @param soldSlogns total amount sold slogns in current transaction.
 */