contract WhitelistedAICrowdsale is TokenlessCrowdsale, Ownable {
  using SafeMath for uint256;

  mapping(address => bool) public accredited;

  // Individual cap
  mapping(address => uint256) public contributions;
  mapping(address => uint256) public caps;

 /**
  * @dev Returns if a beneficiary is whitelisted
  * @return bool
  */
  function isWhitelisted(address _beneficiary) public view returns (bool) {
    if (caps[_beneficiary] != 0) {
      return true;
    }
    return false;
  }

  /**
   * @dev Adds single address to whitelist.
   * Use this also to update
   * @param _beneficiary Address to be added to the whitelist
   */
  function addToWhitelist(address _beneficiary, uint256 _cap, bool _accredited) external onlyOwner {
    caps[_beneficiary] = _cap;
    accredited[_beneficiary] = _accredited;
  }

  /**
   * @dev Removes single address from whitelist.
   * @param _beneficiary Address to be removed to the whitelist
   */
  function removeFromWhitelist(address _beneficiary) external onlyOwner {
    caps[_beneficiary] = 0;
    accredited[_beneficiary] = false;
  }

  /**
   * @dev Extend parent behavior requiring beneficiary to be in whitelist.
   * @param _beneficiary Token beneficiary
   * @param _weiAmount Amount of wei contributed
   */
  function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
    super._preValidatePurchase(_beneficiary, _weiAmount);
    require(contributions[_beneficiary].add(_weiAmount) <= caps[_beneficiary]);
  }

  /**
   * @dev Extend parent behavior to update user contributions
   * @param _beneficiary Token purchaser
   * @param _weiAmount Amount of wei contributed
   */
  function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
    super._updatePurchasingState(_beneficiary, _weiAmount);
    contributions[_beneficiary] = contributions[_beneficiary].add(_weiAmount);
  }

}
/**
 * @title WhitelistedAICrowdsale
 * @dev Crowdsale in which only whitelisted users can contribute,
 * with a defined individual cap in wei,
 * and a bool flag on whether a user is an accredited investor (AI)
 * Based on OpenZeppelin's WhitelistedCrowdsale and IndividuallyCappedCrowdsale
 * @author U-Zyn Chua <uzyn@zynesis.com>
 */
function removeFromWhitelist(address _beneficiary) external onlyOwner {
  caps[_beneficiary] = 0;
  accredited[_beneficiary] = false;
}

/**
 * @dev Removes single address from whitelist.
 * @param _beneficiary Address to be removed to the whitelist
 */