def get_total_energy_chart_data_web(sic_code, report_year, benchmark_year, account_type, comparison_type, demand_type,
                                    y_units, y_unit_map, g):
    """
    Gets the data for the energy consumption chart
    :param sic_code: sic code being reported on
    :param report_year: report year from configuration
    :param benchmark_year: benchmark year from configuration
    :param account_type: 'electric'/'gas'/'all'
    :param comparison_type: 'temp'/'dewpt'/'enthalpy'
    :param demand_type: 'all'/'peak'/'offpeak'
    :param y_units: y units used for reporting 'btu, mcf, etc'
    :param y_unit_map: mapping column for database (often 'sum_btu')
    :param g: g
    :return: object containing all necessary information
    """

    # determine if demand will be included in query
    consider_demand_type = False
    if demand_type != 'all':
        consider_demand_type = True

    same_year = report_year == benchmark_year

    # get unit factor for the selected y units
    unit_factor = SharedReporting.get_factor(y_units, y_unit_map)
    data = TotalEnergyData()

    # get group descendants of sic code
    descendants = g.uow.sic.get_group_descendants(sic_code)
    accounts = []

    # get all accounts for each group for the desired year
    for gr in descendants:
        accounts += SharedReporting.get_accounts_for_group(gr, account_type, report_year, comparison_type, demand_type, g)
        if not same_year:
            accounts += SharedReporting.get_accounts_for_group(gr, account_type, benchmark_year, comparison_type, demand_type, g)

    if len(accounts) < 1:
        benchmark_data = []
    else:
        benchmark_data = g.uow.compiled_energy_records.get_compiled_energy_records_for_report(accounts, data_field_name=y_unit_map, consider_demand_type=consider_demand_type)

    # group the data by value
    grouped = defaultdict(list)

    for d in benchmark_data:
        grouped[d['group']['value']].append(d)

    reported_consumption = []
    diff = []
    benchmark_diff = []
    benchmark_consumption = []

    # get the distinct values for the group
    grouped_keys = list(grouped.keys())
    grouped_keys.sort()

    # if the report year and benchmark year are the same, it will be handled differently
    if same_year:
        for value in grouped_keys:
            entry = grouped[value]
            record_value = entry[0]['reduction'][y_unit_map] * unit_factor / entry[0]['reduction']['sum_hours_in_record']
            reported_consumption.append([value, round(record_value, 5)])
            diff.append([value, 0])
            benchmark_consumption.append([value, round(record_value, 5)])
            benchmark_diff.append([value, 0])
    else:
        # loop through every distinct value and get all of the records for it
        for value in grouped_keys:
            entry = grouped[value]
            if len(entry) > 1:
                report_record = 0
                benchmark_record = 0
                report_avg_size = 0
                benchmark_avg_size = 0
                benchmark_record_hours = 0
                for record in entry:
                    if record['group']['year'] == report_year:
                        report_record_hours = record['reduction']['sum_hours_in_record']

                        # normalize the values
                        report_record = round(record['reduction'][y_unit_map] * unit_factor / report_record_hours, 5)
                        reported_consumption.append([value, report_record])

                        report_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / report_record_hours
                    elif record['group']['year'] == benchmark_year:
                        benchmark_record_hours = record['reduction']['sum_hours_in_record']

                        # get the size and record value to be normalized later
                        benchmark_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / benchmark_record_hours
                        benchmark_record = record['reduction'][y_unit_map] * unit_factor

                # normalize the benchmark value
                size_ratio = report_avg_size * 1.0 / benchmark_avg_size
                benchmark_record *= size_ratio
                benchmark_record /= benchmark_record_hours

                # add normalized value to charts
                benchmark_consumption.append([value, round(benchmark_record, 5)])
                benchmark_diff.append([value, 0])
                diff.append([value, benchmark_record - report_record])

        data.reported_consumption = reported_consumption
        data.benchmark_consumption = benchmark_consumption
        data.diff = diff
        data.benchmark_diff = benchmark_diff
        return data
    def get_total_energy_data(cls, account, year, benchmark_year, demand_type, y_units, y_unit_map, grouped):
        if demand_type != 'all':
            report_index = "has_peak"
        else:
            report_index = "no_peak"

        same_year = int(year) == int(benchmark_year)
        unit_factor = get_factor(y_units, y_unit_map)
        mmbtu_unit_factor = get_factor('mmbtus', y_unit_map)
        data = TotalEnergyData()

        # change the mapping function to ensure that sum_btu will always be returned from the query
        if y_unit_map.lower() == "sum_btu":
            mapping = lambda record: {'sum_btu': record['sum_btu'], 'sum_hours_in_record': record['sum_hours_in_record'],
                                      'sum_price_normalization': record['sum_price_normalization']}
            reduction = lambda a, b: {'sum_btu': a['sum_btu'] + b['sum_btu'],
                                     "sum_hours_in_record": a["sum_hours_in_record"] + b["sum_hours_in_record"],
                                     'sum_price_normalization': a['sum_price_normalization'] + b['sum_price_normalization']}
        else:
            mapping = lambda record: {'sum_btu': record['sum_btu'], y_unit_map: record[y_unit_map],
                                      'sum_hours_in_record': record['sum_hours_in_record'],
                                      'sum_price_normalization': record['sum_price_normalization']}
            reduction = lambda a, b: {'sum_btu': a['sum_btu'] + b['sum_btu'],
                                     y_unit_map: a[y_unit_map] + b[y_unit_map],
                                     "sum_hours_in_record": a["sum_hours_in_record"] + b["sum_hours_in_record"],
                                     'sum_price_normalization': a['sum_price_normalization'] + b['sum_price_normalization']}

        report_data = Db.r.db("pathian").table("compiled_energy_records").get_all(account, index=report_index).group(
            lambda record: {"year": record['year'], "value": record["comparison_value"]}).map(mapping).reduce(reduction).ungroup().run()

        for d in report_data:
            grouped[d['group']['value']].append(d)

        reported_consumption = []
        diff = []
        benchmark_diff = []
        benchmark_consumption = []

        grouped_keys = list(grouped.keys())
        grouped_keys.sort()

        reported_total = 0
        reported_hours = 0
        benchmark_total = 0
        benchmark_hours = 0
        utility_total = 0

        sum_price_norm = 0
        sum_hours = 0

        if same_year:
            for value in grouped_keys:
                entry = grouped[value]
                reported_consumption.append(
                    [value, entry[0]['reduction'][y_unit_map] * unit_factor / entry[0]['reduction']['sum_hours_in_record']]
                )
                sum_price_norm += entry[0]['reduction']['sum_price_normalization'] * entry[0]['reduction']['sum_hours_in_record']
                sum_hours += entry[0]['reduction']['sum_hours_in_record']

                diff.append([value, 0])
                benchmark_consumption.append(
                    [value, entry[0]['reduction'][y_unit_map] * unit_factor / entry[0]['reduction']['sum_hours_in_record']])
                benchmark_diff.append([value, 0])

                # get totals specifying to convert to mmbtus
                reported_total += entry[0]['reduction']['sum_btu'] * mmbtu_unit_factor / entry[0]['reduction']['sum_hours_in_record']
                benchmark_total += entry[0]['reduction']['sum_btu'] * mmbtu_unit_factor / entry[0]['reduction']['sum_hours_in_record']
                utility_total += entry[0]['reduction']['sum_btu'] * mmbtu_unit_factor / entry[0]['reduction']['sum_hours_in_record']
        else:
            for value in grouped_keys:
                entry = grouped[value]

                # search the entry for the report year and add data to the utility total
                for rec in entry:
                    if rec['group']['year'] == int(year):
                        utility_total += rec['reduction']['sum_btu'] * mmbtu_unit_factor / rec['reduction']['sum_hours_in_record']

                # if the data exists for both years
                if len(entry) > 1:
                    report_record = 0
                    benchmark_record = 0
                    for record in entry:
                        if record['group']['year'] == int(year):
                            report_record = record['reduction'][y_unit_map] * unit_factor / record['reduction'][
                                'sum_hours_in_record']
                            reported_consumption.append([value, report_record])

                            # update totals
                            reported_total += record['reduction']['sum_btu'] * mmbtu_unit_factor / record['reduction'][
                                'sum_hours_in_record']
                            reported_hours += record['reduction']['sum_hours_in_record']

                            sum_price_norm += record['reduction']['sum_price_normalization']
                            sum_hours += record['reduction']['sum_hours_in_record']

                        elif record['group']['year'] == int(benchmark_year):
                            benchmark_record = record['reduction'][y_unit_map] * unit_factor / record['reduction'][
                                'sum_hours_in_record']
                            benchmark_consumption.append([value, benchmark_record])
                            benchmark_diff.append([value, 0])

                            # update totals
                            benchmark_total += record['reduction']['sum_btu'] * mmbtu_unit_factor / record['reduction'][
                                'sum_hours_in_record']
                            benchmark_hours += record['reduction']['sum_hours_in_record']

                    diff.append([value, benchmark_record - report_record])

        if benchmark_hours == 0:
            benchmark_total = 0
        else:
            benchmark_total = benchmark_total * (reported_hours * 1.0 / benchmark_hours)

        difference = benchmark_total - reported_total
        data.difference = difference

        if sum_hours == 0:
            data.cost_reduction = 0
        else:
            data.cost_reduction = (sum_price_norm * 1.0 / sum_hours) * difference

        if difference != 0:
            data.calculated_at = data.cost_reduction * 1.0 / data.difference
        else:
            data.calculated_at = 0.0
        data.reported_consumption = reported_consumption
        data.benchmark_consumption = benchmark_consumption
        data.diff = diff
        data.benchmark_diff = benchmark_diff
        return {'data': data, 'difference': difference, 'utility_total': utility_total, 'reported_total': reported_total,
                'reported_hours': reported_hours, 'benchmark_total': benchmark_total, 'benchmark_hours': benchmark_hours}
def calculate_pf_data(account_group, report_year, benchmark_year, same_year):
    """
    Calculates the powerfactor data for the account
    :param account_group: data for the account grouped by value
    :param report_year: current year for the report data
    :param benchmark_year: benchmark year to compare it to
    :param same_year: boolean value stating whether report_year == benchmark_year
    :return: TotalEnergyData
    """
    # initialize all variables for this account/year combination
    reported_consumption = []
    diff = []
    benchmark_diff = []
    benchmark_consumption = []

    grouped_keys = list(account_group.keys())
    grouped_keys.sort()

    kwh_unit_factor = SharedReporting.get_factor('kwh', 'sum_btu')

    # if the benchmark year and current year are the same they will be handled differently
    if same_year:
        for value in grouped_keys:
            entry = account_group[value][0]

            # calculate powerfactor
            record_kwh = entry["reduction"]["sum_btu"] * kwh_unit_factor
            record_kvar = math.sqrt(math.pow(record_kwh, 2) + math.pow(entry['reduction']['sum_kvar'], 2))
            record_pf = record_kwh * 1.0 / record_kvar

            # update lists of data
            reported_consumption.append([value, round(record_pf, 5)])
            diff.append([value, 0])
            benchmark_consumption.append([value, round(record_pf, 5)])
            benchmark_diff.append([value, 0])
    else:
        # loop through each entry in the keys
        for value in grouped_keys:
            entry = account_group[value]

            # if the data exists for both years
            if len(entry) > 1:
                record_pf = 0
                reported_avg_size = 0
                benchmark_avg_size = 0
                benchmark_record_btu_normalized = 0
                benchmark_record_kvar_normalized = 0
                for record in entry:
                    if record['group']['year'] == report_year:
                        # calculate powerfactor
                        record_kwh = record['reduction']['sum_btu'] * kwh_unit_factor
                        record_kvar = math.sqrt(math.pow(record_kwh, 2) + math.pow(record['reduction']['sum_kvar'], 2))
                        record_pf = record_kwh * 1.0 / record_kvar

                        report_record_hours = record['reduction']['sum_hours_in_record']
                        reported_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / report_record_hours

                        # update list
                        reported_consumption.append([value, round(record_pf, 5)])
                    elif record['group']['year'] == benchmark_year:
                        benchmark_avg_size = record['reduction']['sum_size_normalization'] * 1.0 / record['reduction']['sum_hours_in_record']
                        benchmark_record_btu_normalized = record['reduction']['sum_btu']
                        benchmark_record_kvar_normalized = record['reduction']['sum_kvar']

                # normalize the btu and kvar to properly calculate pf
                size_ratio = reported_avg_size * 1.0 / benchmark_avg_size
                benchmark_record_btu_normalized *= size_ratio
                benchmark_record_kvar_normalized *= size_ratio
                benchmark_kwh = benchmark_record_btu_normalized * kwh_unit_factor
                benchmark_kvar = math.sqrt(math.pow(benchmark_kwh, 2) + math.pow(benchmark_record_kvar_normalized, 2))
                benchmark_pf = benchmark_kwh * 1.0 / benchmark_kvar

                # update lists
                benchmark_consumption.append([value, round(benchmark_pf, 5)])
                benchmark_diff.append([value, 0])
                diff.append([value, round(benchmark_pf - record_pf, 5)])

    # create a new data object to be returned
    data = TotalEnergyData()

    data.reported_consumption = reported_consumption
    data.benchmark_consumption = benchmark_consumption
    data.diff = diff
    data.benchmark_diff = benchmark_diff

    return data