package io.openems.edge.energy.optimizer.app;

import static io.openems.common.utils.DateUtils.QUARTERS_PER_DAY;
import static io.openems.common.utils.DateUtils.TIME_FORMATTER;
import static io.openems.common.utils.DateUtils.toQuarterIndex;
import static io.openems.common.utils.JsonUtils.buildJsonArray;
import static io.openems.common.utils.JsonUtils.buildJsonObject;
import static io.openems.common.utils.JsonUtils.toJsonArray;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.BALANCING;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.CHARGE_GRID;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.DELAY_CHARGE;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.DELAY_DISCHARGE;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.DISCHARGE_CONSUMPTION;
import static io.openems.edge.controller.ess.timeofusetariff.StateMachine.LIMIT_CHARGE;
import static io.openems.edge.energy.optimizer.app.AppUtils.period;

import java.time.LocalTime;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import io.openems.common.utils.JsonUtils;
import io.openems.edge.controller.ess.timeofusetariff.StateMachine;
import io.openems.edge.energy.EnergySchedulerTestUtils;
import io.openems.edge.heat.askoma.Mode;

public class TestConfig {

	public static class Grid {

		protected static final JsonObject WITH_DYNAMIC_GRID_LIMIT = buildJsonObject() //
				.addProperty("maxBuyPower", 100000) //
				.addProperty("maxSellPower", 100000) //
				.addProperty("maxSellPowerWithBuffer", 100000) //
				.add("gridBuySoftLimit", buildJsonArray() //
						.add(buildJsonObject() //
								.addProperty("@type", "Task") //
								.addProperty("start", "08:00:00") //
								.addProperty("duration", "PT12H") //
								.add("recurrenceRules", buildJsonArray() //
										.add(buildJsonObject() //
												.addProperty("frequency", "daily") //
												.build()) //
										.build()) //
								.add("openems.io:payload", buildJsonObject() //
										.addProperty("power", 2000) //
										.build()) //
								.build()) //
						.add(buildJsonObject() //
								.addProperty("@type", "Task") //
								.add("openems.io:payload", buildJsonObject() //
										.addProperty("power", 6000) //
										.build()) //
								.build()) //
						.build()) //
				.build();
	}

	public static class Ess {

		protected static final JsonObject FENECON_HOME_10 = buildJsonObject() //
				.addProperty("currentEnergy", 11000) //
				.addProperty("totalEnergy", 22000) //
				.addProperty("maxChargePower", 10000) //
				.addProperty("maxDischargePower", 10000) //
				.build();
	}

	public static class Controller {

		protected static final JsonObject ESS_FIX_ACTIVE_POWER = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.ESS_FIX_ACTIVE_POWER.factoryPid) //
				.addProperty("id", "ctrlFixActivePower0") //
				.add("source", buildJsonObject() //
						.addProperty("mode", "DISCHARGE_ONCE") //
						.addProperty("power", 1000) //
						.addProperty("targetSoc", 5) //
						.build()) //
				.build();

		protected static final JsonObject ESS_LIMIT_TOTAL_DISCHARGE = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.ESS_LIMIT_TOTAL_DISCHARGE.factoryPid)
				.addProperty("id", "ctrlLimitTotalDischarge0") //
				.add("source", buildJsonObject() //
						.addProperty("minSoc", 10) //
						.build()) //
				.build();

		protected static final JsonObject ESS_EMERGENCY_CAPACITY_RESERVE = buildJsonObject() //
				.addProperty("factoryPid",
						EnergySchedulerTestUtils.Controller.ESS_EMERGENCY_CAPACITY_RESERVE.factoryPid) //
				.addProperty("id", "ctrlEmergencyCapacityReserve0") //
				.add("source", buildJsonObject() //
						.addProperty("minSoc", 100) //
						.build()) //
				.build();

		protected static final JsonObject ESS_TIME_OF_USE_TARIFF = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.ESS_TIME_OF_USE_TARIFF.factoryPid) //
				.addProperty("id", "ctrlEssTimeOfUseTariff0") //
				.add("source", buildJsonObject() //
						.add("activeModes", Stream.of(//
								BALANCING, //
								DELAY_DISCHARGE, //
								CHARGE_GRID, //
								DELAY_CHARGE, //
								LIMIT_CHARGE, //
								DISCHARGE_CONSUMPTION)//
								.map(StateMachine::name)//
								.map(JsonPrimitive::new)//
								.collect(toJsonArray())) //
						.addProperty("targetSocBuffer", 0.1)//
						.build()) //
				.build();

		protected static final JsonObject EVSE_CLUSTER_TWO = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.EVSE_CLUSTER.factoryPid) //
				.addProperty("id", "ctrlEvseCluster0") //
				.add("source", buildJsonObject() //
						.addProperty("distributionStrategy", "EQUAL_POWER") //
						.add("params", buildJsonArray() //
								.add(buildJsonObject() //
										.addProperty("componentId", "ctrlEvseSingle0") //
										.addProperty("mode", "SURPLUS") //
										.addProperty("activePower", 0) //
										.addProperty("sessionEnergy", 0) //
										.addProperty("sessionEnergyLimit", 10000) //
										.addProperty("history", "") //
										.addProperty("phaseSwitching", "DISABLE") //
										.add("combinedAbilities", buildJsonObject() //
												.add("chargePointAbilities", buildJsonObject() //
														.add("applySetPoint", buildJsonObject() //
																.addProperty("class", "MilliAmpere") //
																.addProperty("phase", "THREE_PHASE") //
																.addProperty("min", 6000) //
																.addProperty("max", 16000) //
																.build()) //
														.add("phaseSwitch", JsonNull.INSTANCE) //
														.addProperty("isEvConnected", true) //
														.addProperty("isReadyForCharging", true) //
														.build()) //
												.add("electricVehicleAbilities", buildJsonObject() //
														.add("singlePhaseLimit", buildJsonObject() //
																.addProperty("class", "Watt") //
																.addProperty("phase", "SINGLE_PHASE") //
																.addProperty("min", 1380) //
																.addProperty("max", 7360) //
																.addProperty("step", 1) //
																.build()) //
														.add("threePhaseLimit", buildJsonObject() //
																.addProperty("class", "Watt") //
																.addProperty("phase", "THREE_PHASE") //
																.addProperty("min", 4140) //
																.addProperty("max", 11040) //
																.addProperty("step", 1) //
																.build()) //
														.addProperty("capacity", 64000) //
														.addProperty("canInterrupt", true) //
														.build()) //
												.addProperty("isReadyForCharging", true) //
												.add("applySetPoint", buildJsonObject() //
														.addProperty("class", "Watt") //
														.addProperty("phase", "THREE_PHASE") //
														.addProperty("min", 4140) //
														.addProperty("max", 11040) //
														.addProperty("step", 1) //
														.build()) //
												.add("phaseSwitch", JsonNull.INSTANCE) //
												.build()) //
										.add("tasks", buildJsonArray() //
												.build()) //
										.build()) //
								.add(buildJsonObject() //
										.addProperty("componentId", "ctrlEvseSingle1") //
										.addProperty("mode", "ZERO") //
										.addProperty("activePower", 0) //
										.addProperty("sessionEnergy", 0) //
										.addProperty("sessionEnergyLimit", 0) //
										.addProperty("history", "") //
										.addProperty("phaseSwitching", "DISABLE") //
										.add("combinedAbilities", buildJsonObject() //
												.add("chargePointAbilities", buildJsonObject() //
														.add("applySetPoint", buildJsonObject() //
																.addProperty("class", "MilliAmpere") //
																.addProperty("phase", "THREE_PHASE") //
																.addProperty("min", 6000) //
																.addProperty("max", 16000) //
																.build()) //
														.add("phaseSwitch", JsonNull.INSTANCE) //
														.addProperty("isEvConnected", true) //
														.addProperty("isReadyForCharging", true) //
														.build()) //
												.add("electricVehicleAbilities", buildJsonObject() //
														.add("singlePhaseLimit", buildJsonObject() //
																.addProperty("class", "Watt") //
																.addProperty("phase", "SINGLE_PHASE") //
																.addProperty("min", 1380) //
																.addProperty("max", 7360) //
																.addProperty("step", 1) //
																.build()) //
														.add("threePhaseLimit", buildJsonObject() //
																.addProperty("class", "Watt") //
																.addProperty("phase", "THREE_PHASE") //
																.addProperty("min", 4140) //
																.addProperty("max", 11040) //
																.addProperty("step", 1) //
																.build()) //
														.addProperty("capacity", 50000) //
														.addProperty("canInterrupt", true) //
														.build()) //
												.addProperty("isReadyForCharging", true) //
												.add("applySetPoint", buildJsonObject() //
														.addProperty("class", "Watt") //
														.addProperty("phase", "THREE_PHASE") //
														.addProperty("min", 4140) //
														.addProperty("max", 11040) //
														.addProperty("step", 1) //
														.build()) //
												.add("phaseSwitch", JsonNull.INSTANCE) //
												.build()) //
										.add("tasks", buildJsonArray() //
												.add(buildJsonObject() //
														.addProperty("@type", "Task") //
														.addProperty("start", "13:00:00") //
														.addProperty("duration", "PT2H") //
														.add("recurrenceRules", buildJsonArray() //
																.add(buildJsonObject() //
																		.addProperty("frequency", "daily") //
																		.build())
																.build())
														.add("openems.io:payload", buildJsonObject() //
																.addProperty("class", "Manual") //
																.addProperty("mode", "FORCE") //
																.build())
														.build())
												.build()) //
										.build()) //
								.build()) //
						.build()) //
				.build();

		protected static final JsonObject HEAT_ASKOMA = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.HEAT_ASKOMA.factoryPid) //
				.addProperty("id", "heat0") //
				.add("source", buildJsonObject() //
						.addProperty("defaultMode", Mode.OFF.name()) //
						.addProperty("maxHeatPower", 3000) //
						.add("tasks", buildJsonArray() //
								.add(createTask("10:00:00", "PT2H", Mode.SURPLUS.name())) //
								.add(createTask("13:00:00", "PT2H", Mode.FAST_HEAT.name())) //
								.build()) //
						.build()) //
				.build();

		protected static final JsonObject BRAIINS_SINGLE = buildJsonObject() //
				.addProperty("factoryPid", EnergySchedulerTestUtils.Controller.BRAIINS_SINGLE.factoryPid) //
				.addProperty("id", "ctrlBraiinsSingle0") //
				.add("source", buildJsonObject() //
						.addProperty("defaultMode", "OFF") //
						.addProperty("consumptionW", 3000) //
						.add("tasks", buildJsonArray() //
								.add(buildJsonObject() //
										.addProperty("@type", "Task") //
										.addProperty("start", "13:00:00") //
										.addProperty("duration", "PT2H") //
										.add("recurrenceRules", buildJsonArray() //
												.add(buildJsonObject() //
														.addProperty("frequency", "daily") //
														.build()) //
												.build()) //
										.add("openems.io:payload", buildJsonObject() //
												.addProperty("class", "Manual") //
												.addProperty("mode", "ON") //
												.build()) //
										.build()) //
								.build()) //
						.build()) //
				.build();
	}

	private static JsonObject createTask(String start, String duration, String mode) {
		return buildJsonObject() //
				.addProperty("@type", "Task") //
				.addProperty("start", start) //
				.addProperty("duration", duration) //
				.add("recurrenceRules", buildJsonArray() //
						.add(buildJsonObject() //
								.addProperty("frequency", "daily") //
								.build()) //
						.build()) //
				.add("openems.io:payload", buildJsonObject() //
						.addProperty("mode", mode) //
						.build()) //
				.build();
	}

	public static class Periods {

		protected static JsonArray getTestData() {
			var startTimeDayOne = LocalTime.of(0, 0);
			var prodDayOne = ProductionTestData.PRODUCTION_SUMMER_CLEAR;
			var consDayOne = ConsumptionTestData.CONSUMPTION;
			var gridBuyPricesDayOne = GridBuyPricesTestData.PRICES_TIBBER_SUMMER_CLEAR;
			var gridSellPricesDayOne = GridSellPricesTestData.PRICES_CONSTANT;

			var endTimeDayTwo = LocalTime.of(23, 45);
			var prodDayTwo = ProductionTestData.PRODUCTION_SUMMER_CLEAR;
			var consDayTwo = ConsumptionTestData.CONSUMPTION;
			var gridBuyPricesDayTwo = GridBuyPricesTestData.PRICES_TIBBER_SUMMER_CLEAR;
			var gridSellPricesDayTwo = GridSellPricesTestData.PRICES_CONSTANT;

			var dayOneStream = IntStream.range(toQuarterIndex(startTimeDayOne), QUARTERS_PER_DAY)//
					.mapToObj(i -> {
						var time = LocalTime.MIN.plusMinutes(i * 15L);
						return period(//
								time.format(TIME_FORMATTER), //
								null, //
								prodDayOne[i], //
								consDayOne[i], //
								gridBuyPricesDayOne[i], //
								gridSellPricesDayOne[i]);
					});

			var dayTwoStream = IntStream.rangeClosed(0, toQuarterIndex(endTimeDayTwo))//
					.mapToObj(i -> {
						var time = LocalTime.MIN.plusMinutes(i * 15L);
						return period(//
								time.format(TIME_FORMATTER), //
								null, //
								prodDayTwo[i], //
								consDayTwo[i], //
								gridBuyPricesDayTwo[i], //
								gridSellPricesDayTwo[i]);
					});

			return Stream.concat(dayOneStream, dayTwoStream)//
					.collect(new JsonUtils.JsonArrayCollector());
		}

		protected static JsonArray CUSTOM = buildJsonArray()//
				// time | gridBuySoftLimit | production | consumption | price
				// Day One
				.add(period("00:00", null, 0.0, 0.0, 210.0, 90.0)) //
				.add(period("00:15", null, 0.0, 0.0, 210.0, 90.0)) //
				.add(period("00:30", null, 0.0, 0.0, 210.0, 90.0)) //
				.add(period("00:45", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("01:00", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("01:15", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("01:30", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("01:45", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("02:00", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("02:15", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("02:30", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("02:45", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("03:00", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("03:15", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("03:30", null, 0.0, 291.3, 210.0, 90.0)) //
				.add(period("03:45", null, 0.0, 251.3, 210.0, 90.0)) //
				.add(period("04:00", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("04:15", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("04:30", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("04:45", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("05:00", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("05:15", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("05:30", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("05:45", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("06:00", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("06:15", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("06:30", null, 0.0, 217.3, 210.0, 90.0)) //
				.add(period("06:45", null, 0.0, 217.3, 310.0, 90.0)) //
				.add(period("07:00", null, 0.0, 217.3, 310.0, 90.0)) //
				.add(period("07:15", null, 0.0, 217.3, 310.0, 90.0)) //
				.add(period("07:30", null, 0.0, 217.3, 310.0, 90.0)) //
				.add(period("07:45", null, 0.0, 217.3, 310.0, 90.0)) //
				.add(period("08:00", null, 0.0, 20.4, 310.0, 90.0)) //
				.add(period("08:15", null, 0.0, 28.4, 310.0, 90.0)) //
				.add(period("08:30", null, 0.0, 28.4, 310.0, 90.0)) //
				.add(period("08:45", null, 0.0, 28.4, 310.0, 90.0)) //
				.add(period("09:00", null, 0.0, 25.4, 310.0, 90.0)) //
				.add(period("09:15", null, 0.0, 215.4, 310.0, 90.0)) //
				.add(period("09:30", null, 0.0, 25.4, 310.0, 90.0)) //
				.add(period("09:45", null, 0.0, 25.4, 310.0, 90.0)) //
				.add(period("10:00", null, 0.0, 120.6, 310.0, 90.0)) //
				.add(period("10:15", null, 0.0, 120.6, 310.0, 90.0)) //
				.add(period("10:30", null, 0.0, 120.6, 310.0, 90.0)) //
				.add(period("10:45", null, 0.0, 120.6, 310.0, 90.0)) //
				.add(period("11:00", null, 0.0, 100.7, 310.0, 90.0)) //
				.add(period("11:15", null, 0.0, 100.7, 310.0, 90.0)) //
				.add(period("11:30", null, 0.0, 100.7, 310.0, 90.0)) //
				.add(period("11:45", null, 0.0, 100.7, 310.0, 90.0)) //
				.add(period("12:00", null, 0.0, 170.9, 310.0, 90.0)) //
				.add(period("12:15", null, 0.0, 170.9, 310.0, 90.0)) //
				.add(period("12:30", null, 0.0, 170.9, 310.0, 90.0)) //
				.add(period("12:45", null, 0.0, 170.9, 310.0, 90.0)) //
				.add(period("13:00", null, 0.0, 180.2, 310.0, 90.0)) //
				.add(period("13:15", null, 0.0, 180.2, 310.0, 90.0)) //
				.add(period("13:30", null, 0.0, 180.2, 310.0, 90.0)) //
				.add(period("13:45", null, 0.0, 180.2, 310.0, 90.0)) //
				.add(period("14:00", null, 0.0, 100.7, 310.0, 90.0)) //
				.add(period("14:15", null, 0.0, 180.7, 310.0, 90.0)) //
				.add(period("14:30", null, 0.0, 180.7, 310.0, 90.0)) //
				.add(period("14:45", null, 0.0, 18.7, 310.0, 90.0)) //
				.add(period("15:00", null, 0.0, 20.3, 310.0, 90.0)) //
				.add(period("15:15", null, 0.0, 20.3, 310.0, 90.0)) //
				.add(period("15:30", null, 0.0, 20.3, 310.0, 90.0)) //
				.add(period("15:45", null, 0.0, 201.3, 310.0, 90.0)) //
				.add(period("16:00", null, 0.0, 280.4, 310.0, 90.0)) //
				.add(period("16:15", null, 0.0, 280.4, 310.0, 90.0)) //
				.add(period("16:30", null, 0.0, 280.4, 310.0, 90.0)) //
				.add(period("16:45", null, 0.0, 280.4, 310.0, 90.0)) //
				.add(period("17:00", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:15", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:30", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:45", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("18:00", null, 0.0, 310.7, 310.0, 90.0)) //
				.add(period("18:15", null, 0.0, 310.7, 310.0, 90.0)) //
				.add(period("18:30", null, 0.0, 341.7, 310.0, 90.0)) //
				.add(period("18:45", null, 0.0, 341.7, 310.0, 90.0)) //
				.add(period("19:00", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:15", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:30", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:45", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("20:00", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:15", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:30", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:45", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("21:00", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:15", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:30", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:45", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("22:00", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:15", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:30", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:45", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("23:00", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:15", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:30", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:45", null, 0.0, 307.7, 310.0, 90.0)) //
				// Day Two
				.add(period("00:00", null, 0.0, 0.0, 120.0, 90.0)) //
				.add(period("00:15", null, 0.0, 0.0, 120.0, 90.0)) //
				.add(period("00:30", null, 0.0, 0.0, 120.0, 90.0)) //
				.add(period("00:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("01:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("01:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("01:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("01:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("02:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("02:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("02:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("02:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("03:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("03:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("03:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("03:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("04:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("04:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("04:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("04:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("05:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("05:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("05:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("05:45", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("06:00", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("06:15", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("06:30", null, 0.0, 291.3, 120.0, 90.0)) //
				.add(period("06:45", null, 0.0, 291.3, 310.0, 90.0)) //
				.add(period("07:00", null, 0.0, 291.3, 310.0, 90.0)) //
				.add(period("07:15", null, 0.0, 291.3, 310.0, 90.0)) //
				.add(period("07:30", null, 0.0, 291.3, 310.0, 90.0)) //
				.add(period("07:45", null, 0.0, 291.3, 310.0, 90.0)) //
				.add(period("08:00", null, 0.0, 250.4, 310.0, 90.0)) //
				.add(period("08:15", null, 10.0, 258.4, 310.0, 90.0)) //
				.add(period("08:30", null, 20.0, 258.4, 310.0, 90.0)) //
				.add(period("08:45", null, 30.0, 258.4, 310.0, 90.0)) //
				.add(period("09:00", null, 40.0, 215.4, 310.0, 90.0)) //
				.add(period("09:15", null, 60.0, 215.4, 310.0, 90.0)) //
				.add(period("09:30", null, 80.0, 215.4, 310.0, 90.0)) //
				.add(period("09:45", null, 110.0, 215.4, 310.0, 90.0)) //
				.add(period("10:00", null, 120.0, 192.6, 310.0, 90.0)) //
				.add(period("10:15", null, 120.0, 192.6, 310.0, 90.0)) //
				.add(period("10:30", null, 130.0, 192.6, 310.0, 90.0)) //
				.add(period("10:45", null, 130.0, 192.6, 310.0, 90.0)) //
				.add(period("11:00", null, 170.0, 180.7, 310.0, 90.0)) //
				.add(period("11:15", null, 190.0, 180.7, 310.0, 90.0)) //
				.add(period("11:30", null, 220.0, 180.7, 310.0, 90.0)) //
				.add(period("11:45", null, 180.0, 180.7, 310.0, 90.0)) //
				.add(period("12:00", null, 210.0, 177.9, 310.0, 90.0)) //
				.add(period("12:15", null, 220.0, 177.9, 310.0, 90.0)) //
				.add(period("12:30", null, 220.0, 177.9, 310.0, 90.0)) //
				.add(period("12:45", null, 240.0, 177.9, 310.0, 90.0)) //
				.add(period("13:00", null, 220.0, 178.2, 310.0, 90.0)) //
				.add(period("13:15", null, 220.0, 178.2, 310.0, 90.0)) //
				.add(period("13:30", null, 210.0, 178.2, 310.0, 90.0)) //
				.add(period("13:45", null, 210.0, 178.2, 310.0, 90.0)) //
				.add(period("14:00", null, 200.0, 180.7, 310.0, 90.0)) //
				.add(period("14:15", null, 180.0, 180.7, 310.0, 90.0)) //
				.add(period("14:30", null, 160.0, 180.7, 310.0, 90.0)) //
				.add(period("14:45", null, 140.0, 1800.7, 310.0, 90.0)) //
				.add(period("15:00", null, 120.0, 2010.3, 310.0, 90.0)) //
				.add(period("15:15", null, 100.0, 2010.3, 310.0, 90.0)) //
				.add(period("15:30", null, 80.0, 2010.3, 310.0, 90.0)) //
				.add(period("15:45", null, 80.0, 201.3, 310.0, 90.0)) //
				.add(period("16:00", null, 60.0, 280.4, 310.0, 90.0)) //
				.add(period("16:15", null, 50.0, 280.4, 310.0, 90.0)) //
				.add(period("16:30", null, 40.0, 2880.4, 310.0, 90.0)) //
				.add(period("16:45", null, 20.0, 2880.4, 310.0, 90.0)) //
				.add(period("17:00", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:15", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:30", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("17:45", null, 0.0, 330.2, 310.0, 90.0)) //
				.add(period("18:00", null, 0.0, 310.7, 310.0, 90.0)) //
				.add(period("18:15", null, 0.0, 310.7, 310.0, 90.0)) //
				.add(period("18:30", null, 0.0, 341.7, 310.0, 90.0)) //
				.add(period("18:45", null, 0.0, 341.7, 310.0, 90.0)) //
				.add(period("19:00", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:15", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:30", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("19:45", null, 0.0, 343.3, 310.0, 90.0)) //
				.add(period("20:00", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:15", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:30", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("20:45", null, 0.0, 335.6, 310.0, 90.0)) //
				.add(period("21:00", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:15", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:30", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("21:45", null, 0.0, 326.6, 310.0, 90.0)) //
				.add(period("22:00", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:15", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:30", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("22:45", null, 0.0, 314.9, 310.0, 90.0)) //
				.add(period("23:00", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:15", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:30", null, 0.0, 307.7, 310.0, 90.0)) //
				.add(period("23:45", null, 0.0, 307.7, 310.0, 90.0)) //
				.build();
	}
}
