process.stdin.resume();
process.stdin.setEncoding('utf8');
"use strict";
/**
* Класс Элемент сети
* может отдавать и принимать электричество
*
* @constructor
* @param {number} generateDayPower - Генерируемая дневная мощность в киловаттах
* @param {number} generateNightPower - Генерируемая ночная мощность в киловаттах
* @param {number} consumeDayPower - Потребляемя дневная мощность в киловатах
* @param {number} consumeNightPower - Потребляемая ночная мощность в киловатах
* @throw {Error}
*/
function PowerNetElement(generateDayPower, generateNightPower, consumeDayPower, consumeNightPower) {
if (arguments.length < 4) {
throw new Error("Constructor required at least 4 arguments, given: " + arguments.length)
}
this._generateDayPower = generateDayPower;
this._generateNightPower = generateNightPower;
this._consumeDayPower = consumeDayPower;
this._consumeNightPower = consumeNightPower;
}
/**
* Генерирование электричества днем
*
* @return {number} - Количество производимой электроенергии в кВт
*/
PowerNetElement.prototype.generateDayPower = function() {
return this._generateDayPower;
}
/**
* Генерирование электричества ночью
*
* @return {number} - Количество производимой электроенергии в кВт
*/
PowerNetElement.prototype.generateNightPower = function() {
return this._generateNightPower;
}
/**
* Метод возвращает количества потребления электричества днем
*
* @return {number} - Количество потребляемой электроенергии в кВт
*/
PowerNetElement.prototype.consumeDayPower = function() {
return this._consumeDayPower;
}
/**
* Метод возвращает количество потребления электричества ночью
*
* @return {number} - Количество потребляемой электроенергии в кВт
*/
PowerNetElement.prototype.consumeNightPower = function() {
return this._consumeNightPower;
}
/**
* Класс Электростанция
* наследуется от PowerNetElement
*/
function PowerStation() {
PowerNetElement.apply(this, arguments);
}
PowerStation.prototype = Object.create(PowerNetElement.prototype);
/**
* Класс Солнечные панели,
* наследуется от PowerNetElement
*
* @constructor
*/
function SolarPanel() {
PowerNetElement.apply(this, arguments);
}
SolarPanel.prototype = Object.create(PowerNetElement.prototype);
/**
* Класс Квартира,
* наследуется от PowerNetElement
*
* @param {number} power - Мощность в киловаттах
*/
function Apartment() {
PowerNetElement.apply(this, arguments);
}
Apartment.prototype = Object.create(PowerNetElement.prototype);
/**
* Класс Дома,
* содержит Appartment
*
* @constructor
* @param {number} appQuantity - Колво квартир в доме
*/
function House(appQuantity) {
this._apartments = [];
for (var i = 0; i < appQuantity; i++) {
this._apartments.push(new Apartment(0, 0, 4, 1));
}
}
/**
* Метод возвращает потребление электричества днем
*
* @return {number} - Потребление электричества в киловаттах
*/
House.prototype.consumeDayPower = function() {
var consumption = 0;
for (var i = 0; i < this._apartments.length; i++) {
consumption += this._apartments[i].consumeDayPower();
}
return consumption;
}
/**
* Метод возвращает потребление электричества ночью
*
* @return {number} - Потребление электричества в киловаттах
*/
House.prototype.consumeNightPower = function() {
var consumption = 0;
for (var i = 0; i < this._apartments.length; i++) {
consumption += this._apartments[i].consumeNightPower();
}
return consumption;
}
/**
* Метод возвращает потребление электричества днем
*
* @return {number} - Потребление электричества в киловаттах
*/
House.prototype.generateDayPower = function() {
var production = 0;
for (var i = 0; i < this._apartments.length; i++) {
production += this._apartments[i].generateDayPower();
}
return production;
}
/**
* Метод возвращает потребление электричества ночью
*
* @return {number} - Потребление электричества в киловаттах
*/
House.prototype.generateNightPower = function() {
var production = 0;
for (var i = 0; i < this._apartments.length; i++) {
production += this._apartments[i].generateNightPower();
}
return production;
}
/**
* Класс Линии электропередач,
* наследуется от PowerNetElement
*
* @constructor
* @param {number} transmitPower - Передаваемая/получаемая мощность в киловаттах
* @param {number} price - Стоимость в тугриках за киловатт
* @throws {Error}
*/
function PowerLine(transmittedPower, price) {
this._transmittedPower = transmittedPower;
this._price = price;
}
PowerLine.prototype = Object.create(PowerNetElement.prototype);
/**
* Метод возвращает мощность линии
*
* @returns {number} - кВт
*/
PowerLine.prototype.getTransmittedPower= function() {
return this._transmittedPower;
}
/**
* Метод возвращает стоимость за киловатт
*
* @returns {number} - Тугриков за кВт
*/
PowerLine.prototype.getPrice = function() {
return this._price;
}
/**
* Департамент энергетики
* Методы которого считают вырабатываемое и потребляемое электричество,
* расходы и доходы с покупки и продажи электричества.
*
* @constructor
*/
function DepartmentOfEnergy() {
this._netElements = [];
}
/**
* Константы времени суток класса DepartmentOfEnergy
*/
DepartmentOfEnergy.DAY = 'DepartmentOfEnergy.DAY';
DepartmentOfEnergy.NIGHT = 'DepartmentOfEnergy.NIGHT';
/**
* Метод добавления нового элемента сети
*
* @param {(PowerElement|PowerStation|SolarPanel|House|PowerLine)} element - Елемент сети
*/
DepartmentOfEnergy.prototype.addNetElement = function(element) {
this._netElements.push(element);
}
/**
* Считает суммарное производство энергии всех объектов департамента за день/ночь
*
* @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
* @return {number} production - Сумарное производство энергии
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getProduction = function(timeOfDay) {
if (timeOfDay != DepartmentOfEnergy.NIGHT &&
timeOfDay != DepartmentOfEnergy.DAY)
{
throw new Error(
"Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
typeof(timeOfDay)
);
}
// Отфильтровываем линии передачи
var tmpNetElements = this._netElements.filter(function(element) {
return ! ("getTransmittedPower" in element);
});
var production = 0;
if (timeOfDay == DepartmentOfEnergy.DAY) {
for (var i = 0; i < tmpNetElements.length; i++) {
production += tmpNetElements[i].generateDayPower();
}
} else {
for (var i = 0; i < tmpNetElements.length; i++) {
production += tmpNetElements[i].generateNightPower();
}
}
return production;
}
/**
* Считает суммарное потребление энергии всех объектов департамента за день/ночь
*
* @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
* @return {number} consumption - Сумарное производство энергии
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getConsumption = function(timeOfDay) {
if (timeOfDay != DepartmentOfEnergy.NIGHT &&
timeOfDay != DepartmentOfEnergy.DAY)
{
throw new Error(
"Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
typeof(timeOfDay)
);
}
// Отфильтровываем линии передачи
var tmpNetElements = this._netElements.filter(function(element) {
return ! ("getTransmittedPower" in element);
});
var consumption = 0;
if (timeOfDay == DepartmentOfEnergy.DAY) {
for (var i = 0; i < tmpNetElements.length; i++) {
consumption += tmpNetElements[i].consumeDayPower();
}
} else {
for (var i = 0; i < tmpNetElements.length; i++) {
consumption += tmpNetElements[i].consumeNightPower();
}
}
return consumption;
}
/**
* Считает баланс (разница между потреблением и остатком) электричества
*
* @param {number} consumption - Потребление
* @param {number} production - Производство
* @return {number}
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getBalance = function(consumption, production) {
return production - consumption;
}
/**
* Метод считает колво электричества, которое можно купить и его цену
*
* @param {number} demandPower - Нужное кол-во электричество, которое необходимо купить/продать
* @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
* @return {Object} purchase - Заказ на покупку/продажу электричества
* @return {number} purchase.power - Колво электричества которое возможно купить/продать
* @return {number} purchase.cost - Стоимость этого колва электричества
* @return {boolean} purchase.complete - Заказ полный, если куплено/продано столько эл. сколько требовалось
* @throw {Error}
*/
DepartmentOfEnergy.prototype._getPurchase = function(demandPower) {
var instockPower = 0;
var power = 0;
var cost = 0;
var complete = false
var tempPwrLines = this._powerLines;
// Выбираем PowerLines
tempPwrLines = this._netElements.filter(function(element) {
return "getPrice" in element;
});
// Сортируем линии в порядке возрастания цены за МВт
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++) {
instockPower = tempPwrLines[i].getTransmittedPower();
if (instockPower >= demandPower - power) {
cost += tempPwrLines[i].getPrice() * (demandPower - power);
power += demandPower - power;
} else {
cost += tempPwrLines[i].getPrice() * instockPower;
power += instockPower;
}
};
// Проверяем заявку на полноту выполнения
if (power == demandPower) {
complete = true;
}
return {'power': power, 'cost': cost, 'complete': complete}
}
/**
* Метод создания отчета
*
* @param {(DepartmentOfEnergy.DAY|DepartmentOfEnergy.NIGHT)} timeOfDay - Время суток
* @return {number} report.consumption - Потребление энергии в мегаваттах
* @return {number} report.production - Производство энергии в мегаваттах
* @return {number} report.balance - Баланс (остаток/нехватка) энергии в мегаваттах
* @return {boolean} report.balanceConverge - Баланс (остаток/нехватка) энергии в мегаваттах
* @return {number} report.purchasePower - Колво закупаемой энергии в мегаваттах
* @return {number} report.purchaseCost - Стоимость закупаемой энергии в тугриках
* @return {number} report.salesPower - Колво продоваемой энергии в мегаваттах
* @return {number} report.salesCost - Стоимость продоваемой энергии в тугриках
* @return {(DepartmentOfEnergy.DAY|DepartmentOfEnergy.NIGHT)} report.timeOfDay - Время суток
* @throw {Error}
*/
DepartmentOfEnergy.prototype.getReport = function(timeOfDay) {
if (timeOfDay != DepartmentOfEnergy.NIGHT &&
timeOfDay != DepartmentOfEnergy.DAY)
{
throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
typeof(timeOfDay));
}
var consumption = this._getConsumption(timeOfDay);
var production = this._getProduction(timeOfDay);
var balance = this._getBalance(consumption, production);
var salesPower = 0;
var salesCost = 0;
var purchasePower = 0;
var purchaseCost = 0;
var balanceConverge = false;
// Если баланс отрицательный, то покупаем, если положительный - продаем
if (balance < 0) {
var purchase = this._getPurchase(balance * -1, timeOfDay);
purchasePower = purchase.power;
purchaseCost = purchase.cost;
balanceConverge = purchase.complete;
} else {
var sales = this._getPurchase(balance, timeOfDay);
salesPower = sales.power;
salesCost = sales.cost;
balanceConverge = sales.complete;
}
// Собираем все показатели в объект
var report = {
'timeOfDay': timeOfDay,
'consumption': consumption,
'production': production,
'balance': balance,
'balanceConverge': balanceConverge,
'purchasePower': purchasePower,
'purchaseCost': purchaseCost + ' тугр.',
'salesPower': salesPower,
'salesCost': salesCost + ' тугр.'
};
// Переводим кВт в МВт
for (var key in report) {
if (typeof(report[key]) == "number") {
report[key] = Util.convertkWToMW(report[key]);
}
};
return report;
}
/**
* Клaсс утилит,
*/
function Util() {}
/**
* Метод конвертации кВт в МВт
*
* @param {number} - кВт
* @return {number} - МВт
*/
Util.convertkWToMW = function(kW) {
return kW / 1000;
}
/*
******************************************
* Запуск программы
******************************************
*/
// Создаем министерство энергетики
var depOfEnergy = new DepartmentOfEnergy();
// Создаем несколько электростанций
depOfEnergy.addNetElement(new PowerStation(2000, 2000, 0, 0));
depOfEnergy.addNetElement(new PowerStation(1000, 1000, 0, 0));
// Создаем несколько солнечных панелей
depOfEnergy.addNetElement(new SolarPanel(2000, 0, 0, 0));
depOfEnergy.addNetElement(new SolarPanel(1000, 0, 0, 0));
depOfEnergy.addNetElement(new SolarPanel(3000, 0, 0, 0));
depOfEnergy.addNetElement(new SolarPanel(2000, 0, 0, 0));
depOfEnergy.addNetElement(new SolarPanel(4000, 0, 0, 0));
depOfEnergy.addNetElement(new SolarPanel(4000, 0, 0, 0));
// Создаем несколько домов
depOfEnergy.addNetElement(new House(100));
depOfEnergy.addNetElement(new House(120));
depOfEnergy.addNetElement(new House(180));
depOfEnergy.addNetElement(new House(200));
depOfEnergy.addNetElement(new House(320));
depOfEnergy.addNetElement(new House(380));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
depOfEnergy.addNetElement(new House(400));
// Создаем несколько электростанций
depOfEnergy.addNetElement(new PowerLine(1000, 3));
depOfEnergy.addNetElement(new PowerLine(3000, 5));
depOfEnergy.addNetElement(new PowerLine(1000, 1));
// Формируем отчеты и выводим на экран
console.log("Day report: ", depOfEnergy.getReport(DepartmentOfEnergy.DAY));
console.log("Night report: ", depOfEnergy.getReport(DepartmentOfEnergy.NIGHT));