text:
package org.kuali.kfs.module.endow.report.service.impl;

import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.kuali.kfs.module.endow.EndowConstants;
import org.kuali.kfs.module.endow.EndowConstants.EndowmentTransactionTypeCodes;
import org.kuali.kfs.module.endow.EndowPropertyConstants;
import org.kuali.kfs.module.endow.businessobject.HoldingHistory;
import org.kuali.kfs.module.endow.businessobject.KEMID;
import org.kuali.kfs.module.endow.businessobject.KemidHistoricalCash;
import org.kuali.kfs.module.endow.businessobject.MonthEndDate;
import org.kuali.kfs.module.endow.businessobject.TransactionArchive;
import org.kuali.kfs.module.endow.businessobject.TransactionArchiveSecurity;
import org.kuali.kfs.module.endow.dataaccess.HoldingHistoryDao;
import org.kuali.kfs.module.endow.dataaccess.TransactionArchiveDao;
import org.kuali.kfs.module.endow.report.service.TransactionSummaryReportService;
import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder;
import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.CashTransfersDataHolder;
import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.ContributionsDataHolder;
import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.ExpensesDataHolder;
import org.kuali.kfs.module.endow.report.util.TransactionSummaryReportDataHolder.SecurityTransfersDataHolder;
import org.kuali.rice.core.api.util.type.KualiInteger;
import org.kuali.rice.krad.util.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class TransactionSummaryReportServiceImpl extends EndowmentReportServiceImpl implements TransactionSummaryReportService {

    protected TransactionArchiveDao transactionArchiveDao;
    protected HoldingHistoryDao holdingHistoryDao;

    /**
     *
     * @see org.kuali.kfs.module.endow.report.service.TrialBalanceReportService#getTrialBalanceReportForAllKemids(java.lang.String)
     */
    public List<TransactionSummaryReportDataHolder> getTransactionSummaryReportForAllKemids(String beginningDate, String endingDate, String endowmentOption, String closedIndicator, String reportOption) {
        return getTransactionSummaryReportsByKemidByIds(null, beginningDate, endingDate, endowmentOption, closedIndicator, reportOption);
    }

    /**
     *
     * @see org.kuali.kfs.module.endow.report.service.TransactionStatementReportService#getTransactionStatementReportsByKemidByIds(java.util.List, java.lang.String)
     */
    public List<TransactionSummaryReportDataHolder> getTransactionSummaryReportsByKemidByIds(List<String> kemids, String beginningDate, String endingDate, String endowmentOption, String closedIndicator, String reportOption) {

        List<TransactionSummaryReportDataHolder> transactionSummaryReportList = new ArrayList<TransactionSummaryReportDataHolder>();

        Date beginDate = convertStringToDate(beginningDate);
        Date endDate = convertStringToDate(endingDate);
        if (ObjectUtils.isNull(beginDate) || ObjectUtils.isNull(beginDate)) {
            return null;
        }
        //gather kemids based on the user selection of endowmentOption and closed indicators...
        kemids = getKemidsBasedOnUserSelection(kemids, endowmentOption, closedIndicator);

        if (kemids.size() == 0) {
            return null;
        }

        //eliminate kemids that are not in
        kemids = getKemidsInHistoryCash(kemids, beginningDate, endingDate);

        if (kemids.size() == 0) {
            return null;
        }

        MonthEndDate beginningMED = getPreviousMonthEndDate(convertStringToDate(beginningDate));
        MonthEndDate endingMED = getMonthEndDate(convertStringToDate(endingDate));

        for (String kemid : kemids) {
            TransactionSummaryReportDataHolder transactionSummaryReportDataHolder = new TransactionSummaryReportDataHolder();

            List<HoldingHistory> holdingHistoryList = holdingHistoryDao.getHoldingHistoryByKemid(kemid);

            getHistoryCashAmounts(transactionSummaryReportDataHolder, kemid, beginningMED.getMonthEndDateId(), endingMED.getMonthEndDateId());

            for (HoldingHistory holdingHistory : holdingHistoryList) {
                //if month end beginning date
                if (holdingHistory.getMonthEndDateId().equals(beginningMED.getMonthEndDateId())) {
                    if (holdingHistory.getIncomePrincipalIndicator().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                        transactionSummaryReportDataHolder.setIncomeBeginningMarketValue(transactionSummaryReportDataHolder.getIncomeBeginningMarketValue().add(holdingHistory.getMarketValue()));
                    }
                    if (holdingHistory.getIncomePrincipalIndicator().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                        transactionSummaryReportDataHolder.setPrincipalBeginningMarketValue(transactionSummaryReportDataHolder.getPrincipalBeginningMarketValue().add(holdingHistory.getMarketValue()));
                    }
                }
                // if month end ending date ..
                if (holdingHistory.getMonthEndDateId().equals(endingMED.getMonthEndDateId())) {
                    if (holdingHistory.getIncomePrincipalIndicator().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                        transactionSummaryReportDataHolder.setIncomeEndingMarketValue(transactionSummaryReportDataHolder.getIncomeEndingMarketValue().add(holdingHistory.getMarketValue()));
                    }
                    if (holdingHistory.getIncomePrincipalIndicator().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                        transactionSummaryReportDataHolder.setPrincipalEndingMarketValue(transactionSummaryReportDataHolder.getPrincipalEndingMarketValue().add(holdingHistory.getMarketValue()));
                    }
                }

                //start calculating change in market value. It will also be calculated during transaction archive records calculations
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeEndingMarketValue().subtract(transactionSummaryReportDataHolder.getIncomeBeginningMarketValue()));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalEndingMarketValue().subtract(transactionSummaryReportDataHolder.getPrincipalBeginningMarketValue()));

                transactionSummaryReportDataHolder.setNext12MonthsEstimatedIncome(transactionSummaryReportDataHolder.getNext12MonthsEstimatedIncome().add(holdingHistory.getEstimatedIncome()));
                transactionSummaryReportDataHolder.setRemainderOfFYEstimatedIncome(transactionSummaryReportDataHolder.getRemainderOfFYEstimatedIncome().add(holdingHistory.getRemainderOfFYEstimatedIncome()));
                transactionSummaryReportDataHolder.setNextFYEstimatedIncome(transactionSummaryReportDataHolder.getNextFYEstimatedIncome().add(holdingHistory.getNextFYEstimatedIncome()));
            }

            //get the transaction archive records now....
            List<TransactionArchive> transactionArchives = transactionArchiveDao.getTransactionArchivesByKemid(kemid, beginDate, endDate);

            for (TransactionArchive transactionArchive : transactionArchives) {
                transactionArchive.refreshNonUpdateableReferences();

                if (EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_TRANSFER.equalsIgnoreCase(transactionArchive.getTypeCode()) ||
                        EndowConstants.DocumentTypeNames.ENDOWMENT_SECURITY_TRANSFER.equalsIgnoreCase(transactionArchive.getTypeCode())) {
                    //cash transfers...
                    if (EndowConstants.DocumentTypeNames.ENDOWMENT_CASH_TRANSFER.equalsIgnoreCase(transactionArchive.getTypeCode())) {
                        getTransactionArchiveTotalsForCashTransfers(transactionSummaryReportDataHolder, transactionArchive);
                    }
                    //security tranfers....
                    if (EndowConstants.DocumentTypeNames.ENDOWMENT_SECURITY_TRANSFER.equalsIgnoreCase(transactionArchive.getTypeCode())) {
                        getTransactionArchiveTotalsForSecurityTransfers(transactionSummaryReportDataHolder, transactionArchive);
                    }
                }
                else {
                    //income type code...
                    if (transactionArchive.getEtranObj().getEndowmentTransactionTypeCode().equalsIgnoreCase(EndowmentTransactionTypeCodes.INCOME_TYPE_CODE)) {
                        getTransactionArchiveTotalsForIncomeTypeCode(transactionSummaryReportDataHolder, transactionArchive);
                    }
                    //expense type code...
                    if (transactionArchive.getEtranObj().getEndowmentTransactionTypeCode().equalsIgnoreCase(EndowmentTransactionTypeCodes.EXPENSE_TYPE_CODE)) {
                        getTransactionArchiveTotalsForExpenseTypeCode(transactionSummaryReportDataHolder, transactionArchive);
                    }
                }
            }

            //combine the similar etrancode records in the list for
            //contributions, expenses, cash transfers, and security transfers....
            if (transactionSummaryReportDataHolder.getReportGroupsForContributions().size() > 0) {
                combineContributionsData(transactionSummaryReportDataHolder);
            }

            if (transactionSummaryReportDataHolder.getReportGroupsForExpenses().size() > 0) {
                combineExpensesData(transactionSummaryReportDataHolder);
            }

            if (transactionSummaryReportDataHolder.getReportGroupsForCashTransfers().size() > 0) {
                combineCashTransfersData(transactionSummaryReportDataHolder);
            }

            if (transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers().size() > 0) {
                combineSecurityTransfersData(transactionSummaryReportDataHolder);
            }

            //setup the report header information....
            transactionSummaryReportDataHolder.setInstitution(getInstitutionName());
            transactionSummaryReportDataHolder.setKemid(kemid);

            KEMID kemidObj = getKemid(kemid);

            transactionSummaryReportDataHolder.setKemidLongTitle(kemidObj.getLongTitle());
            transactionSummaryReportDataHolder.setBeginningDate(beginningDate);
            transactionSummaryReportDataHolder.setEndingDate(endingDate);

            //setup the report footer information...Only for Detail report option
            if (!reportOption.equalsIgnoreCase(EndowConstants.EndowmentReport.TOTAL)) {
                transactionSummaryReportDataHolder.setFooter(createFooterData(kemidObj));
            }

            // add this new one
            transactionSummaryReportList.add(transactionSummaryReportDataHolder);
        }

        return transactionSummaryReportList;
    }

    /**
     * Method to retrieve the records from END_HIST_CSH_T table for the given
     * kemid and retrieve the the income and principal cash amounts.
     * @param kemid
     * @param historyIncomeCash
     * @param historyPrincipalCash
     * @param beginningMED
     * @param endingMED
     */
    protected void getHistoryCashAmounts(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder, String kemid, KualiInteger beginningMed, KualiInteger endingMed) {
        List<String> kemids = new ArrayList<String>();
        kemids.add(kemid);

        List<KemidHistoricalCash> kemidHistoryCash = kemidHistoricalCashDao.getHistoricalCashRecords(kemids, beginningMed, endingMed);

        for (KemidHistoricalCash historyCash : kemidHistoryCash) {
            if (historyCash.getMonthEndDateId().equals(beginningMed)) {
                transactionSummaryReportDataHolder.setIncomeBeginningMarketValue(historyCash.getHistoricalIncomeCash().bigDecimalValue());
                transactionSummaryReportDataHolder.setPrincipalBeginningMarketValue(historyCash.getHistoricalPrincipalCash().bigDecimalValue());
            }
            if (historyCash.getMonthEndDateId().equals(endingMed)) {
                transactionSummaryReportDataHolder.setIncomeEndingMarketValue(historyCash.getHistoricalIncomeCash().bigDecimalValue());
                transactionSummaryReportDataHolder.setPrincipalEndingMarketValue(historyCash.getHistoricalPrincipalCash().bigDecimalValue());
            }
        }
    }

    /**
     *
     * @see org.kuali.kfs.module.endow.report.service.TransactionStatementReportService#getTransactionStatementReportsByOtherCriteria(java.util.List, java.util.List, java.util.List, java.util.List, java.util.List, java.util.List, java.lang.String)
     */
    public List<TransactionSummaryReportDataHolder> getTransactionSummaryReportsByOtherCriteria(List<String> benefittingOrganziationCampusCodes, List<String> benefittingOrganziationChartCodes,
            List<String> benefittingOrganziationCodes, List<String> typeCodes, List<String> purposeCodes, List<String> combineGroupCodes, String beginningDate, String endingDate, String endowmnetOption, String closedIndicator, String reportOption) {

        List<String> kemids = getKemidsByOtherCriteria(benefittingOrganziationCampusCodes, benefittingOrganziationChartCodes,
                benefittingOrganziationCodes, typeCodes, purposeCodes, combineGroupCodes);

        // Now that we have all the kemids to be reported by the use of the other criteria, go to get the report data
        if (kemids.size() == 0) {
            return null;
        } else {
            return getTransactionSummaryReportsByKemidByIds(kemids, beginningDate, endingDate, endowmnetOption, closedIndicator, reportOption);
        }
    }

    /**
     * Method to look into each transaction archive record and gather income or principal amounts.
     *
     * @param transactionSummaryReportDataHolder
     * @param transactionArchive
     */
    protected void getTransactionArchiveTotalsForIncomeTypeCode(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder, TransactionArchive transactionArchive) {
        transactionArchive.refreshNonUpdateableReferences();

        BigDecimal transactionSecurityCostIncome = BigDecimal.ZERO;
        BigDecimal transactionSecurityCostPrincipal = BigDecimal.ZERO;

        //get the transaction archive data totals....
        List<TransactionArchiveSecurity> archiveSecurities = transactionArchive.getArchiveSecurities();
        for (TransactionArchiveSecurity archiveSecurity : archiveSecurities) {
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                transactionSecurityCostIncome = transactionSecurityCostIncome.add(archiveSecurity.getHoldingCost());
            }
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                transactionSecurityCostPrincipal = transactionSecurityCostPrincipal.add(archiveSecurity.getHoldingCost());
            }
        }

        ContributionsDataHolder contributionsData = transactionSummaryReportDataHolder.new ContributionsDataHolder();
        contributionsData.setContributionsDescription(transactionArchive.getEtranObj().getName());

        //get the transaction archive data totals....
     //   List<TransactionArchiveSecurity> archiveSecurities = transactionArchive.getArchiveSecurities();
     //   for (TransactionArchiveSecurity archiveSecurity : archiveSecurities) {
     //       transactionSecurityCost = transactionSecurityCost.add(archiveSecurity.getHoldingCost());
     //   }
        //income type code...
        if (transactionArchive.getEtranObj().getEndowmentTransactionTypeCode().equalsIgnoreCase(EndowmentTransactionTypeCodes.INCOME_TYPE_CODE)) {
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                contributionsData.setIncomeContributions(transactionSecurityCostIncome.add(contributionsData.getIncomeContributions().add(transactionArchive.getIncomeCashAmount())));
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(contributionsData.getIncomeContributions()));
            }

            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                contributionsData.setPrincipalContributions(transactionSecurityCostPrincipal.add(contributionsData.getPrincipalContributions().add(transactionArchive.getPrincipalCashAmount())));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(contributionsData.getPrincipalContributions()));
            }
        }

        transactionSummaryReportDataHolder.getReportGroupsForContributions().add(contributionsData);
    }

    /**
     * Method to look into each transaction archive record and gather income or principal amounts.
     *
     * @param transactionSummaryReportDataHolder
     * @param transactionArchive
     */
    protected void getTransactionArchiveTotalsForExpenseTypeCode(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder, TransactionArchive transactionArchive) {
        BigDecimal transactionSecurityCostIncome = BigDecimal.ZERO;
        BigDecimal transactionSecurityCostPrincipal = BigDecimal.ZERO;

        //get the transaction archive data totals....
        List<TransactionArchiveSecurity> archiveSecurities = transactionArchive.getArchiveSecurities();
        for (TransactionArchiveSecurity archiveSecurity : archiveSecurities) {
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                transactionSecurityCostIncome = transactionSecurityCostIncome.add(archiveSecurity.getHoldingCost());
            }
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                transactionSecurityCostPrincipal = transactionSecurityCostPrincipal.add(archiveSecurity.getHoldingCost());
            }
        }

        ExpensesDataHolder expensesDataHolder = transactionSummaryReportDataHolder.new ExpensesDataHolder();
        expensesDataHolder.setExpensesDescription(transactionArchive.getEtranObj().getName());

        //get the transaction archive data totals....
     //   List<TransactionArchiveSecurity> archiveSecurities = transactionArchive.getArchiveSecurities();
     //   for (TransactionArchiveSecurity archiveSecurity : archiveSecurities) {
     //       transactionSecurityCost = transactionSecurityCost.add(archiveSecurity.getHoldingCost());
    //    }

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
            expensesDataHolder.setIncomeExpenses(transactionSecurityCostIncome.add(expensesDataHolder.getIncomeExpenses().add(transactionArchive.getIncomeCashAmount())));
            transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(expensesDataHolder.getIncomeExpenses()));
        }

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
            expensesDataHolder.setPrincipalExpenses(transactionSecurityCostPrincipal.add(expensesDataHolder.getPrincipalExpenses().add(transactionArchive.getPrincipalCashAmount())));
            transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(expensesDataHolder.getPrincipalExpenses()));
        }

        transactionSummaryReportDataHolder.getReportGroupsForExpenses().add(expensesDataHolder);
    }

    /**
     * Cash Transfers.....
     *
     * @param transactionSummaryReportDataHolder
     * @param transactionArchive
     */
    protected void getTransactionArchiveTotalsForCashTransfers(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder, TransactionArchive transactionArchive) {
        CashTransfersDataHolder cashTransfersDataHolder = transactionSummaryReportDataHolder.new CashTransfersDataHolder();
        cashTransfersDataHolder.setCashTransfersDescription(transactionArchive.getEtranObj().getName());

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
            cashTransfersDataHolder.setIncomeCashTransfers(cashTransfersDataHolder.getIncomeCashTransfers().add(transactionArchive.getIncomeCashAmount()));
            transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(cashTransfersDataHolder.getIncomeCashTransfers()));
        }

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
            cashTransfersDataHolder.setPrincipalCashTransfers(cashTransfersDataHolder.getPrincipalCashTransfers().add(transactionArchive.getPrincipalCashAmount()));
            transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(cashTransfersDataHolder.getPrincipalCashTransfers()));
        }

        transactionSummaryReportDataHolder.getReportGroupsForCashTransfers().add(cashTransfersDataHolder);
    }

    /**
     * Security Transfers.....
     *
     * @param transactionSummaryReportDataHolder
     * @param transactionArchive
     */
    protected void getTransactionArchiveTotalsForSecurityTransfers(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder, TransactionArchive transactionArchive) {
        SecurityTransfersDataHolder securityTransfersDataHolder = transactionSummaryReportDataHolder.new SecurityTransfersDataHolder();
        securityTransfersDataHolder.setSecurityTransfersDescription(transactionArchive.getEtranObj().getName());

        BigDecimal transactionSecurityCostIncome = BigDecimal.ZERO;
        BigDecimal transactionSecurityCostPrincipal = BigDecimal.ZERO;

        //get the transaction archive data totals....
        List<TransactionArchiveSecurity> archiveSecurities = transactionArchive.getArchiveSecurities();
        for (TransactionArchiveSecurity archiveSecurity : archiveSecurities) {
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
                transactionSecurityCostIncome = transactionSecurityCostIncome.add(archiveSecurity.getHoldingCost());
            }
            if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
                transactionSecurityCostPrincipal = transactionSecurityCostPrincipal.add(archiveSecurity.getHoldingCost());
            }
        }

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.INCOME)) {
            securityTransfersDataHolder.setIncomeSecurityTransfers(securityTransfersDataHolder.getIncomeSecurityTransfers().add(transactionSecurityCostIncome));
            transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(securityTransfersDataHolder.getIncomeSecurityTransfers()));
        }

        if (transactionArchive.getIncomePrincipalIndicatorCode().equalsIgnoreCase(EndowConstants.IncomePrincipalIndicator.PRINCIPAL)) {
            securityTransfersDataHolder.setPrincipalSecurityTransfers(securityTransfersDataHolder.getPrincipalSecurityTransfers().add(transactionSecurityCostPrincipal));
            transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(securityTransfersDataHolder.getPrincipalSecurityTransfers()));
        }

        transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers().add(securityTransfersDataHolder);
    }

    /**
     * Helper method to first retrieve all the contributions records and go over all of them
     * to combine based on same description of the contributions.  The combined records are then
     * added to the data holder.
     *
     * @param transactionSummaryReportDataHolder
     */
    protected void combineContributionsData(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
        String contributionsDescription = null;
        BigDecimal incomeContributionsAmount = BigDecimal.ZERO;
        BigDecimal PrincipalContributionsAmount = BigDecimal.ZERO;

        List<ContributionsDataHolder> contributionsDataList = new ArrayList<ContributionsDataHolder>();

        ContributionsDataHolder combinedContributionsData = transactionSummaryReportDataHolder.new ContributionsDataHolder();

        List<ContributionsDataHolder> contributionsData = transactionSummaryReportDataHolder.getReportGroupsForContributions();

        for (ContributionsDataHolder contributionData : contributionsData) {
            if (contributionsDescription == null) {
                contributionsDescription = contributionData.getContributionsDescription();
            }
            //same description == same etran code so combine the totals.....
            if (contributionsDescription.equals(contributionData.getContributionsDescription())) {
                incomeContributionsAmount = incomeContributionsAmount.add(contributionData.getIncomeContributions());
                PrincipalContributionsAmount = PrincipalContributionsAmount.add(contributionData.getPrincipalContributions());
            }
            else { //write out the record....
                combinedContributionsData.setContributionsDescription(contributionsDescription);
                combinedContributionsData.setIncomeContributions(incomeContributionsAmount);
                combinedContributionsData.setPrincipalContributions(PrincipalContributionsAmount);
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeContributionsAmount));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalContributionsAmount));
                contributionsDataList.add(combinedContributionsData);

                //create a new holder...
                incomeContributionsAmount = BigDecimal.ZERO;
                PrincipalContributionsAmount = BigDecimal.ZERO;
                combinedContributionsData = transactionSummaryReportDataHolder.new ContributionsDataHolder();
                contributionsDescription = contributionData.getContributionsDescription();
                incomeContributionsAmount = incomeContributionsAmount.add(contributionData.getIncomeContributions());
                PrincipalContributionsAmount = PrincipalContributionsAmount.add(contributionData.getPrincipalContributions());
            }
        }

        //add the last data holder....
        combinedContributionsData.setContributionsDescription(contributionsDescription);
        combinedContributionsData.setIncomeContributions(incomeContributionsAmount);
        combinedContributionsData.setPrincipalContributions(PrincipalContributionsAmount);
        transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeContributionsAmount));
        transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalContributionsAmount));
        contributionsDataList.add(combinedContributionsData);

        //now remove the current list of contributions and add the newly created combined list.
        transactionSummaryReportDataHolder.getReportGroupsForContributions().removeAll(contributionsData);
        transactionSummaryReportDataHolder.getReportGroupsForContributions().addAll(contributionsDataList);
    }

    /**
     * Helper method to first retrieve all the expenses records and go over all of them
     * to combine based on same description of the expenses.  The combined records are then
     * added to the data holder.
     *
     * @param transactionSummaryReportDataHolder
     */
    protected void combineExpensesData(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
        String expensesDescription = null;
        BigDecimal incomeExpensesAmount = BigDecimal.ZERO;
        BigDecimal PrincipalExpensesAmount = BigDecimal.ZERO;

        List<ExpensesDataHolder> expensesDataList = new ArrayList<ExpensesDataHolder>();

        ExpensesDataHolder combinedExpensesData = transactionSummaryReportDataHolder.new ExpensesDataHolder();

        List<ExpensesDataHolder> expensesData = transactionSummaryReportDataHolder.getReportGroupsForExpenses();

        for (ExpensesDataHolder expenseData : expensesData) {
            if (expensesDescription == null) {
                expensesDescription = expenseData.getExpensesDescription();
            }
            //same description == same etran code so combine the totals.....
            if (expensesDescription.equals(expenseData.getExpensesDescription())) {
                incomeExpensesAmount = incomeExpensesAmount.add(expenseData.getIncomeExpenses());
                PrincipalExpensesAmount = PrincipalExpensesAmount.add(expenseData.getPrincipalExpenses());
            }
            else { //write out the record....
                combinedExpensesData.setExpensesDescription(expensesDescription);
                combinedExpensesData.setIncomeExpenses(incomeExpensesAmount);
                combinedExpensesData.setPrincipalExpenses(PrincipalExpensesAmount);
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeExpensesAmount));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalExpensesAmount));
                expensesDataList.add(combinedExpensesData);

                //create a new holder...
                incomeExpensesAmount = BigDecimal.ZERO;
                PrincipalExpensesAmount = BigDecimal.ZERO;
                combinedExpensesData = transactionSummaryReportDataHolder.new ExpensesDataHolder();
                expensesDescription = expenseData.getExpensesDescription();
                incomeExpensesAmount = incomeExpensesAmount.add(expenseData.getIncomeExpenses());
                PrincipalExpensesAmount = PrincipalExpensesAmount.add(expenseData.getPrincipalExpenses());
            }
        }

        //add the last data holder....
        combinedExpensesData.setExpensesDescription(expensesDescription);
        combinedExpensesData.setIncomeExpenses(incomeExpensesAmount);
        combinedExpensesData.setPrincipalExpenses(PrincipalExpensesAmount);
        transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeExpensesAmount));
        transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalExpensesAmount));
        expensesDataList.add(combinedExpensesData);

        //now remove the current list of contributions and add the newly created combined list.
        transactionSummaryReportDataHolder.getReportGroupsForExpenses().removeAll(expensesData);
        transactionSummaryReportDataHolder.getReportGroupsForExpenses().addAll(expensesDataList);
    }

    /**
     * Helper method to first retrieve all the Cash Transfers records and go over all of them
     * to combine based on same description of the expenses.  The combined records are then
     * added to the data holder.
     *
     * @param transactionSummaryReportDataHolder
     */
    protected void combineCashTransfersData(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
        String cashTransfersDescription = null;
        BigDecimal incomeCashTransfersAmount = BigDecimal.ZERO;
        BigDecimal PrincipalCashTransfersAmount = BigDecimal.ZERO;

        List<CashTransfersDataHolder> cashTransfersDataList = new ArrayList<CashTransfersDataHolder>();

        CashTransfersDataHolder combinedCashTransfersData = transactionSummaryReportDataHolder.new CashTransfersDataHolder();

        List<CashTransfersDataHolder> cashTransfersData = transactionSummaryReportDataHolder.getReportGroupsForCashTransfers();

        for (CashTransfersDataHolder cashTransferData : cashTransfersData) {
            if (cashTransfersDescription == null) {
                cashTransfersDescription = cashTransferData.getCashTransfersDescription();
            }
            //same description == same etran code so combine the totals.....
            if (cashTransfersDescription.equals(cashTransferData.getCashTransfersDescription())) {
                incomeCashTransfersAmount = incomeCashTransfersAmount.add(cashTransferData.getIncomeCashTransfers());
                PrincipalCashTransfersAmount = PrincipalCashTransfersAmount.add(cashTransferData.getPrincipalCashTransfers());
            }
            else { //write out the record....
                combinedCashTransfersData.setCashTransfersDescription(cashTransfersDescription);
                combinedCashTransfersData.setIncomeCashTransfers(incomeCashTransfersAmount);
                combinedCashTransfersData.setPrincipalCashTransfers(PrincipalCashTransfersAmount);
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeCashTransfersAmount));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalCashTransfersAmount));
                cashTransfersDataList.add(combinedCashTransfersData);

                //create a new holder...
                incomeCashTransfersAmount = BigDecimal.ZERO;
                PrincipalCashTransfersAmount = BigDecimal.ZERO;
                combinedCashTransfersData = transactionSummaryReportDataHolder.new CashTransfersDataHolder();
                cashTransfersDescription = cashTransferData.getCashTransfersDescription();
                incomeCashTransfersAmount = incomeCashTransfersAmount.add(cashTransferData.getIncomeCashTransfers());
                PrincipalCashTransfersAmount = PrincipalCashTransfersAmount.add(cashTransferData.getPrincipalCashTransfers());
            }
        }

        //add the last data holder....
        combinedCashTransfersData.setCashTransfersDescription(cashTransfersDescription);
        combinedCashTransfersData.setIncomeCashTransfers(incomeCashTransfersAmount);
        combinedCashTransfersData.setPrincipalCashTransfers(PrincipalCashTransfersAmount);
        transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeCashTransfersAmount));
        transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(PrincipalCashTransfersAmount));
        cashTransfersDataList.add(combinedCashTransfersData);

        //now remove the current list of contributions and add the newly created combined list.
        transactionSummaryReportDataHolder.getReportGroupsForCashTransfers().removeAll(cashTransfersData);
        transactionSummaryReportDataHolder.getReportGroupsForCashTransfers().addAll(cashTransfersDataList);
    }

    /**
     * Helper method to first retrieve all the Security Transfers records and go over all of them
     * to combine based on same description of the expenses.  The combined records are then
     * added to the data holder.
     *
     * @param transactionSummaryReportDataHolder
     */
    protected void combineSecurityTransfersData(TransactionSummaryReportDataHolder transactionSummaryReportDataHolder) {
        String securityTransfersDescription = null;
        BigDecimal incomeSecurityTransfersAmount = BigDecimal.ZERO;
        BigDecimal principalSecurityTransfersAmount = BigDecimal.ZERO;

        List<SecurityTransfersDataHolder> securityTransfersDataList = new ArrayList<SecurityTransfersDataHolder>();

        SecurityTransfersDataHolder combinedSecurityTransfersData = transactionSummaryReportDataHolder.new SecurityTransfersDataHolder();

        List<SecurityTransfersDataHolder> securityTransfersData = transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers();

        for (SecurityTransfersDataHolder securityTransferData : securityTransfersData) {
            if (securityTransfersDescription == null) {
                securityTransfersDescription = securityTransferData.getSecurityTransfersDescription();
            }
            //same description == same etran code so combine the totals.....
            if (securityTransfersDescription.equals(securityTransferData.getSecurityTransfersDescription())) {
                incomeSecurityTransfersAmount = incomeSecurityTransfersAmount.add(securityTransferData.getIncomeSecurityTransfers());
                principalSecurityTransfersAmount = principalSecurityTransfersAmount.add(securityTransferData.getPrincipalSecurityTransfers());
            }
            else { //write out the record....
                combinedSecurityTransfersData.setSecurityTransfersDescription(securityTransfersDescription);
                combinedSecurityTransfersData.setIncomeSecurityTransfers(incomeSecurityTransfersAmount);
                combinedSecurityTransfersData.setPrincipalSecurityTransfers(principalSecurityTransfersAmount);
                transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeSecurityTransfersAmount));
                transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(principalSecurityTransfersAmount));
                securityTransfersDataList.add(combinedSecurityTransfersData);

                //create a new holder...
                incomeSecurityTransfersAmount = BigDecimal.ZERO;
                principalSecurityTransfersAmount = BigDecimal.ZERO;
                combinedSecurityTransfersData = transactionSummaryReportDataHolder.new SecurityTransfersDataHolder();
                securityTransfersDescription = securityTransferData.getSecurityTransfersDescription();
                incomeSecurityTransfersAmount = incomeSecurityTransfersAmount.add(securityTransferData.getIncomeSecurityTransfers());
                principalSecurityTransfersAmount = principalSecurityTransfersAmount.add(securityTransferData.getPrincipalSecurityTransfers());
            }
        }

        //add the last data holder....
        combinedSecurityTransfersData.setSecurityTransfersDescription(securityTransfersDescription);
        combinedSecurityTransfersData.setIncomeSecurityTransfers(incomeSecurityTransfersAmount);
        combinedSecurityTransfersData.setPrincipalSecurityTransfers(principalSecurityTransfersAmount);
        transactionSummaryReportDataHolder.setIncomeChangeInMarketValue(transactionSummaryReportDataHolder.getIncomeChangeInMarketValue().subtract(incomeSecurityTransfersAmount));
        transactionSummaryReportDataHolder.setPrincipalChangeInMarketValue(transactionSummaryReportDataHolder.getPrincipalChangeInMarketValue().subtract(principalSecurityTransfersAmount));
        securityTransfersDataList.add(combinedSecurityTransfersData);

        //now remove the current list of contributions and add the newly created combined list.
        transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers().removeAll(securityTransfersData);
        transactionSummaryReportDataHolder.getReportGroupsForSecurityTransfers().addAll(securityTransfersDataList);
    }

    protected KEMID getKemid(String kemid) {
        Map<String,String> primaryKeys = new HashMap<String,String>();
        primaryKeys.put(EndowPropertyConstants.KEMID, kemid);
        return (KEMID) businessObjectService.findByPrimaryKey(KEMID.class, primaryKeys);
    }

    protected KemidHistoricalCash getKemidHistoricalCash(String kemid, KualiInteger medId) {
        Map<String,Object> primaryKeys = new HashMap<String,Object>();
        primaryKeys.put(EndowPropertyConstants.ENDOWMENT_HIST_CASH_KEMID, kemid);
        primaryKeys.put(EndowPropertyConstants.ENDOWMENT_HIST_CASH_MED_ID, medId);
        return (KemidHistoricalCash) businessObjectService.findByPrimaryKey(KemidHistoricalCash.class, primaryKeys);
    }

    protected String convertDateToString(Date date) {
        return dateTimeService.toDateString(date);
    }

    public void setTransactionArchiveDao(TransactionArchiveDao transactionArchiveDao) {
        this.transactionArchiveDao = transactionArchiveDao;
    }

    protected TransactionArchiveDao getTransactionArchiveDao() {
        return transactionArchiveDao;
    }

    /**
     * gets attribute holdingHistoryDao
     * @return holdingHistoryDao
     */
    protected HoldingHistoryDao getHoldingHistoryDao() {
        return holdingHistoryDao;
    }

    /**
     * sets attribute holdingHistoryDao
     */
    public void setHoldingHistoryDao(HoldingHistoryDao holdingHistoryDao) {
        this.holdingHistoryDao = holdingHistoryDao;
    }
}


text:
module FeatureMatchers
  def have_fixture(fixture)
    have_css('td.text-center', text: fixture.date) &&
      have_css('td.text-center', text: fixture.home.name) &&
      have_css('td.text-center', text: fixture.home.name) &&
      have_css('td.text-center', text: fixture.competition.abbreviation)
  end

  def have_result(fixture)
    have_fixture(fixture) &&
      have_css('td.text-center', text: "#{fixture.home_score} - #{fixture.away_score}")
  end
end

redpajama_set_name: RedPajamaGithub


text:
""" Non-negative matrix factorization
"""
# Author: Vlad Niculae
#         Lars Buitinck <L.J.Buitinck@uva.nl>
# Author: Chih-Jen Lin, National Taiwan University (original projected gradient
#     NMF implementation)
# Author: Anthony Di Franco (original Python and NumPy port)
# License: BSD

from __future__ import division

from ..base import BaseEstimator, TransformerMixin
from ..utils import atleast2d_or_csr, check_random_state
from ..utils.extmath import randomized_svd, safe_sparse_dot

import numpy as np
from scipy.optimize import nnls
import scipy.sparse as sp
import warnings

def _pos(x):
    """Positive part of a vector / matrix"""
    return (x >= 0) * x

def _neg(x):
    """Negative part of a vector / matrix"""
    neg_x = -x
    neg_x *= x < 0
    return neg_x

def norm(x):
    """Dot product-based Euclidean norm implementation

    See: http://fseoane.net/blog/2011/computing-the-vector-norm/
    """
    x = x.ravel()
    return np.sqrt(np.dot(x.T, x))

def _sparseness(x):
    """Hoyer's measure of sparsity for a vector"""
    sqrt_n = np.sqrt(len(x))
    return (sqrt_n - np.linalg.norm(x, 1) / norm(x)) / (sqrt_n - 1)

def check_non_negative(X, whom):
    X = X.data if sp.issparse(X) else X
    if (X < 0).any():
        raise ValueError("Negative values in data passed to %s" % whom)

def _initialize_nmf(X, n_components, variant=None, eps=1e-6,
                    random_state=None):
    """NNDSVD algorithm for NMF initialization.

    Computes a good initial guess for the non-negative
    rank k matrix approximation for X: X = WH

    Parameters
    ----------

    X: array, [n_samples, n_features]
        The data matrix to be decomposed.

    n_components:
        The number of components desired in the
        approximation.

    variant: None | 'a' | 'ar'
        The variant of the NNDSVD algorithm.
        Accepts None, 'a', 'ar'
        None: leaves the zero entries as zero
        'a': Fills the zero entries with the average of X
        'ar': Fills the zero entries with standard normal random variates.
        Default: None

    eps:
        Truncate all values less then this in output to zero.

    random_state: numpy.RandomState | int, optional
        The generator used to fill in the zeros, when using variant='ar'
        Default: numpy.random

    Returns
    -------

    (W, H):
        Initial guesses for solving X ~= WH such that
        the number of columns in W is n_components.

    Remarks
    -------

    This implements the algorithm described in
    C. Boutsidis, E. Gallopoulos: SVD based
    initialization: A head start for nonnegative
    matrix factorization - Pattern Recognition, 2008

    http://www.cs.rpi.edu/~boutsc/files/nndsvd.pdf
    """
    check_non_negative(X, "NMF initialization")
    if variant not in (None, 'a', 'ar'):
        raise ValueError("Invalid variant name")

    U, S, V = randomized_svd(X, n_components)
    W, H = np.zeros(U.shape), np.zeros(V.shape)

    # The leading singular triplet is non-negative
    # so it can be used as is for initialization.
    W[:, 0] = np.sqrt(S[0]) * np.abs(U[:, 0])
    H[0, :] = np.sqrt(S[0]) * np.abs(V[0, :])

    for j in xrange(1, n_components):
        x, y = U[:, j], V[j, :]

        # extract positive and negative parts of column vectors
        x_p, y_p = _pos(x), _pos(y)
        x_n, y_n = _neg(x), _neg(y)

        # and their norms
        x_p_nrm, y_p_nrm = norm(x_p), norm(y_p)
        x_n_nrm, y_n_nrm = norm(x_n), norm(y_n)

        m_p, m_n = x_p_nrm * y_p_nrm, x_n_nrm * y_n_nrm

        # choose update
        if m_p > m_n:
            u = x_p / x_p_nrm
            v = y_p / y_p_nrm
            sigma = m_p
        else:
            u = x_n / x_n_nrm
            v = y_n / y_n_nrm
            sigma = m_n

        lbd = np.sqrt(S[j] * sigma)
        W[:, j] = lbd * u
        H[j, :] = lbd * v

    W[W < eps] = 0
    H[H < eps] = 0

    if variant == "a":
        avg = X.mean()
        W[W == 0] = avg
        H[H == 0] = avg
    elif variant == "ar":
        random_state = check_random_state(random_state)
        avg = X.mean()
        W[W == 0] = abs(avg * random_state.randn(len(W[W == 0])) / 100)
        H[H == 0] = abs(avg * random_state.randn(len(H[H == 0])) / 100)

    return W, H

def _nls_subproblem(V, W, H_init, tol, max_iter):
    """Non-negative least square solver

    Solves a non-negative least squares subproblem using the
    projected gradient descent algorithm.
    min || WH - V ||_2

    Parameters
    ----------
    V, W:
        Constant matrices

    H_init:
        Initial guess for the solution

    tol:
        Tolerance of the stopping condition.

    max_iter:
        Maximum number of iterations before
        timing out.

    Returns
    -------
    H:
        Solution to the non-negative least squares problem

    grad:
        The gradient.

    n_iter:
        The number of iterations done by the algorithm.

    """
    if (H_init < 0).any():
        raise ValueError("Negative values in H_init passed to NLS solver.")

    H = H_init
    WtV = safe_sparse_dot(W.T, V, dense_output=True)
    WtW = safe_sparse_dot(W.T, W, dense_output=True)

    # values justified in the paper
    alpha = 1
    beta = 0.1
    for n_iter in xrange(1, max_iter + 1):
        grad = np.dot(WtW, H) - WtV
        proj_gradient = norm(grad[np.logical_or(grad < 0, H > 0)])
        if proj_gradient < tol:
            break

        for inner_iter in xrange(1, 20):
            Hn = H - alpha * grad
            # Hn = np.where(Hn > 0, Hn, 0)
            Hn = _pos(Hn)
            d = Hn - H
            gradd = np.sum(grad * d)
            dQd = np.sum(np.dot(WtW, d) * d)
            # magic numbers whoa
            suff_decr = 0.99 * gradd + 0.5 * dQd < 0
            if inner_iter == 1:
                decr_alpha = not suff_decr
                Hp = H

            if decr_alpha:
                if suff_decr:
                    H = Hn
                    break
                else:
                    alpha *= beta
            elif not suff_decr or (Hp == Hn).all():
                H = Hp
                break
            else:
                alpha /= beta
                Hp = Hn

    if n_iter == max_iter:
        warnings.warn("Iteration limit reached in nls subproblem.")

    return H, grad, n_iter

class ProjectedGradientNMF(BaseEstimator, TransformerMixin):
    """Non-Negative matrix factorization by Projected Gradient (NMF)

    Parameters
    ----------
    X: {array-like, sparse matrix}, shape = [n_samples, n_features]
        Data the model will be fit to.

    n_components: int or None
        Number of components, if n_components is not set all components
        are kept

    init:  'nndsvd' |  'nndsvda' | 'nndsvdar' | int | RandomState
        Method used to initialize the procedure.
        Default: 'nndsvdar'
        Valid options::

            'nndsvd': Nonnegative Double Singular Value Decomposition (NNDSVD)
                initialization (better for sparseness)
            'nndsvda': NNDSVD with zeros filled with the average of X
                (better when sparsity is not desired)
            'nndsvdar': NNDSVD with zeros filled with small random values
                (generally faster, less accurate alternative to NNDSVDa
                for when sparsity is not desired)
            int seed or RandomState: non-negative random matrices

    sparseness: 'data' | 'components' | None, default: None
        Where to enforce sparsity in the model.

    beta: double, default: 1
        Degree of sparseness, if sparseness is not None. Larger values mean
        more sparseness.

    eta: double, default: 0.1
        Degree of correctness to mantain, if sparsity is not None. Smaller
        values mean larger error.

    tol: double, default: 1e-4
        Tolerance value used in stopping conditions.

    max_iter: int, default: 200
        Number of iterations to compute.

    nls_max_iter: int, default: 2000
        Number of iterations in NLS subproblem.

    Attributes
    ----------
    `components_` : array, [n_components, n_features]
        Non-negative components of the data

    `reconstruction_err_` : number
        Frobenius norm of the matrix difference between the
        training data and the reconstructed data from the
        fit produced by the model. ``|| X - WH ||_2``
        Not computed for sparse input matrices because it is
        too expensive in terms of memory.

    Examples
    --------

    >>> import numpy as np
    >>> X = np.array([[1,1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])
    >>> from sklearn.decomposition import ProjectedGradientNMF
    >>> model = ProjectedGradientNMF(n_components=2, init=0)
    >>> model.fit(X) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
    ProjectedGradientNMF(beta=1, eta=0.1, init=0, max_iter=200, n_components=2,
                         nls_max_iter=2000, sparseness=None, tol=0.0001)
    >>> model.components_
    array([[ 0.77032744,  0.11118662],
           [ 0.38526873,  0.38228063]])
    >>> model.reconstruction_err_ #doctest: +ELLIPSIS
    0.00746...
    >>> model = ProjectedGradientNMF(n_components=2, init=0,
    ...                              sparseness='components')
    >>> model.fit(X) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
    ProjectedGradientNMF(beta=1, eta=0.1, init=0, max_iter=200, n_components=2,
               nls_max_iter=2000, sparseness='components', tol=0.0001)
    >>> model.components_
    array([[ 1.67481991,  0.29614922],
           [-0.        ,  0.4681982 ]])
    >>> model.reconstruction_err_ #doctest: +ELLIPSIS
    0.513...

    Notes
    -----
    This implements

    C.-J. Lin. Projected gradient methods
    for non-negative matrix factorization. Neural
    Computation, 19(2007), 2756-2779.
    http://www.csie.ntu.edu.tw/~cjlin/nmf/

    P. Hoyer. Non-negative Matrix Factorization with
    Sparseness Constraints. Journal of Machine Learning
    Research 2004.

    NNDSVD is introduced in

    C. Boutsidis, E. Gallopoulos: SVD based
    initialization: A head start for nonnegative
    matrix factorization - Pattern Recognition, 2008
    http://www.cs.rpi.edu/~boutsc/files/nndsvd.pdf

    """

    def __init__(self, n_components=None, init="nndsvdar", sparseness=None,
                 beta=1, eta=0.1, tol=1e-4, max_iter=200, nls_max_iter=2000):
        self.n_components = n_components
        self.init = init
        self.tol = tol
        if sparseness not in (None, 'data', 'components'):
            raise ValueError(
                'Invalid sparseness parameter: got %r instead of one of %r' %
                (sparseness, (None, 'data', 'components')))
        self.sparseness = sparseness
        self.beta = beta
        self.eta = eta
        self.max_iter = max_iter
        self.nls_max_iter = nls_max_iter

    def _init(self, X):
        n_samples, n_features = X.shape

        if self.init == 'nndsvd':
            W, H = _initialize_nmf(X, self.n_components)
        elif self.init == 'nndsvda':
            W, H = _initialize_nmf(X, self.n_components, variant='a')
        elif self.init == 'nndsvdar':
            W, H = _initialize_nmf(X, self.n_components, variant='ar')
        else:
            try:
                rng = check_random_state(self.init)
                W = rng.randn(n_samples, self.n_components)
                # we do not write np.abs(W, out=W) to stay compatible with
                # numpy 1.5 and earlier where the 'out' keyword is not
                # supported as a kwarg on ufuncs
                np.abs(W, W)
                H = rng.randn(self.n_components, n_features)
                np.abs(H, H)
            except ValueError:
                raise ValueError(
                    'Invalid init parameter: got %r instead of one of %r' %
                    (self.init, (None, 'nndsvd', 'nndsvda', 'nndsvdar',
                                 int, np.random.RandomState)))

        return W, H

    def _update_W(self, X, H, W, tolW):
        n_samples, n_features = X.shape

        if self.sparseness == None:
            W, gradW, iterW = _nls_subproblem(X.T, H.T, W.T, tolW,
                                              self.nls_max_iter)
        elif self.sparseness == 'data':
            W, gradW, iterW = _nls_subproblem(
                    np.r_[X.T, np.zeros((1, n_samples))],
                    np.r_[H.T, np.sqrt(self.beta) *
                          np.ones((1, self.n_components))],
                    W.T, tolW, self.nls_max_iter)
        elif self.sparseness == 'components':
            W, gradW, iterW = _nls_subproblem(
                    np.r_[X.T, np.zeros((self.n_components, n_samples))],
                    np.r_[H.T, np.sqrt(self.eta) *
                          np.eye(self.n_components)],
                    W.T, tolW, self.nls_max_iter)

        return W, gradW, iterW

    def _update_H(self, X, H, W, tolH):
        n_samples, n_features = X.shape

        if self.sparseness == None:
            H, gradH, iterH = _nls_subproblem(X, W, H, tolH,
                                              self.nls_max_iter)
        elif self.sparseness == 'data':
            H, gradH, iterH = _nls_subproblem(
                    np.r_[X, np.zeros((self.n_components, n_features))],
                    np.r_[W, np.sqrt(self.eta) *
                          np.eye(self.n_components)],
                    H, tolH, self.nls_max_iter)
        elif self.sparseness == 'components':
            H, gradH, iterH = _nls_subproblem(
                    np.r_[X, np.zeros((1, n_features))],
                    np.r_[W, np.sqrt(self.beta) *
                          np.ones((1, self.n_components))],
                    H, tolH, self.nls_max_iter)

        return H, gradH, iterH

    def fit_transform(self, X, y=None):
        """Learn a NMF model for the data X and returns the transformed data.

        This is more efficient than calling fit followed by transform.

        Parameters
        ----------

        X: {array-like, sparse matrix}, shape = [n_samples, n_features]
            Data matrix to be decomposed

        Returns
        -------
        data: array, [n_samples, n_components]
            Transformed data
        """
        X = atleast2d_or_csr(X)
        check_non_negative(X, "NMF.fit")

        n_samples, n_features = X.shape

        if not self.n_components:
            self.n_components = n_features

        W, H = self._init(X)

        gradW = (np.dot(W, np.dot(H, H.T))
                 - safe_sparse_dot(X, H.T, dense_output=True))
        gradH = (np.dot(np.dot(W.T, W), H)
                 - safe_sparse_dot(W.T, X, dense_output=True))
        init_grad = norm(np.r_[gradW, gradH.T])
        tolW = max(0.001, self.tol) * init_grad  # why max?
        tolH = tolW

        for n_iter in xrange(1, self.max_iter + 1):
            # stopping condition
            # as discussed in paper
            proj_norm = norm(np.r_[gradW[np.logical_or(gradW < 0, W > 0)],
                                   gradH[np.logical_or(gradH < 0, H > 0)]])
            if proj_norm < self.tol * init_grad:
                break

            # update W
            W, gradW, iterW = self._update_W(X, H, W, tolW)

            W = W.T
            gradW = gradW.T
            if iterW == 1:
                tolW = 0.1 * tolW

            # update H
            H, gradH, iterH = self._update_H(X, H, W, tolH)

            if iterH == 1:
                tolH = 0.1 * tolH

            self.comp_sparseness_ = _sparseness(H.ravel())
            self.data_sparseness_ = _sparseness(W.ravel())

            if not sp.issparse(X):
                self.reconstruction_err_ = norm(X - np.dot(W, H))

            self.components_ = H

        if n_iter == self.max_iter:
            warnings.warn("Iteration limit reached during fit")

        return W

    def fit(self, X, y=None, **params):
        """Learn a NMF model for the data X.

        Parameters
        ----------

        X: {array-like, sparse matrix}, shape = [n_samples, n_features]
            Data matrix to be decomposed

        Returns
        -------
        self
        """
        self.fit_transform(X, **params)
        return self

    def transform(self, X):
        """Transform the data X according to the fitted NMF model

        Parameters
        ----------

        X: {array-like, sparse matrix}, shape = [n_samples, n_features]
            Data matrix to be transformed by the model

        Returns
        -------
        data: array, [n_samples, n_components]
            Transformed data
        """
        X = atleast2d_or_csr(X)
        H = np.zeros((X.shape[0], self.n_components))
        for j in xrange(0, X.shape[0]):
            H[j, :], _ = nnls(self.components_.T, X[j, :])
        return H

class NMF(ProjectedGradientNMF):
    __doc__ = ProjectedGradientNMF.__doc__
    pass


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.ggj</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>zuul</artifactId>
    <version>1.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--main方法类-->
        <start-class>com.ggj.ZuulApp</start-class>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

    </dependencies>

    <build>
        <finalName>zuul</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


text:
<?xml version="1.0"?>

<model xmlns="http://www.neeveresearch.com/schema/x-adml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" namespace="com.neeve.oms.messages">
    <import model="com/neeve/fix/entities/entities.xml"/>

    <factories>
        <factory name="MessageFactory" id="1"/>
    </factories>

    <messages>
        <message name="NewOrderMessage" id="1" factoryid="1">
            <inline ref="FIXNewOrderSingle"/>
        </message>

        <message name="OrderEvent" id="2" factoryid="1">
            <inline ref="FIXExecutionReport" />
        </message>
    </messages>
</model>


text:
<!-- <app-home *ngIf="!loggedIn; else elseBlock"></app-home>
<ng-template #elseBlock><app-dashboard></app-dashboard></ng-template> -->
<router-outlet></router-outlet>


text:
class Mech::Compiler::Format::Ruby < Mech::Compiler::Format
end


text:
/**
 * Test case for persistize.
 * Runs with mocha.
 */
'use strict'

const persistize = require('../lib/persistize.js')
const assert = require('assert')
const co = require('co')

describe('persistize', function () {
  this.timeout(3000)

  before(() => {

  })

  after(() => {

  })

  it('Persistize', () => {
    let handlers = persistize(['foo', 'bar'])
    assert.ok(handlers.foo)
    assert.ok(handlers.bar)
  })
})

/* global describe, before, after, it */


text:
require 'ostruct'
default_config_file = Rails.root.join("config", "config.example.yml")

# Allow a Rails Engine to override config by defining it earlier
unless defined?(Errbit::Config)
  Errbit::Config = OpenStruct.new
  use_env = ENV['HEROKU'] || ENV['USE_ENV']

  # If Errbit is running on Heroku, config can be set from environment variables.
  if use_env
    Errbit::Config.host = ENV['ERRBIT_HOST']
    Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM']
    #  Not really easy to use like an env because need an array and ENV return a string :(
    # Errbit::Config.email_at_notices = ENV['ERRBIT_EMAIL_AT_NOTICES']
    Errbit::Config.confirm_resolve_err = ENV['ERRBIT_CONFIRM_RESOLVE_ERR'].to_i == 0
    Errbit::Config.user_has_username = ENV['ERRBIT_USER_HAS_USERNAME'].to_i == 1
    Errbit::Config.allow_comments_with_issue_tracker = ENV['ERRBIT_ALLOW_COMMENTS_WITH_ISSUE_TRACKER'].to_i == 0
    Errbit::Config.enforce_ssl = ENV['ERRBIT_ENFORCE_SSL']

    Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR']
    Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT']

    Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION']
    Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID']
    Errbit::Config.github_secret = ENV['GITHUB_SECRET']
    Errbit::Config.github_access_scope = ENV['GITHUB_ACCESS_SCOPE'].split(',').map(&:strip) if ENV['GITHUB_ACCESS_SCOPE']

    Errbit::Config.smtp_settings = {
      :address        => ENV['SMTP_SERVER'] || 'smtp.sendgrid.net',
      :port           => ENV['SMTP_PORT']   || 25,
      :authentication => :plain,
      :user_name      => ENV['SMTP_USERNAME']   || ENV['SENDGRID_USERNAME'],
      :password       => ENV['SMTP_PASSWORD']   || ENV['SENDGRID_PASSWORD'],
      :domain         => ENV['SMTP_DOMAIN'] || ENV['SENDGRID_DOMAIN'] || ENV['ERRBIT_EMAIL_FROM'].split('@').last
    }
  end

  # Use example config for test environment.
  config_file = Rails.env == "test" ? default_config_file : Rails.root.join("config", "config.yml")

  # Load config if config file exists.
  if File.exists?(config_file)
    config = YAML.load_file(config_file)
    config.merge!(config.delete(Rails.env)) if config.has_key?(Rails.env)
    config.each do |k,v|
      Errbit::Config.send("#{k}=", v)
    end
  # Show message if we are not running tests, not running on Heroku, and config.yml doesn't exist.
  elsif not use_env
    puts "Please copy 'config/config.example.yml' to 'config/config.yml' and configure your settings. Using default settings."
  end

  # Set default devise modules
  Errbit::Config.devise_modules = [:database_authenticatable,
                                   :recoverable, :rememberable, :trackable,
                                   :validatable, :token_authenticatable, :omniauthable]
end

# Set default settings from config.example.yml if key is missing from config.yml
default_config = YAML.load_file(default_config_file)
default_config.each do |k,v|
  Errbit::Config.send("#{k}=", v) if Errbit::Config.send(k) === nil
end

# Disable GitHub oauth if gem is missing
Errbit::Config.github_authentication = false unless defined?(OmniAuth::Strategies::GitHub)

# Set SMTP settings if given.
if smtp = Errbit::Config.smtp_settings
  ActionMailer::Base.delivery_method = :smtp
  ActionMailer::Base.smtp_settings = smtp
end

# Set config specific values
(ActionMailer::Base.default_url_options ||= {}).tap do |default|
  default.merge! :host => Errbit::Config.host if default[:host].blank?
end

if Rails.env.production?
  Rails.application.config.consider_all_requests_local = Errbit::Config.display_internal_errors
end


text:
@interface OrgApacheLuceneUtilArrayInPlaceMergeSorter () {
 @public
  IOSObjectArray *arr_;
  id<JavaUtilComparator> comparator_;
}

@end

J2OBJC_FIELD_SETTER(OrgApacheLuceneUtilArrayInPlaceMergeSorter, arr_, IOSObjectArray *)
J2OBJC_FIELD_SETTER(OrgApacheLuceneUtilArrayInPlaceMergeSorter, comparator_, id<JavaUtilComparator>)

@implementation OrgApacheLuceneUtilArrayInPlaceMergeSorter

- (instancetype)initPackagePrivateWithNSObjectArray:(IOSObjectArray *)arr
                             withJavaUtilComparator:(id<JavaUtilComparator>)comparator {
  OrgApacheLuceneUtilArrayInPlaceMergeSorter_initPackagePrivateWithNSObjectArray_withJavaUtilComparator_(self, arr, comparator);
  return self;
}

- (jint)compareWithInt:(jint)i
               withInt:(jint)j {
  return [((id<JavaUtilComparator>) nil_chk(comparator_)) compareWithId:IOSObjectArray_Get(nil_chk(arr_), i) withId:IOSObjectArray_Get(arr_, j)];
}

- (void)swapWithInt:(jint)i
            withInt:(jint)j {
  OrgApacheLuceneUtilArrayUtil_swapWithNSObjectArray_withInt_withInt_(arr_, i, j);
}

- (void)dealloc {
  RELEASE_(arr_);
  RELEASE_(comparator_);
  [super dealloc];
}

+ (const J2ObjcClassInfo *)__metadata {
  static J2ObjcMethodInfo methods[] = {
    { NULL, NULL, 0x1, -1, 0, -1, 1, -1, -1 },
    { NULL, "I", 0x4, 2, 3, -1, -1, -1, -1 },
    { NULL, "V", 0x4, 4, 3, -1, -1, -1, -1 },
  };
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wobjc-multiple-method-names"
  #pragma clang diagnostic ignored "-Wundeclared-selector"
  methods[0].selector = @selector(initPackagePrivateWithNSObjectArray:withJavaUtilComparator:);
  methods[1].selector = @selector(compareWithInt:withInt:);
  methods[2].selector = @selector(swapWithInt:withInt:);
  #pragma clang diagnostic pop
  static const J2ObjcFieldInfo fields[] = {
    { "arr_", "[LNSObject;", .constantValue.asLong = 0, 0x12, -1, -1, 5, -1 },
    { "comparator_", "LJavaUtilComparator;", .constantValue.asLong = 0, 0x12, -1, -1, 6, -1 },
  };
  static const void *ptrTable[] = { "[LNSObject;LJavaUtilComparator;", "([TT;Ljava/util/Comparator<-TT;>;)V", "compare", "II", "swap", "[TT;", "Ljava/util/Comparator<-TT;>;", "<T:Ljava/lang/Object;>Lorg/apache/lucene/util/InPlaceMergeSorter;" };
  static const J2ObjcClassInfo _OrgApacheLuceneUtilArrayInPlaceMergeSorter = { "ArrayInPlaceMergeSorter", "org.apache.lucene.util", ptrTable, methods, fields, 7, 0x10, 3, 2, -1, -1, -1, 7, -1 };
  return &_OrgApacheLuceneUtilArrayInPlaceMergeSorter;
}

@end

void OrgApacheLuceneUtilArrayInPlaceMergeSorter_initPackagePrivateWithNSObjectArray_withJavaUtilComparator_(OrgApacheLuceneUtilArrayInPlaceMergeSorter *self, IOSObjectArray *arr, id<JavaUtilComparator> comparator) {
  OrgApacheLuceneUtilInPlaceMergeSorter_init(self);
  JreStrongAssign(&self->arr_, arr);
  JreStrongAssign(&self->comparator_, comparator);
}

OrgApacheLuceneUtilArrayInPlaceMergeSorter *new_OrgApacheLuceneUtilArrayInPlaceMergeSorter_initPackagePrivateWithNSObjectArray_withJavaUtilComparator_(IOSObjectArray *arr, id<JavaUtilComparator> comparator) {
  J2OBJC_NEW_IMPL(OrgApacheLuceneUtilArrayInPlaceMergeSorter, initPackagePrivateWithNSObjectArray_withJavaUtilComparator_, arr, comparator)
}

OrgApacheLuceneUtilArrayInPlaceMergeSorter *create_OrgApacheLuceneUtilArrayInPlaceMergeSorter_initPackagePrivateWithNSObjectArray_withJavaUtilComparator_(IOSObjectArray *arr, id<JavaUtilComparator> comparator) {
  J2OBJC_CREATE_IMPL(OrgApacheLuceneUtilArrayInPlaceMergeSorter, initPackagePrivateWithNSObjectArray_withJavaUtilComparator_, arr, comparator)
}

J2OBJC_CLASS_TYPE_LITERAL_SOURCE(OrgApacheLuceneUtilArrayInPlaceMergeSorter)


text:
define([
    'amber/devel',
    './deploy',
    // --- packages used only during development begin here ---
    'amber-context/ContextAmber-Tests',
    'amber-context/Athens-Amber',
    'amber-context/Athens-Core-Matrices',
    'amber-context/Athens-Core-Paints',
    'amber-context/Athens-Core-Paths',
    'amber-context/Athens-Core-PathsGeometry',
    'amber-context/Athens-Core',
    'amber-context/Athens-HTML-Matrices',
    'amber-context/Athens-HTML-Paints',
    'amber-context/Athens-HTML-Paths',
    'amber-context/Athens-HTML-Tutorial',
    'amber-context/Athens-HTML',
    'amber-context/Athens-Debug-Layers'
    // --- packages used only during development end here ---
], function (amber) {
    return amber;
});


text:
.sort-desc {
    background-image: url("../../resources/images/default/grid/sort_desc.gif") !important;
    background-position: 4px 7px !important;
}

.sort-asc {
    background-image: url("../../resources/images/default/grid/sort_asc.gif") !important;
    background-position: 4px 7px !important;
}


text:
// WARNING
//
// This file has been generated automatically by Xamarin Studio from the outlets and
// actions declared in your storyboard file.
// Manual changes to this file will not be maintained.
//
using Foundation;
using System;
using System.CodeDom.Compiler;
using UIKit;

namespace HiPMobile.iOS
{
    [Register ("ExhibitTableViewCell")]
    partial class ExhibitTableViewCell
    {
        void ReleaseDesignerOutlets ()
        {
        }
    }
}


text:
typedef void(*sys_fn)(unsigned int, unsigned int, context*);

extern sys_fn syscalls[256];

void init_syscall();
void syscall(unsigned int status, unsigned int cause, context* pt_context);
void register_syscall(int index, sys_fn fn);

// Syscall code allocation
#define SYSCALL_MALLOC 1
#define SYSCALL_FREE   2
#define SYSCALL_EXIT   3
#define SYSCALL_GPIO   4
#define SYSCALL_KILL   5
#define SYSCALL_PRINTTASKS 6
#define SYSCALL_SCHEDULE 7
#define SYSCALL_FORK 8
#define SYSCALL_SLEEP 9
#define SYSCALL_WAIT 10

#endif


text:
class Marca < ClassyEnum::Base
end

class Marca::Caterpillar < Marca
end

class Marca::JohnDeere < Marca
end

class Marca::Dynapac < Marca
end

class Marca::TemaTerra < Marca
end

class Marca::Bombardier < Marca
end

class Marca::DeutzFahr < Marca
end

class Marca::NewHolland < Marca
end

class Marca::Volkswagen < Marca
end

class Marca::Puckett < Marca
end


text:
//
//  Answers.h
//  Crashlytics
//
//  Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ANSCompatibility.h"

NS_ASSUME_NONNULL_BEGIN

/**
 *  This class exposes the Answers Events API, allowing you to track key
 *  user user actions and metrics in your app.
 */
@interface Answers : NSObject

/**
 *  Log a Sign Up event to see users signing up for your app in real-time, understand how
 *  many users are signing up with different methods and their success rate signing up.
 *
 *  @param signUpMethodOrNil     The method by which a user logged in, e.g. Twitter or Digits.
 *  @param signUpSucceededOrNil  The ultimate success or failure of the login
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil
                    success:(nullable NSNumber *)signUpSucceededOrNil
           customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log an Log In event to see users logging into your app in real-time, understand how many
 *  users are logging in with different methods and their success rate logging into your app.
 *
 *  @param loginMethodOrNil      The method by which a user logged in, e.g. email, Twitter or Digits.
 *  @param loginSucceededOrNil   The ultimate success or failure of the login
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil
                   success:(nullable NSNumber *)loginSucceededOrNil
          customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Share event to see users sharing from your app in real-time, letting you
 *  understand what content they're sharing from the type or genre down to the specific id.
 *
 *  @param shareMethodOrNil      The method by which a user shared, e.g. email, Twitter, SMS.
 *  @param contentNameOrNil      The human readable name for this piece of content.
 *  @param contentTypeOrNil      The type of content shared.
 *  @param contentIdOrNil        The unique identifier for this piece of content. Useful for finding the top shared item.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
 */
+ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil
               contentName:(nullable NSString *)contentNameOrNil
               contentType:(nullable NSString *)contentTypeOrNil
                 contentId:(nullable NSString *)contentIdOrNil
          customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log an Invite Event to track how users are inviting other users into
 *  your application.
 *
 *  @param inviteMethodOrNil     The method of invitation, e.g. GameCenter, Twitter, email.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil
           customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which
 *  items are most popular, and track plenty of other important purchase-related metrics.
 *
 *  @param itemPriceOrNil         The purchased item's price.
 *  @param currencyOrNil          The ISO4217 currency code. Example: USD
 *  @param purchaseSucceededOrNil Was the purchase succesful or unsuccesful
 *  @param itemNameOrNil          The human-readable form of the item's name. Example:
 *  @param itemIdOrNil            The machine-readable, unique item identifier Example: SKU
 *  @param itemTypeOrNil          The type, or genre of the item. Example: Song
 *  @param customAttributesOrNil  A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
                    currency:(nullable NSString *)currencyOrNil
                     success:(nullable NSNumber *)purchaseSucceededOrNil
                    itemName:(nullable NSString *)itemNameOrNil
                    itemType:(nullable NSString *)itemTypeOrNil
                      itemId:(nullable NSString *)itemIdOrNil
            customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Level Start Event to track where users are in your game.
 *
 *  @param levelNameOrNil        The level name
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event.
 */
+ (void)logLevelStart:(nullable NSString *)levelNameOrNil
     customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Level End event to track how users are completing levels in your game.
 *
 *  @param levelNameOrNil                 The name of the level completed, E.G. "1" or "Training"
 *  @param scoreOrNil                     The score the user completed the level with.
 *  @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed succesfully.
 *  @param customAttributesOrNil          A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logLevelEnd:(nullable NSString *)levelNameOrNil
              score:(nullable NSNumber *)scoreOrNil
            success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil
   customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how
 *  many users start the purchase flow, see which items are most popular, and track plenty of other important
 *  purchase-related metrics.
 *
 *  @param itemPriceOrNil         The purchased item's price.
 *  @param currencyOrNil          The ISO4217 currency code. Example: USD
 *  @param itemNameOrNil          The human-readable form of the item's name. Example:
 *  @param itemTypeOrNil          The type, or genre of the item. Example: Song
 *  @param itemIdOrNil            The machine-readable, unique item identifier Example: SKU
 *  @param customAttributesOrNil  A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
                     currency:(nullable NSString *)currencyOrNil
                     itemName:(nullable NSString *)itemNameOrNil
                     itemType:(nullable NSString *)itemTypeOrNil
                       itemId:(nullable NSString *)itemIdOrNil
             customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many
 *  users are doing this and how much they're spending per checkout, and see how it related to other important
 *  purchase-related metrics.
 *
 *  @param totalPriceOrNil        The total price of the cart.
 *  @param currencyOrNil          The ISO4217 currency code. Example: USD
 *  @param itemCountOrNil         The number of items in the cart.
 *  @param customAttributesOrNil  A dictionary of custom attributes to associate with this purchase.
 */
+ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil
                         currency:(nullable NSString *)currencyOrNil
                        itemCount:(nullable NSNumber *)itemCountOrNil
                 customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Rating event to see users rating content within your app in real-time and understand what
 *  content is most engaging, from the type or genre down to the specific id.
 *
 *  @param ratingOrNil           The integer rating given by the user.
 *  @param contentNameOrNil      The human readable name for this piece of content.
 *  @param contentTypeOrNil      The type of content shared.
 *  @param contentIdOrNil        The unique identifier for this piece of content. Useful for finding the top shared item.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
 */
+ (void)logRating:(nullable NSNumber *)ratingOrNil
      contentName:(nullable NSString *)contentNameOrNil
      contentType:(nullable NSString *)contentTypeOrNil
        contentId:(nullable NSString *)contentIdOrNil
 customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Content View event to see users viewing content within your app in real-time and
 *  understand what content is most engaging, from the type or genre down to the specific id.
 *
 *  @param contentNameOrNil      The human readable name for this piece of content.
 *  @param contentTypeOrNil      The type of content shared.
 *  @param contentIdOrNil        The unique identifier for this piece of content. Useful for finding the top shared item.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
 */
+ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil
                   contentType:(nullable NSString *)contentTypeOrNil
                     contentId:(nullable NSString *)contentIdOrNil
              customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Search event allows you to see users searching within your app in real-time and understand
 *  exactly what they're searching for.
 *
 *  @param queryOrNil            The user's query.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
 */
+ (void)logSearchWithQuery:(nullable NSString *)queryOrNil
          customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

/**
 *  Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often
 *  they're performing these actions with breakdowns by different categories you add. Use a human-readable name for
 *  the name of the event, since this is how the event will appear in Answers.
 *
 *  @param eventName             The human-readable name for the event.
 *  @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase. Attribute keys
 *                               must be NSString and and values must be NSNumber or NSString.
 *  @discussion                  How we treat NSNumbers:
 *                               We will provide information about the distribution of values over time.
 *
 *                               How we treat NSStrings:
 *                               NSStrings are used as categorical data, allowing comparison across different category values.
 *                               Strings are limited to a maximum length of 100 characters, attributes over this length will be
 *                               truncated.
 *
 *                               When tracking the Tweet views to better understand user engagement, sending the tweet's length
 *                               and the type of media present in the tweet allows you to track how tweet length and the type of media influence
 *                               engagement.
 */
+ (void)logCustomEventWithName:(NSString *)eventName
              customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

@end

NS_ASSUME_NONNULL_END