fork download
  1. process.stdin.resume();
  2. process.stdin.setEncoding('utf8');
  3.  
  4. "use strict";
  5. /**
  6.  * Класс Элемент сети
  7.  * может отдавать и принимать электричество
  8.  *
  9.  * @constructor
  10.  * @param {number} generateDayPower - Генерируемая дневная мощность в киловаттах
  11.  * @param {number} generateNightPower - Генерируемая ночная мощность в киловаттах
  12.  * @param {number} consumeDayPower - Потребляемя дневная мощность в киловатах
  13.  * @param {number} consumeNightPower - Потребляемая ночная мощность в киловатах
  14.  * @throw {Error}
  15.  */
  16. function PowerNetElement(generateDayPower, generateNightPower, consumeDayPower, consumeNightPower) {
  17. if (arguments.length < 4) {
  18. throw new Error("Constructor required at least 4 arguments, given: " + arguments.length)
  19. }
  20.  
  21. this._generateDayPower = generateDayPower;
  22. this._generateNightPower = generateNightPower;
  23. this._consumeDayPower = consumeDayPower;
  24. this._consumeNightPower = consumeNightPower;
  25. }
  26.  
  27. /**
  28.  * Генерирование электричества днем
  29.  *
  30.  * @return {number} - Количество производимой электроенергии в кВт
  31.  */
  32. PowerNetElement.prototype.generateDayPower = function() {
  33. return this._generateDayPower;
  34. }
  35.  
  36. /**
  37.  * Генерирование электричества ночью
  38.  *
  39.  * @return {number} - Количество производимой электроенергии в кВт
  40.  */
  41. PowerNetElement.prototype.generateNightPower = function() {
  42. return this._generateNightPower;
  43. }
  44.  
  45. /**
  46.  * Метод возвращает количества потребления электричества днем
  47.  *
  48.  * @return {number} - Количество потребляемой электроенергии в кВт
  49.  */
  50. PowerNetElement.prototype.consumeDayPower = function() {
  51. return this._consumeDayPower;
  52. }
  53.  
  54. /**
  55.  * Метод возвращает количество потребления электричества ночью
  56.  *
  57.  * @return {number} - Количество потребляемой электроенергии в кВт
  58.  */
  59. PowerNetElement.prototype.consumeNightPower = function() {
  60. return this._consumeNightPower;
  61. }
  62.  
  63. /**
  64.  * Класс Электростанция
  65.  * наследуется от PowerNetElement
  66.  */
  67. function PowerStation() {
  68. PowerNetElement.apply(this, arguments);
  69. }
  70.  
  71. PowerStation.prototype = Object.create(PowerNetElement.prototype);
  72.  
  73.  
  74. /**
  75.  * Класс Солнечные панели,
  76.  * наследуется от PowerNetElement
  77.  *
  78.  * @constructor
  79.  */
  80. function SolarPanel() {
  81. PowerNetElement.apply(this, arguments);
  82. }
  83.  
  84. SolarPanel.prototype = Object.create(PowerNetElement.prototype);
  85.  
  86.  
  87. /**
  88.  * Класс Квартира,
  89.  * наследуется от PowerNetElement
  90.  *
  91.  * @param {number} power - Мощность в киловаттах
  92.  */
  93. function Apartment() {
  94. PowerNetElement.apply(this, arguments);
  95. }
  96.  
  97. Apartment.prototype = Object.create(PowerNetElement.prototype);
  98.  
  99.  
  100. /**
  101.  * Класс Дома,
  102.  * содержит Appartment
  103.  *
  104.  * @constructor
  105.  * @param {number} appQuantity - Колво квартир в доме
  106.  */
  107. function House(appQuantity) {
  108. this._apartments = [];
  109. for (var i = 0; i < appQuantity; i++) {
  110. this._apartments.push(new Apartment(0, 0, 4, 1));
  111. }
  112. }
  113.  
  114. /**
  115.  * Метод возвращает потребление электричества днем
  116.  *
  117.  * @return {number} - Потребление электричества в киловаттах
  118.  */
  119. House.prototype.consumeDayPower = function() {
  120. var consumption = 0;
  121. for (var i = 0; i < this._apartments.length; i++) {
  122. consumption += this._apartments[i].consumeDayPower();
  123. }
  124. return consumption;
  125. }
  126.  
  127. /**
  128.  * Метод возвращает потребление электричества ночью
  129.  *
  130.  * @return {number} - Потребление электричества в киловаттах
  131.  */
  132. House.prototype.consumeNightPower = function() {
  133. var consumption = 0;
  134. for (var i = 0; i < this._apartments.length; i++) {
  135. consumption += this._apartments[i].consumeNightPower();
  136. }
  137. return consumption;
  138. }
  139.  
  140. /**
  141.  * Метод возвращает потребление электричества днем
  142.  *
  143.  * @return {number} - Потребление электричества в киловаттах
  144.  */
  145. House.prototype.generateDayPower = function() {
  146. var production = 0;
  147. for (var i = 0; i < this._apartments.length; i++) {
  148. production += this._apartments[i].generateDayPower();
  149. }
  150. return production;
  151. }
  152.  
  153. /**
  154.  * Метод возвращает потребление электричества ночью
  155.  *
  156.  * @return {number} - Потребление электричества в киловаттах
  157.  */
  158. House.prototype.generateNightPower = function() {
  159. var production = 0;
  160. for (var i = 0; i < this._apartments.length; i++) {
  161. production += this._apartments[i].generateNightPower();
  162. }
  163. return production;
  164. }
  165.  
  166.  
  167. /**
  168.  * Класс Линии электропередач,
  169.  * наследуется от PowerNetElement
  170.  *
  171.  * @constructor
  172.  * @param {number} transmitPower - Передаваемая/получаемая мощность в киловаттах
  173.  * @param {number} price - Стоимость в тугриках за киловатт
  174.  * @throws {Error}
  175.  */
  176. function PowerLine(transmittedPower, price) {
  177. this._transmittedPower = transmittedPower;
  178. this._price = price;
  179. }
  180.  
  181. PowerLine.prototype = Object.create(PowerNetElement.prototype);
  182.  
  183. /**
  184.  * Метод возвращает мощность линии
  185.  *
  186.  * @returns {number} - кВт
  187.  */
  188. PowerLine.prototype.getTransmittedPower= function() {
  189. return this._transmittedPower;
  190. }
  191.  
  192. /**
  193.  * Метод возвращает стоимость за киловатт
  194.  *
  195.  * @returns {number} - Тугриков за кВт
  196.  */
  197. PowerLine.prototype.getPrice = function() {
  198. return this._price;
  199. }
  200.  
  201.  
  202. /**
  203.  * Департамент энергетики
  204.  * Методы которого считают вырабатываемое и потребляемое электричество,
  205.  * расходы и доходы с покупки и продажи электричества.
  206.  *
  207.  * @constructor
  208.  */
  209. function DepartmentOfEnergy() {
  210. this._netElements = [];
  211. }
  212.  
  213. /**
  214.  * Константы времени суток класса DepartmentOfEnergy
  215.  */
  216. DepartmentOfEnergy.DAY = 'DepartmentOfEnergy.DAY';
  217. DepartmentOfEnergy.NIGHT = 'DepartmentOfEnergy.NIGHT';
  218.  
  219. /**
  220.  * Метод добавления нового элемента сети
  221.  *
  222.  * @param {(PowerElement|PowerStation|SolarPanel|House|PowerLine)} element - Елемент сети
  223.  */
  224. DepartmentOfEnergy.prototype.addNetElement = function(element) {
  225. this._netElements.push(element);
  226. }
  227.  
  228. /**
  229.  * Считает суммарное производство энергии всех объектов департамента за день/ночь
  230.  *
  231.  * @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
  232.  * @return {number} production - Сумарное производство энергии
  233.  * @throw {Error}
  234.  */
  235. DepartmentOfEnergy.prototype._getProduction = function(timeOfDay) {
  236. if (timeOfDay != DepartmentOfEnergy.NIGHT &&
  237. timeOfDay != DepartmentOfEnergy.DAY)
  238. {
  239. throw new Error(
  240. "Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
  241. typeof(timeOfDay)
  242. );
  243. }
  244.  
  245. // Отфильтровываем линии передачи
  246. var tmpNetElements = this._netElements.filter(function(element) {
  247. return ! ("getTransmittedPower" in element);
  248. });
  249.  
  250. var production = 0;
  251. if (timeOfDay == DepartmentOfEnergy.DAY) {
  252. for (var i = 0; i < tmpNetElements.length; i++) {
  253. production += tmpNetElements[i].generateDayPower();
  254. }
  255. } else {
  256. for (var i = 0; i < tmpNetElements.length; i++) {
  257. production += tmpNetElements[i].generateNightPower();
  258. }
  259. }
  260.  
  261. return production;
  262. }
  263.  
  264. /**
  265.  * Считает суммарное потребление энергии всех объектов департамента за день/ночь
  266.  *
  267.  * @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
  268.  * @return {number} consumption - Сумарное производство энергии
  269.  * @throw {Error}
  270.  */
  271. DepartmentOfEnergy.prototype._getConsumption = function(timeOfDay) {
  272. if (timeOfDay != DepartmentOfEnergy.NIGHT &&
  273. timeOfDay != DepartmentOfEnergy.DAY)
  274. {
  275. throw new Error(
  276. "Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
  277. typeof(timeOfDay)
  278. );
  279. }
  280.  
  281. // Отфильтровываем линии передачи
  282. var tmpNetElements = this._netElements.filter(function(element) {
  283. return ! ("getTransmittedPower" in element);
  284. });
  285.  
  286. var consumption = 0;
  287. if (timeOfDay == DepartmentOfEnergy.DAY) {
  288. for (var i = 0; i < tmpNetElements.length; i++) {
  289. consumption += tmpNetElements[i].consumeDayPower();
  290. }
  291. } else {
  292. for (var i = 0; i < tmpNetElements.length; i++) {
  293. consumption += tmpNetElements[i].consumeNightPower();
  294. }
  295. }
  296.  
  297. return consumption;
  298. }
  299.  
  300. /**
  301.  * Считает баланс (разница между потреблением и остатком) электричества
  302.  *
  303.  * @param {number} consumption - Потребление
  304.  * @param {number} production - Производство
  305.  * @return {number}
  306.  * @throw {Error}
  307.  */
  308. DepartmentOfEnergy.prototype._getBalance = function(consumption, production) {
  309. return production - consumption;
  310. }
  311.  
  312. /**
  313.  * Метод считает колво электричества, которое можно купить и его цену
  314.  *
  315.  * @param {number} demandPower - Нужное кол-во электричество, которое необходимо купить/продать
  316.  * @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)} timeOfDay - Время суток
  317.  * @return {Object} purchase - Заказ на покупку/продажу электричества
  318.  * @return {number} purchase.power - Колво электричества которое возможно купить/продать
  319.  * @return {number} purchase.cost - Стоимость этого колва электричества
  320.  * @return {boolean} purchase.complete - Заказ полный, если куплено/продано столько эл. сколько требовалось
  321.  * @throw {Error}
  322.  */
  323. DepartmentOfEnergy.prototype._getPurchase = function(demandPower) {
  324.  
  325. var instockPower = 0;
  326. var power = 0;
  327. var cost = 0;
  328. var complete = false
  329. var tempPwrLines = this._powerLines;
  330.  
  331. // Выбираем PowerLines
  332. tempPwrLines = this._netElements.filter(function(element) {
  333. return "getPrice" in element;
  334. });
  335.  
  336. // Сортируем линии в порядке возрастания цены за МВт
  337. tempPwrLines.sort(function(a, b){
  338. if (a.getPrice() > b.getPrice()) return 1;
  339. if (a.getPrice() < b.getPrice()) return -1;
  340. });
  341.  
  342. // В выбираем нужное колво энергии у каждой линии
  343. // записывая цену, пока не запоним заявку
  344. for(var i = 0; i < tempPwrLines.length && power < demandPower; i++) {
  345. instockPower = tempPwrLines[i].getTransmittedPower();
  346.  
  347. if (instockPower >= demandPower - power) {
  348. cost += tempPwrLines[i].getPrice() * (demandPower - power);
  349. power += demandPower - power;
  350. } else {
  351. cost += tempPwrLines[i].getPrice() * instockPower;
  352. power += instockPower;
  353. }
  354. };
  355.  
  356. // Проверяем заявку на полноту выполнения
  357. if (power == demandPower) {
  358. complete = true;
  359. }
  360.  
  361. return {'power': power, 'cost': cost, 'complete': complete}
  362. }
  363.  
  364. /**
  365.  * Метод создания отчета
  366.  *
  367.  * @param {(DepartmentOfEnergy.DAY|DepartmentOfEnergy.NIGHT)} timeOfDay - Время суток
  368.  * @return {number} report.consumption - Потребление энергии в мегаваттах
  369.  * @return {number} report.production - Производство энергии в мегаваттах
  370.  * @return {number} report.balance - Баланс (остаток/нехватка) энергии в мегаваттах
  371.  * @return {boolean} report.balanceConverge - Баланс (остаток/нехватка) энергии в мегаваттах
  372.  * @return {number} report.purchasePower - Колво закупаемой энергии в мегаваттах
  373.  * @return {number} report.purchaseCost - Стоимость закупаемой энергии в тугриках
  374.  * @return {number} report.salesPower - Колво продоваемой энергии в мегаваттах
  375.  * @return {number} report.salesCost - Стоимость продоваемой энергии в тугриках
  376.  * @return {(DepartmentOfEnergy.DAY|DepartmentOfEnergy.NIGHT)} report.timeOfDay - Время суток
  377.  * @throw {Error}
  378.  */
  379. DepartmentOfEnergy.prototype.getReport = function(timeOfDay) {
  380. if (timeOfDay != DepartmentOfEnergy.NIGHT &&
  381. timeOfDay != DepartmentOfEnergy.DAY)
  382. {
  383. throw new Error("Argument must be constant DepartmentOfEnergy.DAY or DepartmentOfEnergy.NIGHT, given: " +
  384. typeof(timeOfDay));
  385. }
  386.  
  387. var consumption = this._getConsumption(timeOfDay);
  388. var production = this._getProduction(timeOfDay);
  389. var balance = this._getBalance(consumption, production);
  390. var salesPower = 0;
  391. var salesCost = 0;
  392. var purchasePower = 0;
  393. var purchaseCost = 0;
  394. var balanceConverge = false;
  395.  
  396. // Если баланс отрицательный, то покупаем, если положительный - продаем
  397. if (balance < 0) {
  398. var purchase = this._getPurchase(balance * -1, timeOfDay);
  399. purchasePower = purchase.power;
  400. purchaseCost = purchase.cost;
  401. balanceConverge = purchase.complete;
  402. } else {
  403. var sales = this._getPurchase(balance, timeOfDay);
  404. salesPower = sales.power;
  405. salesCost = sales.cost;
  406. balanceConverge = sales.complete;
  407. }
  408.  
  409. // Собираем все показатели в объект
  410. var report = {
  411. 'timeOfDay': timeOfDay,
  412. 'consumption': consumption,
  413. 'production': production,
  414. 'balance': balance,
  415. 'balanceConverge': balanceConverge,
  416. 'purchasePower': purchasePower,
  417. 'purchaseCost': purchaseCost + ' тугр.',
  418. 'salesPower': salesPower,
  419. 'salesCost': salesCost + ' тугр.'
  420. };
  421.  
  422. // Переводим кВт в МВт
  423. for (var key in report) {
  424. if (typeof(report[key]) == "number") {
  425. report[key] = Util.convertkWToMW(report[key]);
  426. }
  427. };
  428.  
  429. return report;
  430. }
  431.  
  432. /**
  433.  * Клaсс утилит,
  434.  */
  435. function Util() {}
  436.  
  437. /**
  438.  * Метод конвертации кВт в МВт
  439.  *
  440.  * @param {number} - кВт
  441.  * @return {number} - МВт
  442.  */
  443. Util.convertkWToMW = function(kW) {
  444. return kW / 1000;
  445. }
  446.  
  447.  
  448. /*
  449.  ******************************************
  450.  * Запуск программы
  451.  ******************************************
  452.  */
  453.  
  454. // Создаем министерство энергетики
  455. var depOfEnergy = new DepartmentOfEnergy();
  456.  
  457. // Создаем несколько электростанций
  458. depOfEnergy.addNetElement(new PowerStation(2000, 2000, 0, 0));
  459. depOfEnergy.addNetElement(new PowerStation(1000, 1000, 0, 0));
  460.  
  461. // Создаем несколько солнечных панелей
  462. depOfEnergy.addNetElement(new SolarPanel(2000, 0, 0, 0));
  463. depOfEnergy.addNetElement(new SolarPanel(1000, 0, 0, 0));
  464. depOfEnergy.addNetElement(new SolarPanel(3000, 0, 0, 0));
  465. depOfEnergy.addNetElement(new SolarPanel(2000, 0, 0, 0));
  466. depOfEnergy.addNetElement(new SolarPanel(4000, 0, 0, 0));
  467. depOfEnergy.addNetElement(new SolarPanel(4000, 0, 0, 0));
  468.  
  469. // Создаем несколько домов
  470. depOfEnergy.addNetElement(new House(100));
  471. depOfEnergy.addNetElement(new House(120));
  472. depOfEnergy.addNetElement(new House(180));
  473. depOfEnergy.addNetElement(new House(200));
  474. depOfEnergy.addNetElement(new House(320));
  475. depOfEnergy.addNetElement(new House(380));
  476. depOfEnergy.addNetElement(new House(400));
  477. depOfEnergy.addNetElement(new House(400));
  478. depOfEnergy.addNetElement(new House(400));
  479. depOfEnergy.addNetElement(new House(400));
  480. depOfEnergy.addNetElement(new House(400));
  481. depOfEnergy.addNetElement(new House(400));
  482. depOfEnergy.addNetElement(new House(400));
  483.  
  484. // Создаем несколько электростанций
  485. depOfEnergy.addNetElement(new PowerLine(1000, 3));
  486. depOfEnergy.addNetElement(new PowerLine(3000, 5));
  487. depOfEnergy.addNetElement(new PowerLine(1000, 1));
  488.  
  489. // Формируем отчеты и выводим на экран
  490. console.log("Day report: ", depOfEnergy.getReport(DepartmentOfEnergy.DAY));
  491. console.log("Night report: ", depOfEnergy.getReport(DepartmentOfEnergy.NIGHT));
  492.  
Success #stdin #stdout 0.07s 29608KB
stdin
Standard input is empty
stdout
Day report:  { timeOfDay: 'DepartmentOfEnergy.DAY',
  consumption: 16.4,
  production: 19,
  balance: 2.6,
  balanceConverge: true,
  purchasePower: 0,
  purchaseCost: '0 тугр.',
  salesPower: 2.6,
  salesCost: '7000 тугр.' }
Night report:  { timeOfDay: 'DepartmentOfEnergy.NIGHT',
  consumption: 4.1,
  production: 3,
  balance: -1.1,
  balanceConverge: true,
  purchasePower: 1.1,
  purchaseCost: '1300 тугр.',
  salesPower: 0,
  salesCost: '0 тугр.' }