All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.powertac.householdcustomer.customers.Village Maven / Gradle / Ivy

There is a newer version: 1.9.0
Show newest version
/*
 * Copyright 2009-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an
 * "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.powertac.householdcustomer.customers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.joda.time.Instant;
import org.powertac.common.CapacityProfile;
import org.powertac.common.CustomerInfo;
import org.powertac.common.RandomSeed;
import org.powertac.common.Tariff;
import org.powertac.common.TariffEvaluationHelper;
import org.powertac.common.TariffEvaluator;
import org.powertac.common.TariffSubscription;
import org.powertac.common.Timeslot;
import org.powertac.common.WeatherReport;
import org.powertac.common.enumerations.PowerType;
import org.powertac.common.interfaces.CustomerModelAccessor;
import org.powertac.common.interfaces.TariffMarket;
import org.powertac.customer.AbstractCustomer;
import org.powertac.householdcustomer.configurations.VillageConstants;

/**
 * The village domain class is a set of households that comprise a small village
 * that consumes aggregated energy by the appliances installed in each
 * household.
 * 
 * @author Antonios Chrysopoulos
 * @version 1.5, Date: 2.25.12
 */
public class Village extends AbstractCustomer
{

  /**
   * logger for trace logging -- use log.info(), log.warn(), and log.error()
   * appropriately. Use log.debug() for output you want to see in testing or
   * debugging.
   */
  static protected Logger log = LogManager.getLogger(Village.class.getName());

  int seedId = 1;

  /**
   * These are the vectors containing aggregated each day's base load from the
   * appliances installed inside the households of each type.
   **/
  Vector> aggDailyBaseLoadNS = new Vector>();
  Vector> aggDailyBaseLoadRaS = new Vector>();
  Vector> aggDailyBaseLoadReS = new Vector>();
  Vector> aggDailyBaseLoadSS = new Vector>();

  /**
   * These are the vectors containing aggregated each day's controllable load
   * from the appliances installed inside the households.
   **/
  Vector> aggDailyControllableLoadNS = new Vector>();
  Vector> aggDailyControllableLoadRaS = new Vector>();
  Vector> aggDailyControllableLoadReS = new Vector>();
  Vector> aggDailyControllableLoadSS = new Vector>();

  /**
   * These are the vectors containing aggregated each day's weather sensitive
   * load from the appliances installed inside the households.
   **/
  Vector> aggDailyWeatherSensitiveLoadNS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadRaS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadReS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadSS =
    new Vector>();

  /**
   * These are the vectors containing aggregated each day's dominant load from
   * the appliances installed inside the households of each type.
   **/
  Vector> aggDailyDominantLoadNS = new Vector>();
  Vector> aggDailyDominantLoadRaS = new Vector>();
  Vector> aggDailyDominantLoadReS = new Vector>();
  Vector> aggDailyDominantLoadSS = new Vector>();

  /**
   * These are the vectors containing aggregated each day's non dominant load
   * from the appliances installed inside the households of each type.
   **/
  Vector> aggDailyNonDominantLoadNS = new Vector>();
  Vector> aggDailyNonDominantLoadRaS = new Vector>();
  Vector> aggDailyNonDominantLoadReS = new Vector>();
  Vector> aggDailyNonDominantLoadSS = new Vector>();

  /**
   * These are the aggregated vectors containing each day's base load of all the
   * households in hours.
   **/
  Vector> aggDailyBaseLoadInHoursNS = new Vector>();
  Vector> aggDailyBaseLoadInHoursRaS = new Vector>();
  Vector> aggDailyBaseLoadInHoursReS = new Vector>();
  Vector> aggDailyBaseLoadInHoursSS = new Vector>();

  /**
   * These are the aggregated vectors containing each day's controllable load of
   * all the households in hours.
   **/
  Vector> aggDailyControllableLoadInHoursNS =
    new Vector>();
  Vector> aggDailyControllableLoadInHoursRaS =
    new Vector>();
  Vector> aggDailyControllableLoadInHoursReS =
    new Vector>();
  Vector> aggDailyControllableLoadInHoursSS =
    new Vector>();

  /**
   * These are the aggregated vectors containing each day's weather sensitive
   * load of all the households in hours.
   **/
  Vector> aggDailyWeatherSensitiveLoadInHoursNS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadInHoursRaS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadInHoursReS =
    new Vector>();
  Vector> aggDailyWeatherSensitiveLoadInHoursSS =
    new Vector>();

  /**
   * These are the vectors containing aggregated each day's dominant load from
   * the appliances installed inside the households of each type.
   **/
  Vector> aggDailyDominantLoadInHoursNS =
    new Vector>();
  Vector> aggDailyDominantLoadInHoursRaS =
    new Vector>();
  Vector> aggDailyDominantLoadInHoursReS =
    new Vector>();
  Vector> aggDailyDominantLoadInHoursSS =
    new Vector>();

  /**
   * These are the vectors containing aggregated each day's non dominant load
   * from the appliances installed inside the households of each type.
   **/
  Vector> aggDailyNonDominantLoadInHoursNS =
    new Vector>();
  Vector> aggDailyNonDominantLoadInHoursRaS =
    new Vector>();
  Vector> aggDailyNonDominantLoadInHoursReS =
    new Vector>();
  Vector> aggDailyNonDominantLoadInHoursSS =
    new Vector>();

  /**
   * These are the mean consumption of the village types for the days with the
   * dominant appliances working.
   **/
  double[] dominantLoadNS = new double[VillageConstants.HOURS_OF_DAY];
  double[] dominantLoadRaS = new double[VillageConstants.HOURS_OF_DAY];
  double[] dominantLoadReS = new double[VillageConstants.HOURS_OF_DAY];
  double[] dominantLoadSS = new double[VillageConstants.HOURS_OF_DAY];

  /**
   * These are the mean consumption of the village types for the days with the
   * dominant appliances not working.
   **/
  double[] nonDominantLoadNS = new double[VillageConstants.HOURS_OF_DAY];
  double[] nonDominantLoadRaS = new double[VillageConstants.HOURS_OF_DAY];
  double[] nonDominantLoadReS = new double[VillageConstants.HOURS_OF_DAY];
  double[] nonDominantLoadSS = new double[VillageConstants.HOURS_OF_DAY];

  protected final TariffEvaluationHelper tariffEvalHelper =
    new TariffEvaluationHelper();

  /**
   * This variable is utilized for the creation of the RandomSeed numbers and is
   * taken from the service.
   */
  RandomSeed gen;

  /**
   * These variables are mapping of the characteristics of the types of houses.
   */
  Map numberOfHouses = new TreeMap();
  Map tariffEvaluators;
  Map houseMapping = new TreeMap();

  /**
   * These vectors contain the houses of type in the village. There are 4 types
   * available: 1) Not Shifting Houses: They do not change the tariff
   * subscriptions during the game. 2) Randomly Shifting Houses: They change
   * their tariff subscriptions in a RandomSeed way. 3) Regularly Shifting
   * Houses:
   * They change their tariff subscriptions during the game in regular time
   * periods. 4) Smart Shifting Houses: They change their tariff subscriptions
   * in a smart way in order to minimize their costs.
   */
  Vector notShiftingHouses = new Vector();
  Vector randomlyShiftingHouses = new Vector();
  Vector regularlyShiftingHouses = new Vector();
  Vector smartShiftingHouses = new Vector();

  /** This is the constructor function of the Village customer */
  public Village (String name)
  {
    super(name);

    ArrayList typeList = new ArrayList();
    typeList.add("NS");
    typeList.add("RaS");
    typeList.add("ReS");
    typeList.add("SS");

    Comparator comp = new Comparator() {
      public int compare (CustomerInfo customer1, CustomerInfo customer2)
      {
        return customer1.getName().compareToIgnoreCase(customer2.getName());
      }
    };

    for (String type: typeList) {
      numberOfHouses.put(type, null);
      tariffEvaluators = new TreeMap(comp);
    }
  }

  @Override
  public void initialize ()
  {
    super.initialize();
  }

  /**
   * This is the initialization function. It uses the variable values for the
   * configuration file to create the village with its households and then fill
   * them with persons and appliances.
   * 
   * @param conf
   * @param seed
   * @param mapping
   */
  public void initialize (Properties conf, int seed,
                          Map mapping)
  {
    this.initialize();
    // Initializing variables
    houseMapping = mapping;

    numberOfHouses.put("NS", Integer.parseInt(conf
            .getProperty("NotShiftingCustomers")));
    numberOfHouses.put("RaS", Integer.parseInt(conf
            .getProperty("RegularlyShiftingCustomers")));
    numberOfHouses.put("ReS", Integer.parseInt(conf
            .getProperty("RandomlyShiftingCustomers")));
    numberOfHouses.put("SS", Integer.parseInt(conf
            .getProperty("SmartShiftingCustomers")));
    int days = Integer.parseInt(conf.getProperty("PublicVacationDuration"));

    gen = service.getRandomSeedRepo()
        .getRandomSeed(toString(), seed, "Village Model" + seed);

    Vector publicVacationVector = createPublicVacationVector(days);

    for (int i = 0; i < numberOfHouses.get("NS"); i++) {
      log.info("Initializing " + toString() + " NSHouse " + i);
      Household hh = new Household();
      hh.initialize(toString() + " NSHouse" + i, conf, publicVacationVector,
                    seedId++);
      notShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < numberOfHouses.get("RaS"); i++) {
      log.info("Initializing " + toString() + " RaSHouse " + i);
      Household hh = new Household();
      hh.initialize(toString() + " RaSHouse" + i, conf, publicVacationVector,
                    seedId++);
      randomlyShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < numberOfHouses.get("ReS"); i++) {
      log.info("Initializing " + toString() + " ReSHouse " + i);
      Household hh = new Household();
      hh.initialize(toString() + " ReSHouse" + i, conf, publicVacationVector,
                    seedId++);
      regularlyShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < numberOfHouses.get("SS"); i++) {
      log.info("Initializing " + toString() + " SSHouse " + i);
      Household hh = new Household();
      hh.initialize(toString() + " SSHouse" + i, conf, publicVacationVector,
                    seedId++);
      smartShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (String type: numberOfHouses.keySet()) {
      fillAggWeeklyLoad(type);

      double weight = gen.nextDouble() * VillageConstants.WEIGHT_INCONVENIENCE;

      double weeks =
        gen.nextInt(VillageConstants.MAX_DEFAULT_DURATION
                    - VillageConstants.MIN_DEFAULT_DURATION)
                + VillageConstants.MIN_DEFAULT_DURATION;

      List customer =
        service.getCustomerRepo().findByName(name + " " + type + " Base");

      TariffEvaluationWrapper wrapper =
        new TariffEvaluationWrapper(type, customer.get(0));

      TariffEvaluator te = new TariffEvaluator(wrapper);

      te.initializeInconvenienceFactors(VillageConstants.TOU_FACTOR,
                                        VillageConstants.TIERED_RATE_FACTOR,
                                        VillageConstants.VARIABLE_PRICING_FACTOR,
                                        VillageConstants.INTERRUPTIBILITY_FACTOR);
      te.withInconvenienceWeight(weight)
              .withInertia(Double.parseDouble(conf
                                   .getProperty(type + "Inertia")))
              .withPreferredContractDuration(weeks
                                             * VillageConstants.DAYS_OF_WEEK)
              .withRationality(Double.parseDouble(conf
                                       .getProperty(type + "Rationality")))
              .withTariffEvalDepth(VillageConstants.TARIFF_COUNT)
              .withTariffSwitchFactor(VillageConstants.TARIFF_SWITCH_FACTOR);

      tariffEvaluators.put(customer.get(0), te);

      customer = service.getCustomerRepo()
          .findByName(name + " " + type + " Controllable");

      wrapper = new TariffEvaluationWrapper(type, customer.get(0));

      te = new TariffEvaluator(wrapper);

      te.initializeInconvenienceFactors(VillageConstants.TOU_FACTOR,
                                        VillageConstants.TIERED_RATE_FACTOR,
                                        VillageConstants.VARIABLE_PRICING_FACTOR,
                                        VillageConstants.INTERRUPTIBILITY_FACTOR);
      te.withInconvenienceWeight(weight)
              .withInertia(Double.parseDouble(conf
                                   .getProperty(type + "Inertia")))
              .withPreferredContractDuration(weeks
                                                     * VillageConstants.DAYS_OF_WEEK)
              .withRationality(Double.parseDouble(conf
                                       .getProperty(type + "Rationality")))
              .withTariffEvalDepth(VillageConstants.TARIFF_COUNT)
              .withTariffSwitchFactor(VillageConstants.TARIFF_SWITCH_FACTOR);

      tariffEvaluators.put(customer.get(0), te);
    }
  }

  // =====SUBSCRIPTION FUNCTIONS===== //

  //@Override
  public void subscribeDefault (TariffMarket tariffMarketService)
  {
    for (CustomerInfo customer: getCustomerInfos()) {
      Tariff candidate =
          tariffMarketService.getDefaultTariff(customer.getPowerType());
      if (null == candidate) {
        log.error("No default tariff for " + customer.getPowerType().toString());
      }
      else {
        log.info("Subscribe " + customer.getName()
                 + " to " + candidate.getPowerType().toString());
      }
      tariffMarketService.subscribeToTariff(candidate, customer,
                                            customer.getPopulation());
    }
  }

  // =====LOAD FUNCTIONS===== //

  /**
   * This function is used in order to fill each week day of the aggregated
   * daily Load of the village households for each quarter of the hour.
   * 
   * @param type
   * @return
   */
  void fillAggWeeklyLoad (String type)
  {

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.DAYS_OF_WEEK
                          * (VillageConstants.WEEKS_OF_COMPETITION + VillageConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadNS.add(fillAggDailyBaseLoad(i, type));
        aggDailyControllableLoadNS.add(fillAggDailyControllableLoad(i, type));
        aggDailyWeatherSensitiveLoadNS
                .add(fillAggDailyWeatherSensitiveLoad(i, type));

        aggDailyBaseLoadInHoursNS.add(fillAggDailyBaseLoadInHours(i, type));
        aggDailyControllableLoadInHoursNS
                .add(fillAggDailyControllableLoadInHours(i, type));
        aggDailyWeatherSensitiveLoadInHoursNS
                .add(fillAggDailyWeatherSensitiveLoadInHours(i, type));

        aggDailyDominantLoadNS.add(fillAggDailyDominantLoad(i, type));
        aggDailyNonDominantLoadNS.add(fillAggDailyNonDominantLoad(i, type));
        aggDailyDominantLoadInHoursNS
                .add(fillAggDailyDominantLoadInHours(i, type));
        aggDailyNonDominantLoadInHoursNS
                .add(fillAggDailyNonDominantLoadInHours(i, type));
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.DAYS_OF_WEEK
                          * (VillageConstants.WEEKS_OF_COMPETITION + VillageConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadRaS.add(fillAggDailyBaseLoad(i, type));
        aggDailyControllableLoadRaS.add(fillAggDailyControllableLoad(i, type));
        aggDailyWeatherSensitiveLoadRaS
                .add(fillAggDailyWeatherSensitiveLoad(i, type));
        aggDailyBaseLoadInHoursRaS.add(fillAggDailyBaseLoadInHours(i, type));
        aggDailyControllableLoadInHoursRaS
                .add(fillAggDailyControllableLoadInHours(i, type));
        aggDailyWeatherSensitiveLoadInHoursRaS
                .add(fillAggDailyWeatherSensitiveLoadInHours(i, type));

        aggDailyDominantLoadRaS.add(fillAggDailyDominantLoad(i, type));
        aggDailyNonDominantLoadRaS.add(fillAggDailyNonDominantLoad(i, type));
        aggDailyDominantLoadInHoursRaS
                .add(fillAggDailyDominantLoadInHours(i, type));
        aggDailyNonDominantLoadInHoursRaS
                .add(fillAggDailyNonDominantLoadInHours(i, type));
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.DAYS_OF_WEEK
                          * (VillageConstants.WEEKS_OF_COMPETITION + VillageConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadReS.add(fillAggDailyBaseLoad(i, type));
        aggDailyControllableLoadReS.add(fillAggDailyControllableLoad(i, type));
        aggDailyWeatherSensitiveLoadReS
                .add(fillAggDailyWeatherSensitiveLoad(i, type));
        aggDailyBaseLoadInHoursReS.add(fillAggDailyBaseLoadInHours(i, type));
        aggDailyControllableLoadInHoursReS
                .add(fillAggDailyControllableLoadInHours(i, type));
        aggDailyWeatherSensitiveLoadInHoursReS
                .add(fillAggDailyWeatherSensitiveLoadInHours(i, type));

        aggDailyDominantLoadReS.add(fillAggDailyDominantLoad(i, type));
        aggDailyNonDominantLoadReS.add(fillAggDailyNonDominantLoad(i, type));
        aggDailyDominantLoadInHoursReS
                .add(fillAggDailyDominantLoadInHours(i, type));
        aggDailyNonDominantLoadInHoursReS
                .add(fillAggDailyNonDominantLoadInHours(i, type));
      }
    }
    else {
      for (int i = 0; i < VillageConstants.DAYS_OF_WEEK
                          * (VillageConstants.WEEKS_OF_COMPETITION + VillageConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadSS.add(fillAggDailyBaseLoad(i, type));
        aggDailyControllableLoadSS.add(fillAggDailyControllableLoad(i, type));
        aggDailyWeatherSensitiveLoadSS
                .add(fillAggDailyWeatherSensitiveLoad(i, type));
        aggDailyBaseLoadInHoursSS.add(fillAggDailyBaseLoadInHours(i, type));
        aggDailyControllableLoadInHoursSS
                .add(fillAggDailyControllableLoadInHours(i, type));
        aggDailyWeatherSensitiveLoadInHoursSS
                .add(fillAggDailyWeatherSensitiveLoadInHours(i, type));

        aggDailyDominantLoadSS.add(fillAggDailyDominantLoad(i, type));
        aggDailyNonDominantLoadSS.add(fillAggDailyNonDominantLoad(i, type));
        aggDailyDominantLoadInHoursSS
                .add(fillAggDailyDominantLoadInHours(i, type));
        aggDailyNonDominantLoadInHoursSS
                .add(fillAggDailyNonDominantLoadInHours(i, type));
      }
    }

    fillAggDominantLoads(type);
  }

  private void fillAggDominantLoads (String type)
  {

    double[] dominant = new double[VillageConstants.HOURS_OF_DAY];
    double[] nonDominant = new double[VillageConstants.HOURS_OF_DAY];

    Vector houses = getHouses(type);

    for (int i = 0; i < houses.size(); i++) {
      for (int j = 0; j < VillageConstants.HOURS_OF_DAY; j++) {

        dominant[j] += houses.get(i).getDominantConsumption(j);
        nonDominant[j] += houses.get(i).getNonDominantConsumption(j);

      }
    }

    if (type.equals("NS")) {

      dominantLoadNS = dominant;
      nonDominantLoadNS = nonDominant;

    }
    else if (type.equals("RaS")) {

      dominantLoadRaS = dominant;
      nonDominantLoadRaS = nonDominant;
    }
    else if (type.equals("ReS")) {

      dominantLoadReS = dominant;
      nonDominantLoadReS = nonDominant;

    }
    else {

      dominantLoadSS = dominant;
      nonDominantLoadSS = nonDominant;

    }
  }

  private double[] getDominantLoad (String type)
  {

    if (type.equals("NS"))
      return dominantLoadNS;

    else if (type.equals("RaS"))
      return dominantLoadRaS;
    else if (type.equals("ReS"))
      return dominantLoadReS;
    else
      return dominantLoadSS;

  }

  /**
   * This function is used in order to update the daily aggregated Load in case
   * there are changes in the weather sensitive loads of the village's
   * households.
   * 
   * @param type
   * @return
   */
  void updateAggDailyWeatherSensitiveLoad (String type, int day)
  {
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);
    if (type.equals("NS")) {
      aggDailyWeatherSensitiveLoadNS
              .set(dayTemp, fillAggDailyWeatherSensitiveLoad(dayTemp, type));
      aggDailyWeatherSensitiveLoadInHoursNS
              .set(dayTemp,
                   fillAggDailyWeatherSensitiveLoadInHours(dayTemp, type));
    }
    else if (type.equals("RaS")) {
      aggDailyWeatherSensitiveLoadRaS
              .set(dayTemp, fillAggDailyWeatherSensitiveLoad(dayTemp, type));
      aggDailyWeatherSensitiveLoadInHoursRaS
              .set(dayTemp,
                   fillAggDailyWeatherSensitiveLoadInHours(dayTemp, type));
    }
    else if (type.equals("ReS")) {
      aggDailyWeatherSensitiveLoadReS
              .set(dayTemp, fillAggDailyWeatherSensitiveLoad(dayTemp, type));
      aggDailyWeatherSensitiveLoadInHoursReS
              .set(dayTemp,
                   fillAggDailyWeatherSensitiveLoadInHours(dayTemp, type));
    }
    else {
      aggDailyWeatherSensitiveLoadSS
              .set(dayTemp, fillAggDailyWeatherSensitiveLoad(dayTemp, type));
      aggDailyWeatherSensitiveLoadInHoursSS
              .set(dayTemp,
                   fillAggDailyWeatherSensitiveLoadInHours(dayTemp, type));
    }
  }

  /**
   * This function is used in order to fill the aggregated daily Base Load of
   * the village's households for each quarter of the hour.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyBaseLoad (int day, String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(VillageConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < VillageConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house: houses) {
        sum = sum + house.weeklyBaseLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the aggregated daily Controllable
   * Load of the village's households for each quarter of the hour.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyControllableLoad (int day, String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(VillageConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < VillageConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house: houses) {
        sum = sum + house.weeklyControllableLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the aggregated daily weather
   * sensitive Load of the village's households for each quarter of the hour.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyWeatherSensitiveLoad (int day, String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(VillageConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < VillageConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house: houses) {
        sum = sum + house.weeklyWeatherSensitiveLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the aggregated daily dominant
   * Load of the village's households for each quarter of the hour.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyDominantLoad (int day, String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(VillageConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < VillageConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house: houses) {
        sum = sum + house.weeklyDominantLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the aggregated daily non dominant
   * Load of the village's households for each quarter of the hour.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyNonDominantLoad (int day, String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(VillageConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < VillageConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house: houses) {
        sum = sum + house.weeklyNonDominantLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the daily Base Load of the household
   * for each hour for a certain type of households.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyBaseLoadInHours (int day, String type)
  {

    Vector daily = new Vector();
    long sum = 0;

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyBaseLoadNS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyBaseLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyBaseLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyBaseLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyBaseLoadRaS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyBaseLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyBaseLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyBaseLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyBaseLoadReS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyBaseLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyBaseLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyBaseLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyBaseLoadSS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyBaseLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyBaseLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyBaseLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This function is used in order to fill the daily Controllable Load of the
   * household for each hour for a certain type of households.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyControllableLoadInHours (int day, String type)
  {

    Vector daily = new Vector();
    long sum = 0;

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyControllableLoadNS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyControllableLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyControllableLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyControllableLoadNS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyControllableLoadRaS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyControllableLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyControllableLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyControllableLoadRaS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyControllableLoadReS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyControllableLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyControllableLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyControllableLoadReS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyControllableLoadSS.get(day)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyControllableLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyControllableLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyControllableLoadSS.get(day)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This function is used in order to fill the daily weather sensitive Load of
   * the household for each hour for a certain type of households.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyWeatherSensitiveLoadInHours (int day, String type)
  {

    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);
    Vector daily = new Vector();
    long sum = 0;

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyWeatherSensitiveLoadNS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyWeatherSensitiveLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyWeatherSensitiveLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyWeatherSensitiveLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyWeatherSensitiveLoadRaS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyWeatherSensitiveLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyWeatherSensitiveLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyWeatherSensitiveLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyWeatherSensitiveLoadReS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyWeatherSensitiveLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyWeatherSensitiveLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyWeatherSensitiveLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyWeatherSensitiveLoadSS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyWeatherSensitiveLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyWeatherSensitiveLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyWeatherSensitiveLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This function is used in order to fill the daily dominant Load of
   * the household for each hour for a certain type of households.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyDominantLoadInHours (int day, String type)
  {

    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);
    Vector daily = new Vector();
    long sum = 0;

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyDominantLoadNS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyDominantLoadRaS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyDominantLoadReS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyDominantLoadSS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This function is used in order to fill the daily non dominant Load of
   * the household for each hour for a certain type of households.
   * 
   * @param day
   * @param type
   * @return
   */
  Vector fillAggDailyNonDominantLoadInHours (int day, String type)
  {

    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);
    Vector daily = new Vector();
    long sum = 0;

    if (type.equals("NS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyNonDominantLoadNS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyNonDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyNonDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyNonDominantLoadNS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("RaS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyNonDominantLoadRaS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyNonDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyNonDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyNonDominantLoadRaS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else if (type.equals("ReS")) {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyNonDominantLoadReS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyNonDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyNonDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyNonDominantLoadReS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }
    else {
      for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum =
          aggDailyNonDominantLoadSS.get(dayTemp)
                  .get(i * VillageConstants.QUARTERS_OF_HOUR)
                  + aggDailyNonDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 1)
                  + aggDailyNonDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 2)
                  + aggDailyNonDominantLoadSS.get(dayTemp)
                          .get(i * VillageConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  // // =====CONSUMPTION FUNCTIONS===== //

  public void consumePower ()
  {
    Timeslot ts = service.getTimeslotRepo().currentTimeslot();
    int serial;

    for (CustomerInfo customer: getCustomerInfos()) {

      List subscriptions =
        service.getTariffSubscriptionRepo()
        .findActiveSubscriptionsForCustomer(customer);

      String temp = houseMapping.get(customer);

      String type = temp.substring(0, 2);

      boolean controllable = temp.contains("Controllable");

      if (ts == null) {
        log.error("Current timeslot is null");
        serial = 0;
      }
      else {
        log.debug("Timeslot Serial: " + ts.getSerialNumber());
        serial = ts.getSerialNumber();
      }

      double load = getConsumptionByTimeslot(serial, type, controllable);

      log.debug("Consumption Load for Customer " + customer.toString() + ": "
                + load + " for subscriptions " + subscriptions.toString());

      if (subscriptions != null && subscriptions.size() != 0) {
        subscriptions.get(0).usePower(load);
      }
    }
  }

  /**
   * This method takes as an input the time-slot serial number (in order to know
   * in the current time) and estimates the consumption for this time-slot over
   * the population under the Village Household Consumer.
   */
  double
    getConsumptionByTimeslot (int serial, String type, boolean controllable)
  {

    int day = (int) (serial / VillageConstants.HOURS_OF_DAY);
    int hour = (int) (serial % VillageConstants.HOURS_OF_DAY);
    long summary = 0;

    log.debug("Serial : " + serial + " Day: " + day + " Hour: " + hour);

    if (controllable)
      summary = getControllableConsumptions(day, hour, type);
    else
      summary =
        getBaseConsumptions(day, hour, type)
                + getWeatherSensitiveConsumptions(day, hour, type);

    return (double) summary / VillageConstants.THOUSAND;
  }

  // =====GETTER FUNCTIONS===== //

  /** This function returns the inertia Map variable of the village. */
  public Map getHouseMapping ()
  {
    return houseMapping;
  }

  /** This function returns the period Map variable of the village. */
  public Map getTariffEvaluators ()
  {
    return tariffEvaluators;
  }

  /**
   * This function returns the quantity of base load for a specific day and hour
   * of that day for a specific type of households.
   */
  long getBaseConsumptions (int day, int hour, String type)
  {
    long summaryBase = 0;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      summaryBase = aggDailyBaseLoadInHoursNS.get(dayTemp).get(hour);
    }
    else if (type.equals("RaS")) {
      summaryBase = aggDailyBaseLoadInHoursRaS.get(dayTemp).get(hour);
    }
    else if (type.equals("ReS")) {
      summaryBase = aggDailyBaseLoadInHoursReS.get(dayTemp).get(hour);
    }
    else {
      summaryBase = aggDailyBaseLoadInHoursSS.get(dayTemp).get(hour);
    }

    log.debug("Base Load for " + type + ":" + summaryBase);
    return summaryBase;
  }

  /**
   * This function returns the quantity of controllable load for a specific day
   * and hour of that day for a specific type of households.
   */
  long getControllableConsumptions (int day, int hour, String type)
  {
    long summaryControllable = 0;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      summaryControllable =
        aggDailyControllableLoadInHoursNS.get(dayTemp).get(hour);
    }
    else if (type.equals("RaS")) {
      summaryControllable =
        aggDailyControllableLoadInHoursRaS.get(dayTemp).get(hour);
    }
    else if (type.equals("ReS")) {
      summaryControllable =
        aggDailyControllableLoadInHoursReS.get(dayTemp).get(hour);
    }
    else {
      summaryControllable =
        aggDailyControllableLoadInHoursSS.get(dayTemp).get(hour);
    }

    log.debug("Controllable Load for " + type + ":" + summaryControllable);
    return summaryControllable;
  }

  /**
   * This function returns the quantity of weather sensitive load for a specific
   * day and hour of that day for a specific type of household.
   */
  long getNonDominantConsumptions (int day, int hour, String type)
  {
    long summaryNonDominant = 0;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      summaryNonDominant =
        aggDailyNonDominantLoadInHoursNS.get(dayTemp).get(hour);
    }
    else if (type.equals("RaS")) {
      summaryNonDominant =
        aggDailyNonDominantLoadInHoursRaS.get(dayTemp).get(hour);
    }
    else if (type.equals("ReS")) {
      summaryNonDominant =
        aggDailyNonDominantLoadInHoursReS.get(dayTemp).get(hour);
    }
    else {
      summaryNonDominant =
        aggDailyNonDominantLoadInHoursSS.get(dayTemp).get(hour);
    }

    log.debug("NonDominant Load for " + type + ":" + summaryNonDominant);
    return summaryNonDominant;
  }

  /**
   * This function returns the quantity of non dominant load for a specific
   * day and hour of that day for a specific type of household.
   */
  long getWeatherSensitiveConsumptions (int day, int hour, String type)
  {
    long summaryWeatherSensitive = 0;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      summaryWeatherSensitive =
        aggDailyWeatherSensitiveLoadInHoursNS.get(dayTemp).get(hour);
    }
    else if (type.equals("RaS")) {
      summaryWeatherSensitive =
        aggDailyWeatherSensitiveLoadInHoursRaS.get(dayTemp).get(hour);
    }
    else if (type.equals("ReS")) {
      summaryWeatherSensitive =
        aggDailyWeatherSensitiveLoadInHoursReS.get(dayTemp).get(hour);
    }
    else {
      summaryWeatherSensitive =
        aggDailyWeatherSensitiveLoadInHoursSS.get(dayTemp).get(hour);
    }

    log.debug("WeatherSensitive Load for " + type + ":"
              + summaryWeatherSensitive);
    return summaryWeatherSensitive;
  }

  /**
   * This function curtails the quantity of controllable load given by the
   * subscription, by reducing current timeslots consumption and adding it to
   * the next timeslot.
   */
  void curtailControllableConsumption (int day, int hour, String type,
                                       long curtail)
  {
    long before = 0, after = 0;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      before = aggDailyControllableLoadInHoursNS.get(dayTemp).get(hour);
      aggDailyControllableLoadInHoursNS.get(dayTemp)
              .set(hour, before + curtail);
      after = aggDailyControllableLoadInHoursNS.get(dayTemp).get(hour);
    }
    else if (type.equals("RaS")) {
      before = aggDailyControllableLoadInHoursRaS.get(dayTemp).get(hour);
      aggDailyControllableLoadInHoursRaS.get(dayTemp).set(hour,
                                                          before + curtail);
      after = aggDailyControllableLoadInHoursRaS.get(dayTemp).get(hour);
    }
    else if (type.equals("ReS")) {
      before = aggDailyControllableLoadInHoursReS.get(dayTemp).get(hour);
      aggDailyControllableLoadInHoursReS.get(dayTemp).set(hour,
                                                          before + curtail);
      after = aggDailyControllableLoadInHoursReS.get(dayTemp).get(hour);
    }
    else {
      before = aggDailyControllableLoadInHoursSS.get(dayTemp).get(hour);
      aggDailyControllableLoadInHoursSS.get(dayTemp)
              .set(hour, before + curtail);
      after = aggDailyControllableLoadInHoursSS.get(dayTemp).get(hour);
    }

    log.debug("Controllable Load for " + type + ": Before Curtailment "
              + before + " After Curtailment " + after);

  }

  /**
   * This function returns the quantity of controllable load for a specific day
   * in form of a vector for a certain type of households.
   */
  Vector getControllableConsumptions (int day, String type)
  {

    Vector controllableVector = new Vector();
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      controllableVector = aggDailyControllableLoadInHoursNS.get(dayTemp);
    }
    else if (type.equals("RaS")) {
      controllableVector = aggDailyControllableLoadInHoursRaS.get(dayTemp);
    }
    else if (type.equals("ReS")) {
      controllableVector = aggDailyControllableLoadInHoursReS.get(dayTemp);
    }
    else {
      controllableVector = aggDailyControllableLoadInHoursSS.get(dayTemp);
    }

    return controllableVector;
  }

  /**
   * This function returns the quantity of weather sensitive load for a specific
   * day in form of a vector for a certain type of households.
   */
  Vector getWeatherSensitiveConsumptions (int day, String type)
  {

    Vector weatherSensitiveVector = new Vector();
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      weatherSensitiveVector =
        aggDailyWeatherSensitiveLoadInHoursNS.get(dayTemp);
    }
    else if (type.equals("RaS")) {
      weatherSensitiveVector =
        aggDailyWeatherSensitiveLoadInHoursRaS.get(dayTemp);
    }
    else if (type.equals("ReS")) {
      weatherSensitiveVector =
        aggDailyWeatherSensitiveLoadInHoursReS.get(dayTemp);
    }
    else {
      weatherSensitiveVector =
        aggDailyWeatherSensitiveLoadInHoursSS.get(dayTemp);
    }

    return weatherSensitiveVector;
  }

  /**
   * This function returns the quantity of weather sensitive load for a specific
   * day in form of a vector for a certain type of households.
   */
  Vector getNonDominantConsumptions (int day, String type)
  {

    Vector nonDominantVector = new Vector();
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    if (type.equals("NS")) {
      nonDominantVector = aggDailyNonDominantLoadInHoursNS.get(dayTemp);
    }
    else if (type.equals("RaS")) {
      nonDominantVector = aggDailyNonDominantLoadInHoursRaS.get(dayTemp);
    }
    else if (type.equals("ReS")) {
      nonDominantVector = aggDailyNonDominantLoadInHoursReS.get(dayTemp);
    }
    else {
      nonDominantVector = aggDailyNonDominantLoadInHoursSS.get(dayTemp);
    }

    return nonDominantVector;
  }

  /**
   * This function returns a vector with all the houses that are present in this
   * village.
   */
  public Vector getHouses ()
  {

    Vector houses = new Vector();

    for (Household house: notShiftingHouses)
      houses.add(house);
    for (Household house: regularlyShiftingHouses)
      houses.add(house);
    for (Household house: randomlyShiftingHouses)
      houses.add(house);
    for (Household house: smartShiftingHouses)
      houses.add(house);

    return houses;

  }

  /**
   * This function returns a vector with all the households of a certain type
   * that are present in this village.
   */
  public Vector getHouses (String type)
  {

    Vector houses = new Vector();

    if (type.equals("NS")) {
      for (Household house: notShiftingHouses) {
        houses.add(house);
      }
    }
    else if (type.equals("RaS")) {
      for (Household house: regularlyShiftingHouses) {
        houses.add(house);
      }
    }
    else if (type.equals("ReS")) {
      for (Household house: randomlyShiftingHouses) {
        houses.add(house);
      }
    }
    else {
      for (Household house: smartShiftingHouses) {
        houses.add(house);
      }
    }

    return houses;

  }

  double[] getNonDominantUsage (int day, String type)
  {

    double[] nonDominantUsage = new double[VillageConstants.HOURS_OF_DAY];

    for (int hour = 0; hour < VillageConstants.HOURS_OF_DAY; hour++) {

      if (hour == VillageConstants.HOURS_OF_DAY - 1)
        nonDominantUsage[hour] = getNonDominantConsumptions(day, 0, type);
      else
        nonDominantUsage[hour] =
          getNonDominantConsumptions(day, hour + 1, type);
      log.debug("Non Dominant Usage for hour " + hour + ":"
                + nonDominantUsage[hour]);

    }

    return nonDominantUsage;
  }

  // =====EVALUATION FUNCTIONS===== //

  /**
   * This is the basic evaluation function, taking into consideration the
   * minimum cost without shifting the appliances' load but the tariff chosen
   * is
   * picked up randomly by using a possibility pattern. The better tariffs
   * have
   * more chances to be chosen.
   */
  @Override
  public void evaluateTariffs (List tariffs)
  {
    for (CustomerInfo customer: getCustomerInfos()) {
      log.info("Customer " + customer.toString()
               + " evaluating tariffs for timeslot "
               + service.getTimeslotRepo().currentTimeslot().getId());
      TariffEvaluator evaluator = tariffEvaluators.get(customer);
      evaluator.evaluateTariffs();
    }
  }

  // =====SHIFTING FUNCTIONS===== //

  /**
   * This is the function that takes every household in the village and reads
   * the shifted Controllable Consumption for the needs of the tariff
   * evaluation.
   * 
   * @param tariff
   * @param day
   * @param type
   * @param start 
   * @return
   */
  double[] dailyShifting (Tariff tariff, double[] nonDominantUsage, int day,
                          String type, Instant start)
  {

    double[] newControllableLoad = nonDominantUsage;
    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    Vector houses = new Vector();

    if (type.equals("NS")) {
      houses = notShiftingHouses;
    }
    else if (type.equals("RaS")) {
      houses = randomlyShiftingHouses;
    }
    else if (type.equals("ReS")) {
      houses = regularlyShiftingHouses;
    }
    else {
      houses = smartShiftingHouses;
    }

    for (Household house: houses) {
      double[] temp =
        house.dailyShifting(tariff, newControllableLoad, tariffEvalHelper,
                            dayTemp, gen, start);

      log.debug("New Dominant Load for house " + house.toString()
                + " for Tariff " + tariff.toString() + ": "
                + Arrays.toString(temp));

      for (int j = 0; j < VillageConstants.HOURS_OF_DAY; j++)
        newControllableLoad[j] += temp[j];

    }

    log.debug("New Overall Load of Village " + toString() + " type " + type
              + " for Tariff " + tariff.toString() + ": "
              + Arrays.toString(newControllableLoad));

    return newControllableLoad;
  }

  // =====VECTOR CREATION===== //

  /**
   * This function is creating a certain number of RandomSeed days that will be
   * public vacation for the people living in the environment.
   * 
   * @param days
   * @param gen
   * @return
   */
  Vector createPublicVacationVector (int days)
  {
    // Creating auxiliary variables
    Vector v = new Vector(days);

    for (int i = 0; i < days; i++) {
      int x =
        gen.nextInt(VillageConstants.DAYS_OF_COMPETITION
                    + VillageConstants.DAYS_OF_BOOTSTRAP);
      ListIterator iter = v.listIterator();
      while (iter.hasNext()) {
        int temp = (int) iter.next();
        if (x == temp) {
          x = x + 1;
          iter = v.listIterator();
        }
      }
      v.add(x);
    }
    java.util.Collections.sort(v);
    return v;
  }

  // =====STEP FUNCTIONS===== //

  @Override
  public void step ()
  {
    int serial = service.getTimeslotRepo().currentSerialNumber();
    Timeslot ts = service.getTimeslotRepo().currentTimeslot();
    // TODO - this code assumes that games start at midnight. Bad assumption.
    int day = (int) (serial / VillageConstants.HOURS_OF_DAY);
    int hour = ts.getStartTime().getHourOfDay();
    Instant now = ts.getStartInstant();

    weatherCheck(day, hour, now);

    checkCurtailment(serial, day, hour);

    consumePower();

    // for (Household house: getHouses())
    // house.test();

    if (hour == 23) {

      for (String type: numberOfHouses.keySet()) {
        if (!(type.equals("NS"))) {
          log.info("Rescheduling " + type);
          rescheduleNextDay(type);
        }

      }

    }

  }

  /**
   * This function is utilized in order to check the weather at each time tick
   * of the competition clock and reschedule the appliances that are weather
   * sensitive to work.
   */
  void weatherCheck (int day, int hour, Instant now)
  {

    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    WeatherReport wr = null;
    wr = service.getWeatherReportRepo().currentWeatherReport();

    if (wr != null) {
      double temperature = wr.getTemperature();
      // log.debug("Temperature: " + temperature);

      Vector houses = getHouses();

      for (Household house: houses) {
        house.weatherCheck(dayTemp, hour, now, temperature);
      }

      for (String type: numberOfHouses.keySet()) {
        updateAggDailyWeatherSensitiveLoad(type, day);
        if (dayTemp + 1 < VillageConstants.DAYS_OF_COMPETITION) {
          updateAggDailyWeatherSensitiveLoad(type, dayTemp + 1);
        }

      }
    }
  }

  /**
   * This function is utilized in order to check the subscriptions
   * curtailments
   * for each time tick and move the controllable load at the nexttimeslot.
   */
  void checkCurtailment (int serial, int day, int hour)
  {
    int nextSerial = service.getTimeslotRepo().currentSerialNumber() + 1;
      // (int) ((timeService.getCurrentTime().getMillis() - timeService.getBase()) / TimeService.HOUR) + 1;
    int nextDay = (int) (nextSerial / VillageConstants.HOURS_OF_DAY);
    int nextHour = (int) (nextSerial % VillageConstants.HOURS_OF_DAY);

    int dayTemp =
      day
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);
    int nextDayTemp =
      nextDay
              % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    for (CustomerInfo customer: getCustomerInfos()) {

      if (customer.getPowerType() == PowerType.INTERRUPTIBLE_CONSUMPTION) {

        List subs =
          service.getTariffSubscriptionRepo()
          .findActiveSubscriptionsForCustomer(customer);

        long curt =
          (long) subs.get(0).getCurtailment() * VillageConstants.THOUSAND;
        log.debug(this.toString() + " Subscription " + subs.get(0).toString()
                  + " Curtailment " + curt);

        if (curt > 0) {

          String temp = houseMapping.get(customer);

          String type = temp.substring(0, 2);

          curtailControllableConsumption(dayTemp, hour, type, -(long) (curt));
          curtailControllableConsumption(nextDayTemp, nextHour, type,
                                         (long) (curt));

        }
      }

    }

  }

  /**
   * This function is utilized in order to reschedule the consumption load for
   * the next day of the competition according to the tariff rates of the
   * subscriptions under contract.
   */
  void rescheduleNextDay (String type)
  {
    int serial = service.getTimeslotRepo().currentSerialNumber();
    int day = (int) (serial / VillageConstants.HOURS_OF_DAY) + 1;

    int dayTemp =
      day % (VillageConstants.DAYS_OF_BOOTSTRAP + VillageConstants.DAYS_OF_COMPETITION);

    double[] nonDominantUsage = getNonDominantUsage(dayTemp, type);

    Vector controllableVector = new Vector();

    CustomerInfo customer = service.getCustomerRepo()
        .findByNameAndPowerType(name + " " + type + " Controllable",
                                PowerType.INTERRUPTIBLE_CONSUMPTION);

    TariffSubscription sub = service.getTariffSubscriptionRepo()
        .findActiveSubscriptionsForCustomer(customer).get(0);

    log.debug("Old Consumption for day " + day + ": "
              + getControllableConsumptions(dayTemp, type).toString());
    double[] newControllableLoad =
      dailyShifting(sub.getTariff(), nonDominantUsage,
                    dayTemp, type, nextStartOfDay());

    for (int i = 0; i < VillageConstants.HOURS_OF_DAY; i++) {
      String newControllableLoadString =
        Double.toString(newControllableLoad[i]);
      newControllableLoadString = newControllableLoadString.replace(".0", "");
      controllableVector.add(Long.parseLong(newControllableLoadString));
    }

    log.debug("New Consumption for day " + day + ": "
              + controllableVector.toString());

    if (type.equals("RaS")) {
      aggDailyControllableLoadInHoursRaS.set(dayTemp, controllableVector);
    }
    else if (type.equals("ReS")) {
      aggDailyControllableLoadInHoursReS.set(dayTemp, controllableVector);
    }
    else {
      aggDailyControllableLoadInHoursSS.set(dayTemp, controllableVector);
    }

  }

  @Override
  public String toString ()
  {
    return name;
  }

  public class TariffEvaluationWrapper implements CustomerModelAccessor
  {
    private String type;
    private int day;
    private CustomerInfo customerInfo;

    public TariffEvaluationWrapper (String type, CustomerInfo customer)
    {
      this.type = type;
      customerInfo = customer;
      day =
        gen.nextInt(VillageConstants.DAYS_OF_BOOTSTRAP
                    + VillageConstants.DAYS_OF_COMPETITION);
    }

    @Override
    public CustomerInfo getCustomerInfo ()
    {
      return customerInfo;
    }

    public String getType ()
    {
      return type;
    }

    public int getPopulation ()
    {
      return getHouses(type).size();
    }

    @Override
    public CapacityProfile getCapacityProfile (Tariff tariff)
    {
      double[] result = new double[VillageConstants.HOURS_OF_DAY];

      if (type.equalsIgnoreCase("NS"))
        result =
          Arrays.copyOf(getDominantLoad(type), getDominantLoad(type).length);

      else {
        double[] nonDominantUsage = getNonDominantUsage(day, type);

        result = dailyShifting(tariff, nonDominantUsage,
                               day, type, nextStartOfDay());
      }

      log.debug(Arrays.toString(result));

      for (int i = 0; i < result.length; i++)
        result[i] /= (VillageConstants.THOUSAND * getPopulation());

      log.info("Usage: " + Arrays.toString(result));

      return new CapacityProfile(result, nextStartOfDay());
    }

    @Override
    public double getBrokerSwitchFactor (boolean isSuperseding)
    {
      double result = VillageConstants.BROKER_SWITCH_FACTOR;
      if (isSuperseding)
        return result * 5.0;
      return result;
    }

    @Override
    public double getTariffChoiceSample ()
    {
      return gen.nextDouble();
    }

    @Override
    public double getInertiaSample ()
    {

      return gen.nextDouble();
    }

    @Override
    public double getShiftingInconvenienceFactor(Tariff tariff) {
      // TODO Auto-generated method stub
      return VillageConstants.TOU_FACTOR;
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy