process.stdin.resume();
process.stdin.setEncoding('utf8');
"use strict";
/**
* Класс Электростанция
*
* @constructor
* @params {number} power - Мощность в киловаттах 1000-1000000
* @throws {Error}
*/
function PowerStation(power) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
this._setPower(power);
}
/**
* Возвращает мощность электростанции
*
* @return {number} - Мощность в киловаттах
*/
PowerStation.prototype.getPower = function() {
return this._power;
}
/**
* Устанавливает мощность электростанции
*
* @param {number} power - Мощность в мегаваттах 1-5
* @throws {Error}
*/
PowerStation.prototype._setPower = function(power) {
if (typeof(power) != "number") {
throw new Error("Required argument 'power' must be integer, given: " + typeof(power))
}
this._power = power;
}
/**
* Класс Солнечные панели, наследуется от класса Электростанция
*
* @constructor
* @param {number} power - Мощность в киловаттах
* @throws {Error}
*/
function SolarPanel(power) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
this._setPower(power);
}
SolarPanel.prototype = Object.create(PowerStation.prototype);
/**
* Возвращает мощность солнечной панели
*
* @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy
* @return {number} - Мощность в киловаттах
* @throw {Error}
*/
SolarPanel.prototype.getPower = function(timesOfDay) {
if (timesOfDay == DepartmentOfEnergy.DAY) {
return this._power;
} else if (timesOfDay == DepartmentOfEnergy.NIGHT) {
return 0;
} else {
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " + typeof(timesOfDay));
}
}
/**
* Класс Дома
*
* @constructor
* @param {number} appQuantity - Колво квартир
* @throws {Error}
*/
function House(appQuantity) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length);
}
if (typeof(appQuantity) != 'number') {
throw new Error("Type of argument must be a 'number', given: " + typeof(appQuantity));
}
this._appQuantity = appQuantity;
}
/**
* Метод возвращает потребление электричества
*
* @param {Constant} timesOfDay - Константы класса DepartmentOfEnergy
* @return {integer} - Потребление электричества в киловаттах
* @throw {Error}
*/
House.prototype._getConsumption = function(timesOfDay) {
if (timesOfDay == DepartmentOfEnergy.NIGHT) {
return 1 * this._appQuantity;
} else if (timesOfDay == DepartmentOfEnergy.DAY) {
return 4 * this._appQuantity;
} else {
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " + typeof(timesOfDay));
}
}
/**
* Класс Линии электропередач
*
* @constructor
* @param {number} power - Колво передаваемой энергии в киловаттах
* @param {number} price - Стоимость за киловатт
* @throws {Error}
*/
function PowerLine(power, price) {
if (arguments.length != 2) {
throw new Error("Constructor required 2 arguments, given: " + arguments.length)
}
if (typeof(power) != 'number' && typeof(price) != 'number') {
throw new Error("Type of arguments must be a 'number', given: " + typeof(power) + ", " + typeof(price));
}
this._power = power;
this._price = price;
}
/**
* Метод возвращает мощность
*/
PowerLine.prototype.getPower = function() {
return this._power;
}
/**
* Метод возвращает стоимость за киловатт
*/
PowerLine.prototype.getPrice = function() {
return this._price;
}
/**
* Департамент энергетики
* Методы которого считают вырабатываемое и потребляемое электричество,
* расходы и доходы с покупки и продажи электричества.
*
* @param {Array.PowerStation} powerStations
* @param {Array.SolarPanel} solarPanel
* @param {Array.House} houses
* @param {Array.PowerLine} powerLines
* @throws {Error}
*/
function DepartmentOfEnergy(powerSatations, solarPanels, houses, powerLines) {
if (arguments.length != 4) {
throw new Error("Constructor required 4 arguments, given: " + arguments.length)
}
this._powerSatations = powerSatations;
this._solarPanels = solarPanels;
this._houses = houses;
this._powerLines = powerLines;
}
/**
* Константы времени суток класса DepartmentOfEnergy
*/
DepartmentOfEnergy.DAY = 'DepartmentOfEnergy.DAY';
DepartmentOfEnergy.NIGHT = 'DepartmentOfEnergy.NIGHT';
/**
* Считает суммарное производство энергии всех объектов департамента за день/ночь
* условно день = 12 часов
*
* @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy
* @return {number} - Сумарное производство энергии
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getProduction = function(timesOfDay) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
if (timesOfDay != DepartmentOfEnergy.NIGHT &&
timesOfDay != DepartmentOfEnergy.DAY)
{
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " + typeof(timesOfDay));
}
var powerStationsMegawatts = 0;
this._powerSatations.forEach(function(pwrStat) {
powerStationsMegawatts += pwrStat.getPower() / 2;
});
var solarPanelMegawatts = 0;
this._solarPanels.forEach(function(solPan) {
solarPanelMegawatts += solPan.getPower(DepartmentOfEnergy.DAY);
});
return powerStationsMegawatts + solarPanelMegawatts;
}
/**
* Считает суммарное потребление энергии всех объектов департамента за день/ночь
* условно день = 12 часов
*
* @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy
* @return {number}
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getConsumption = function(timesOfDay) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
if (timesOfDay != DepartmentOfEnergy.NIGHT &&
timesOfDay != DepartmentOfEnergy.DAY)
{
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " + typeof(timesOfDay));
}
var сonsumption = 0;
this._houses.forEach(function(house) {
сonsumption += house._getConsumption(timesOfDay);
});
return сonsumption;
}
/**
* Считает баланс (разница между потреблением и остатком) электричества
*
* @param {number} consumption - Потребление
* @param {number} production - Производство
* @return {number}
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getBalance = function(consumption, production) {
if (arguments.length != 2) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
if (typeof(consumption) != 'number' && typeof(production) != 'number') {
throw new Error("Type of arguments must be a 'number', given: " + typeof(consumption) + ", " + typeof(production));
}
return production - consumption;
}
/**
* Считает колво электричества, которое можно купить и его цену
*
* @param {number} demandPower - Нужное кол-во электричество, которое необходимо купить/продать
* @return {Object} purchase - Заказ на покупку/продажу электричества
* @return {number} purchase.power - Колво электричества которое возможно купить/продать
* @return {number} purchase.cost - Стоимость этого колва электричества
* @return {boolean} purchase.complete - Заказ полный, если куплено/продано столько эл. сколько требовалось
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getPurchase = function(demandPower) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length);
}
if (typeof(demandPower) != 'number') {
throw new Error("Type of arguments must be a 'number', given: " + typeof(demandPower));
}
var instockPower = 0;
var power = 0;
var cost = 0;
var complete = false
var tempPwrLines = this._powerLines;
// Сортируем линии в порядке возрастания цены за мВт
tempPwrLines.sort(function(a, b){
if (a.getPrice() > b.getPrice()) return 1;
if (a.getPrice() < b.getPrice()) return -1;
});
// В выбираем нужное колво энергии у каждой линии, начиная с самой дешевой
// записывая цену, пока не запоним заявку
for(var i = 0; i < tempPwrLines.length && power < demandPower; i++) {
if (tempPwrLines[i].getPower() >= demandPower - power) {
cost += tempPwrLines[i].getPrice() * (demandPower - power);
power += demandPower - power;
} else {
cost += tempPwrLines[i].getPrice() * tempPwrLines[i].getPower();
power += tempPwrLines[i].getPower();
}
};
// Проверяем заявку на полноту
if (power == demandPower) {
complete = true;
}
return {'power': power, 'cost': cost, 'complete': complete}
}
/**
* Метод создания отчета
*
* @return {Report} - Отчет с результатами вычислений покупки/продажи и стоимости
* @throw {Error}
*/
DepartmentOfEnergy.prototype.getReport = function(timesOfDay) {
if (arguments.length != 1) {
throw new Error("Constructor required 1 argument, given: " + arguments.length)
}
if (timesOfDay != DepartmentOfEnergy.NIGHT &&
timesOfDay != DepartmentOfEnergy.DAY)
{
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " + typeof(timesOfDay));
}
var consumption = this._getConsumption(timesOfDay);
var production = this._getProduction(timesOfDay);
var balance = this._getBalance(consumption, production);
// Если баланс отрицательный, то покупаем, если положительный - продаем
if (balance < 0) {
var purchase = this._getPurchase(balance * -1);
var balanceConverge = purchase.complete;
var sales = {'power': 0, 'cost': 0};
} else {
var sales = this._getPurchase(balance);
var balanceConverge = sales.complete;
var purchase = {'power': 0, 'cost': 0};
}
return new Report(
timesOfDay,
consumption,
production,
balance,
balanceConverge,
purchase.power,
purchase.cost,
sales.power,
sales.cost
);
}
/**
* Класс отчет, создается департаментом энергетики
*
* @property {} timesOfDay - Время суток
* @property {} consumption - Потребление энергии в мегаваттах
* @property {} production - Производство энергии в мегаваттах
* @property {} balance - Баланс (остаток/нехватка) энергии в мегаваттах
* @property {} balanceConverge - Баланс (остаток/нехватка) энергии в мегаваттах
* @property {} purchasePower - Колво закупаемой энергии в мегаваттах
* @property {} purchaseCost - Стоимость закупаемой энергии в тугриках
* @property {} salesPower - Колво продоваемой энергии в мегаваттах
* @property {} salesCost - Стоимость продоваемой энергии в тугриках
*/
function Report(timesOfDay, consumption, production, balance, balanceConverge, purchasePower, purchaseCost, salesPower, salesCost) {
if (arguments.length != 9) {
throw new Error("Constructor required 9 arguments, given: " + arguments.length)
}
this.timesOfDay = timesOfDay;
this.consumption = consumption / 1000;
this.production = production / 1000;
this.balance = balance / 1000;
this.balanceConverge = balanceConverge;
this.purchasePower = purchasePower / 1000;
this.purchaseCost = purchaseCost;
this.salesPower = salesPower / 1000;
this.salesCost = salesCost;
}
// Создаем несколько электростанций
var powerStations = [
new PowerStation(16000),
new PowerStation(24000)
];
// Создаем несколько солнечных панелей
var solarPanels = [
new SolarPanel(1),
new SolarPanel(1),
new SolarPanel(3)
];
// Создаем несколько домов
var houses = [
new House(100),
new House(120),
new House(180),
new House(200),
new House(220),
new House(320),
new House(380),
new House(400),
new House(400),
new House(400),
new House(400),
new House(400),
new House(400),
new House(400),
new House(400),
new House(400),
];
// Создаем несколько электростанций
var powerLines = [
new PowerLine(80000, 3),
new PowerLine(60000, 2),
new PowerLine(10000, 1),
new PowerLine(20000, 4),
];
// Создаем министерство энергетики
var depOfEnergy = new DepartmentOfEnergy(powerStations, solarPanels, houses, powerLines);
// Формируем отчеты и выводим на экран
console.log("Day report:", depOfEnergy.getReport(DepartmentOfEnergy.DAY));
console.log("Night report:", depOfEnergy.getReport(DepartmentOfEnergy.NIGHT));