예제 #1
0
 // Get a beginning-of-week time for consistent tariff evaluation
 private Instant getNextSunday() {
   Instant result = getNowInstant();
   int hour = result.get(DateTimeFieldType.hourOfDay());
   if (hour > 0) result = result.plus((24 - hour) * TimeService.HOUR);
   int day = result.get(DateTimeFieldType.dayOfWeek());
   result = result.plus((7 - day) * TimeService.DAY);
   return result;
 }
  // Check production transactions
  @Test
  public void testProduction() {
    Instant exp = now.plus(TimeService.WEEK * 10);
    TariffSpecification tariffSpec =
        new TariffSpecification(broker, PowerType.PRODUCTION)
            .withExpiration(exp)
            .withMinDuration(TimeService.WEEK * 4)
            .withSignupPayment(-34.2)
            .withEarlyWithdrawPayment(35.0)
            .addRate(new Rate().withValue(0.102));
    tariff = new Tariff(tariffSpec);
    tariff.init();

    // subscribe and consume in the first timeslot
    TariffSubscription tsub = tariffMarketService.subscribeToTariff(tariff, customer, 4);
    assertEquals("four customers committed", 4, tsub.getCustomersCommitted());
    tsub.usePower(-244.6); // production
    assertEquals("correct total usage", -244.6 / 4, tsub.getTotalUsage(), 1e-6);
    assertEquals("correct realized price", 0.102, tariff.getRealizedPrice(), 1e-6);
    // def txs = TariffTransaction.findAllByPostedTime(timeService.currentTime);
    // assertEquals("two transactions", 2, txs.size())
    // TariffTransaction ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.SIGNUP)
    // assertNotNull("found signup tx", ttx)
    // assertEquals("correct charge", -34.2 * 4, ttx.charge, 1e-6)
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.PRODUCE)
    // assertNotNull("found production tx", ttx)
    // assertEquals("correct amount", -244.6, ttx.quantity)
    // assertEquals("correct charge", -0.102 * 244.6, ttx.charge, 1e-6)
  }
예제 #3
0
 // Returns the next date/time when the given shift index will occur
 Instant indexToInstant(int index) {
   Instant now = getNowInstant();
   int probe = index;
   // get the probe within the shift schedule
   while (probe < 0) {
     probe += shiftSchedule.length;
   }
   while (probe > shiftSchedule.length) {
     probe -= shiftSchedule.length;
   }
   int nowIndex = indexOfShift(now);
   if (nowIndex <= index) {
     return (now.plus(TimeService.HOUR * (index - nowIndex)));
   }
   return (now.plus(TimeService.HOUR * (shiftSchedule.length + index - nowIndex)));
 }
  // subscription withdrawal without and with penalty
  @Test
  public void testEarlyWithdraw() {
    Instant exp = now.plus(TimeService.WEEK * 10);
    TariffSpecification tariffSpec =
        new TariffSpecification(broker, PowerType.CONSUMPTION)
            .withExpiration(exp)
            .withMinDuration(TimeService.WEEK * 4)
            .withSignupPayment(-33.2)
            .withEarlyWithdrawPayment(42.1)
            .addRate(new Rate().withValue(0.121));
    tariff = new Tariff(tariffSpec);
    tariff.init();
    TariffSubscription tsub = tariffMarketService.subscribeToTariff(tariff, customer, 5);

    // move time forward 2 weeks, withdraw 2 customers
    Instant wk2 = now.plus(TimeService.WEEK * 2);
    timeService.setCurrentTime(wk2);
    tsub.unsubscribe(2);
    verify(mockAccounting)
        .addTariffTransaction(
            TariffTransaction.Type.WITHDRAW, tariff, customer.getCustomerInfo(), 2, 0.0, 42.1 * 2);
    // def txs = TariffTransaction.findAllByPostedTime(wk2)
    // assertEquals("one transaction", 1, txs.size())
    // assertEquals("correct txType", TariffTransactionType.WITHDRAW, txs[0].txType)
    // assertEquals("correct charge", 42.1*2, txs[0].charge)
    assertEquals("three customers committed", 3, tsub.getCustomersCommitted());

    // move time forward another week, add 4 customers and drop 1
    Instant wk3 = now.plus(TimeService.WEEK * 2 + TimeService.HOUR * 6);
    timeService.setCurrentTime(wk3);
    TariffSubscription tsub1 = tariffMarketService.subscribeToTariff(tariff, customer, 4);
    assertEquals("same subscription", tsub, tsub1);
    tsub1.unsubscribe(1);
    // txs = TariffTransaction.findAllByPostedTime(wk3)
    // assertEquals("two transactions", 2, txs.size())
    // TariffTransaction ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    //
    // TariffTransactionType.SIGNUP)
    // assertNotNull("found signup tx", ttx)
    // assertEquals("correct charge", -33.2 * 4, ttx.charge)
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    //                                                  TariffTransactionType.WITHDRAW)
    // assertNotNull("found withdraw tx", ttx)
    // assertEquals("correct charge", 42.1, ttx.charge)
    assertEquals("six customers committed", 6, tsub1.getCustomersCommitted());
  }
  // Check consumption transactions
  @Test
  public void testConsumption() {
    Instant exp = now.plus(TimeService.WEEK * 10);
    TariffSpecification tariffSpec =
        new TariffSpecification(broker, PowerType.CONSUMPTION)
            .withExpiration(exp)
            .withMinDuration(TimeService.WEEK * 4)
            .withSignupPayment(-33.2)
            .addRate(new Rate().withValue(0.121));
    tariff = new Tariff(tariffSpec);
    tariff.init();

    // subscribe and consume in the first timeslot
    TariffSubscription tsub = tariffMarketService.subscribeToTariff(tariff, customer, 4);
    assertEquals("four customers committed", 4, tsub.getCustomersCommitted());
    tsub.usePower(24.4); // consumption
    assertEquals("correct total usage", 24.4 / 4, tsub.getTotalUsage(), 1e-6);
    assertEquals("correct realized price", 0.121, tariff.getRealizedPrice(), 1e-6);
    // def txs = TariffTransaction.findAllByPostedTime(timeService.getCurrentTime());
    // assertEquals("two transactions", 2, txs.size())
    // TariffTransaction ttx =
    //    TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.SIGNUP)
    // assertNotNull("found signup tx", ttx)
    // assertEquals("correct charge", -33.2 * 4, ttx.charge, 1e-6)
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.CONSUME)
    // assertNotNull("found consumption tx", ttx)
    // assertEquals("correct amount", 24.4, ttx.quantity)
    // assertEquals("correct charge", 0.121 * 24.4, ttx.charge, 1e-6)

    // just consume in the second timeslot
    Instant hour = now.plus(TimeService.HOUR);
    timeService.setCurrentTime(hour);
    tsub.usePower(32.8); // consumption
    assertEquals("correct total usage", (24.4 + 32.8) / 4, tsub.getTotalUsage(), 1e-6);
    assertEquals("correct realized price", 0.121, tariff.getRealizedPrice(), 1e-6);
    // txs = TariffTransaction.findAllByPostedTime(timeService.getCurrentTime())
    // assertEquals("one transaction", 1, txs.size())
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.getCurrentTime(),
    // TariffTransactionType.CONSUME)
    // assertNotNull("found consumption tx", ttx)
    // assertEquals("correct amount", 32.8, ttx.quantity)
    // assertEquals("correct charge", 0.121 * 32.8, ttx.charge, 1e-6)
  }
예제 #6
0
  // set commitment leadtime to a larger number and make sure ordering
  // behavior is correct
  @Test
  public void testGenerateOrders2() {
    // set up the genco with commitment leadtime=3
    PluginConfig config = new PluginConfig("Genco", "").addConfiguration("commitmentLeadtime", "3");
    genco.configure(config); // all defaults
    // capture orders
    final ArrayList<Order> orderList = new ArrayList<Order>();
    doAnswer(
            new Answer() {
              public Object answer(InvocationOnMock invocation) {
                Object[] args = invocation.getArguments();
                orderList.add((Order) args[0]);
                return null;
              }
            })
        .when(mockProxy)
        .routeMessage(isA(Order.class));
    // set up some timeslots
    Timeslot ts0 = timeslotRepo.makeTimeslot(start);
    ts0.disable();
    assertEquals("first ts has sn=0", 0, ts0.getSerialNumber());
    timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR));
    timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR * 2));
    timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR * 3));
    timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR * 4));
    assertEquals("4 enabled timeslots", 4, timeslotRepo.enabledTimeslots().size());

    // generate orders and check
    genco.generateOrders(start, timeslotRepo.enabledTimeslots());
    assertEquals("two orders", 2, orderList.size());
    Order first = orderList.get(0);
    assertEquals("first order for ts3", 3, first.getTimeslot().getSerialNumber());
    assertEquals("first order price", 1.0, first.getLimitPrice(), 1e-6);
    assertEquals("first order for 50 mwh", -100.0, first.getMWh(), 1e-6);
    Order second = orderList.get(1);
    assertEquals("second order for ts4", 4, second.getTimeslot().getSerialNumber());
    assertEquals("second order price", 1.0, second.getLimitPrice(), 1e-6);
    assertEquals("second order for 100 mwh", -100.0, second.getMWh(), 1e-6);
  }
예제 #7
0
 @Test
 public void testGenerateOrders() {
   // set up the genco
   PluginConfig config = new PluginConfig("Genco", "");
   genco.configure(config); // all defaults
   // capture orders
   final ArrayList<Order> orderList = new ArrayList<Order>();
   doAnswer(
           new Answer() {
             public Object answer(InvocationOnMock invocation) {
               Object[] args = invocation.getArguments();
               orderList.add((Order) args[0]);
               return null;
             }
           })
       .when(mockProxy)
       .routeMessage(isA(Order.class));
   // set up some timeslots
   Timeslot ts1 = timeslotRepo.makeTimeslot(start);
   ts1.disable();
   Timeslot ts2 = timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR));
   Timeslot ts3 = timeslotRepo.makeTimeslot(start.plus(TimeService.HOUR * 2));
   assertEquals("2 enabled timeslots", 2, timeslotRepo.enabledTimeslots().size());
   // 50 mwh already sold in ts2
   MarketPosition posn2 = new MarketPosition(genco, ts2, -50.0);
   genco.addMarketPosition(posn2, ts2);
   // generate orders and check
   genco.generateOrders(start, timeslotRepo.enabledTimeslots());
   assertEquals("two orders", 2, orderList.size());
   Order first = orderList.get(0);
   assertEquals("first order for ts2", ts2, first.getTimeslot());
   assertEquals("first order price", 1.0, first.getLimitPrice(), 1e-6);
   assertEquals("first order for 50 mwh", -50.0, first.getMWh(), 1e-6);
   Order second = orderList.get(1);
   assertEquals("second order for ts3", ts3, second.getTimeslot());
   assertEquals("second order price", 1.0, second.getLimitPrice(), 1e-6);
   assertEquals("second order for 100 mwh", -100.0, second.getMWh(), 1e-6);
 }
 @Before
 public void setUp() {
   broker = new Broker("Joe");
   now = new DateTime(2011, 1, 10, 0, 0, 0, 0, DateTimeZone.UTC).toInstant();
   timeService.setCurrentTime(now);
   Instant exp = now.plus(TimeService.WEEK * 10);
   TariffSpecification tariffSpec =
       new TariffSpecification(broker, PowerType.CONSUMPTION)
           .withExpiration(exp)
           .withMinDuration(TimeService.WEEK * 8)
           .addRate(new Rate().withValue(0.121));
   tariff = new Tariff(tariffSpec);
   tariff.init();
   customerInfo = new CustomerInfo("Charley", 100);
   customer = new AbstractCustomer(customerInfo);
   reset(mockAccounting);
 }
  // subscription with non-zero signup bonus
  @Test
  public void testSignupBonus() {
    Instant exp = now.plus(TimeService.WEEK * 10);
    TariffSpecification tariffSpec =
        new TariffSpecification(broker, PowerType.CONSUMPTION)
            .withExpiration(exp)
            .withMinDuration(TimeService.WEEK * 4)
            .withSignupPayment(-33.2)
            .addRate(new Rate().withValue(0.121));
    tariff = new Tariff(tariffSpec);
    tariff.init();

    TariffSubscription tsub = tariffMarketService.subscribeToTariff(tariff, customer, 5);
    assertNotNull("non-null subscription", tsub);
    assertEquals("five customers committed", 5, tsub.getCustomersCommitted());
    verify(mockAccounting)
        .addTariffTransaction(
            TariffTransaction.Type.SIGNUP, tariff, customer.getCustomerInfo(), 5, 0.0, -33.2 * 5);
  }
  // Check two-part tariff
  @Test
  public void testTwoPart() {
    Instant exp = now.plus(TimeService.WEEK * 10);
    TariffSpecification tariffSpec =
        new TariffSpecification(broker, PowerType.CONSUMPTION)
            .withExpiration(exp)
            .withMinDuration(TimeService.WEEK * 4)
            .withSignupPayment(-31.2)
            .withPeriodicPayment(1.3)
            .addRate(new Rate().withValue(0.112));
    tariff = new Tariff(tariffSpec);
    tariff.init();

    // subscribe and consume in the first timeslot
    TariffSubscription tsub = tariffMarketService.subscribeToTariff(tariff, customer, 6);
    assertEquals("six customers committed", 6, tsub.getCustomersCommitted());
    tsub.usePower(28.8); // consumption
    assertEquals("correct total usage", 28.8 / 6, tsub.getTotalUsage(), 1e-6);
    assertEquals(
        "correct realized price", (0.112 * 28.8 + 6 * 1.3) / 28.8, tariff.getRealizedPrice(), 1e-6);
    // def txs = TariffTransaction.findAllByPostedTime(timeService.currentTime);
    // assertEquals("two transactions", 3, txs.size())
    // TariffTransaction ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.SIGNUP)
    // assertNotNull("found signup tx", ttx)
    // assertEquals("correct charge", -31.2 * 6, ttx.charge, 1e-6)
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.CONSUME)
    // assertNotNull("found consumption tx", ttx)
    // assertEquals("correct amount", 28.8, ttx.quantity)
    // assertEquals("correct charge", 0.112 * 28.8, ttx.charge, 1e-6)
    // ttx = TariffTransaction.findByPostedTimeAndTxType(timeService.currentTime,
    // TariffTransactionType.PERIODIC)
    // assertNotNull("found periodoc tx", ttx)
    // assertEquals("correct charge", 6 * 1.3, ttx.charge, 1e-6)
  }
예제 #11
0
 // Computes constraints on future energy needs
 // Amounts are energy needed to run the chargers. Energy input to trucks
 // will be smaller due to charge efficiency.
 ShiftEnergy[] getFutureEnergyNeeds(Instant start, int horizon, double initialCharging) {
   Instant seStart = start;
   int index = indexOfShift(start);
   // current time is likely to be partway into first shift
   Shift currentShift = shiftSchedule[index]; // might be null
   int duration = 0;
   while (shiftSchedule[index] == currentShift) {
     duration += 1;
     index = nextShiftIndex(index);
   }
   Shift nextShift = shiftSchedule[index];
   // this gives us the info we need to start the sequence
   ArrayList<ShiftEnergy> data = new ArrayList<ShiftEnergy>();
   data.add(new ShiftEnergy(seStart, index, duration));
   seStart = seStart.plus(duration * TimeService.HOUR);
   int elapsed = duration;
   // add shifts until we run off the end of the horizon
   // keep in mind that a shift can be null
   while (elapsed < horizon) {
     duration = 0;
     while (nextShift == shiftSchedule[index]) {
       index = nextShiftIndex(index);
       duration += 1;
     }
     nextShift = shiftSchedule[index];
     data.add(new ShiftEnergy(seStart, index, duration));
     elapsed += duration;
     seStart = seStart.plus(duration * TimeService.HOUR);
   }
   // now we convert to array, then walk backward and fill in energy needs
   ShiftEnergy[] result = data.toArray(new ShiftEnergy[data.size()]);
   double shortage = 0.0;
   for (int i = result.length - 1; i >= 0; i--) {
     int endx = result[i].endIndex;
     int prev = previousShiftIndex(endx);
     currentShift = shiftSchedule[prev];
     Shift end = shiftSchedule[endx];
     double needed = 0.0;
     if (null != end) {
       // Assume we need, at the end of each shift, enough energy to
       // run the next shift
       needed = (end.getTrucks() * end.getDuration() * getTruckKW()) / getChargeEfficiency();
     }
     // chargers is min of charger capacity and battery availability
     int chargers = getNChargers();
     int availableBatteries = nBatteries;
     if (null != currentShift) {
       availableBatteries -= currentShift.getTrucks();
     }
     chargers = (int) Math.min(chargers, availableBatteries);
     double available =
         getMaxChargeKW() * result[i].getDuration() * chargers / getChargeEfficiency();
     double surplus = available - needed - shortage;
     shortage = Math.max(0.0, -(available - needed - shortage));
     result[i].setEnergyNeeded(needed);
     result[i].setMaxSurplus(surplus);
   }
   // finally, we need to update the first element with
   // the current battery charge.
   double finalSurplus = result[0].getMaxSurplus();
   if (finalSurplus > 0.0) {
     result[0].setMaxSurplus(finalSurplus + initialCharging);
   } else if (shortage > 0.0) {
     result[0].setMaxSurplus(initialCharging - shortage);
   }
   return result;
 }
예제 #12
0
 @Override
 public IntervalWindow assignWindow(Instant timestamp) {
   long start =
       timestamp.getMillis() - timestamp.plus(size).minus(offset).getMillis() % size.getMillis();
   return new IntervalWindow(new Instant(start), size);
 }