function purchaseTicketsWithReferral(uint[] _tickets, uint _affiliateCode) public payable {
		
		
		if (state != State.Running) {
			if (state == State.NotRunning) return failPurchase(PurchaseError.LotteryClosed);
			return failPurchase(PurchaseError.OutOfTickets);
		}

		
		if (msg.value < _tickets.length * game.rules.ticketPrice) 
			return failPurchase(PurchaseError.NotEnoughFunds);

		uint[] memory _userTickets = getMyTickets();

		
		if (_userTickets.length >= game.rules.maxTicketsPer)
			return failPurchase(PurchaseError.TooManyTickets);

		
		
		uint[] memory _successful = new uint[](_tickets.length);
		uint[] memory _failed = new uint[](_tickets.length);
		PurchaseError[] memory _errors = new PurchaseError[](_tickets.length);
		uint _successCount;
		uint _errorCount;

		for(uint i = 0; i < _tickets.length; i++) {
			uint _ticket = _tickets[i];

			
			if (_ticket <= 0 || _ticket > game.rules.slots) {
				_failed[_errorCount] = _ticket;
				_errors[_errorCount] = PurchaseError.InvalidTicket;
				_errorCount++;
				continue;
			}

			
			if (game.tickets[_ticket] != address(0)) {
				_failed[_errorCount] = _ticket;
				_errors[_errorCount] = PurchaseError.TicketUnavailable;
				_errorCount++;
				continue;
			}

			
			if (_userTickets.length + _successCount >= game.rules.maxTicketsPer) {
				_failed[_errorCount] = _ticket;
				_errors[_errorCount] = PurchaseError.TooManyTickets;
				_errorCount++;
				continue;
			}

			game.tickets[_ticket] = msg.sender;
			game.ticketsSold++;

			_successful[_successCount] = _ticket;
			_successCount++;
		}

		
		
		if (_errorCount > 0) refund(_errorCount * game.rules.ticketPrice);
		
		
		uint _userAffiliateCode = userAffiliate();
		if (_affiliateCode != 0 && _userAffiliateCode == 0)
			_userAffiliateCode = setUserAffiliate(_affiliateCode);
		if (_userAffiliateCode != 0) addAffiliate(_userAffiliateCode, _successCount);

		
		TicketsPurchased(msg.sender, _successful, _failed, _errors);

		
		if (game.ticketsSold >= game.rules.slots) findWinner();
	}