private Dollars Charge(int usage)
        {
            Dollars result;
            if (usage == 0) return new Dollars(0);
            double t1 = START_RATE - ((END_RATE*END_AMOUNT) - START_RATE)/(END_AMOUNT - 1);
            double t2 = ((END_RATE*END_AMOUNT) - START_RATE)*Math.Min(END_AMOUNT, usage)/
                (END_AMOUNT - 1);
            double t3 = Math.Max(usage - END_AMOUNT, 0)*END_RATE;

            result = new Dollars(t1 + t2 + t3);

            result = result.Plus(new Dollars(usage*0.0175));

            Dollars base1 = new Dollars(result.Min(new Dollars(50)).Times(0.07));
                if (result.IsGreaterThan(new Dollars(50)))
                {
                    base1 = new Dollars(base1.Plus(result.Min(new Dollars(75)).Minus(
                        new Dollars(50)).Times(0.06)
                        ));
                }
                if (result.IsGreaterThan(new Dollars(75)))
                {
                    base1 = new Dollars(base1.Plus(result.Minus(new Dollars(75)).Times(0.05)));
                }
            result = result.Plus(base1);
            return result;
        }
        private Dollars Charge(int usage)
        {
            double base1 = Math.Min(usage, 100)*0.03;
            if (usage > 100)
            {
                base1 += (Math.Min(usage, 200) - 100)*0.05;
            }
            if (usage > 200)
            {
                base1 += (usage - 200)*0.07;
            }

            Dollars result = new Dollars(base1);
            Dollars tax = new Dollars(result.Minus(new Dollars(8)).Max(new Dollars(0)).Times(TAX_RATE));
            result = result.Plus(tax);

            Dollars fuelCharge = new Dollars(usage*0.0175);
            result = result.Plus(fuelCharge);
            return result.Plus(new Dollars(fuelCharge.Times(TAX_RATE)));
        }
        private Dollars Charge(int usage, DateTime start, DateTime end)
        {
            Dollars result;
            double summerFraction;

            // Find out how much of period is in the summer
            if (start.After(zone.SummerEnd()) || end.Before(zone.SummerStart()))
                summerFraction = 0;
            else if (!start.Before(zone.SummerStart()) && !start.After(zone.SummerEnd()) && !end.Before(zone.SummerStart()) && !end.After(zone.SummerEnd()))
            {
                summerFraction = 1;
            }
            else
            {
                // part in summer part in winter
                double summerDays;
                if (start.Before(zone.SummerStart()) || start.After(zone.SummerEnd()))
                {
                    // end is in the summer
                    summerDays = DayOfYear(end) - DayOfYear(zone.SummerStart()) + 1;
                }
                else
                {
                    // start is in summer
                    summerDays = DayOfYear(zone.SummerEnd()) - DayOfYear(start) + 1;
                }
                summerFraction = summerDays/(DayOfYear(end) - DayOfYear(start) + 1);
            }

            result = new Dollars((usage*zone.SummerRate()*summerFraction) + (usage*zone.WinterRate()*(1 - summerFraction)));
            result = result.Plus(new Dollars(result.Times(TAX_RATE)));

            Dollars fuel = new Dollars(usage*0.0175);
            result = result.Plus(fuel);

            result = new Dollars(result.Plus(fuel.Times(TAX_RATE)));

            return result;
        }
        private Dollars Charge(int fullUsage, DateTime start, DateTime end)
        {
            Dollars result;
            double summerFraction;
            int usage = Math.Min(fullUsage, CAP);
            if (start.After(zone.SummerEnd()) || end.Before(zone.SummerStart()))
                summerFraction = 0;
            else if (!start.Before(zone.SummerStart()) && !start.After(zone.SummerEnd()) &&
                !end.Before(zone.SummerStart()) && !end.After(zone.SummerEnd()))
                summerFraction = 1;
            else
            {
                double summerDays;
                if (start.Before(zone.SummerStart()) || start.After(zone.SummerEnd()))
                {
                    // end is in the summer
                    summerDays = DayOfYear(end) - DayOfYear(zone.SummerStart()) + 1;
                }
                else
                {
                    // start is in summer
                    summerDays = DayOfYear(zone.SummerEnd()) - DayOfYear(start) + 1;
                }
                ;
                summerFraction = summerDays/(DayOfYear(end) - DayOfYear(start) + 1);
            }

            result = new Dollars((usage*zone.SummerRate()*summerFraction) +
                (usage*zone.WinterRate()*(1 - summerFraction)));

            result = result.Plus(new Dollars(Math.Max(fullUsage - usage, 0)*0.062));
            result = result.Plus(new Dollars(result.Times(TAX_RATE)));

            Dollars fuel = new Dollars(fullUsage*0.0175);
            result = result.Plus(fuel);
            result = new Dollars(result.Plus(fuel.Times(TAX_RATE).Min(FUEL_TAX_CAP)));

            return result;
        }