Venciity

Estates JavaScript 100/100

Nov 8th, 2014
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function processEstatesAgencyCommands(commands) {
  2.  
  3.     'use strict';
  4.  
  5.     Object.prototype.extends = function (parent) {
  6.         this.prototype = Object.create(parent.prototype);
  7.         this.prototype.constructor = this;
  8.     }
  9.  
  10.     Object.prototype.validateNonEmptyString = function (value, variableName) {
  11.         if (typeof (value) != 'string' || !value) {
  12.             throw new Error(variableName + " should be non-empty string!");
  13.         }
  14.     }
  15.  
  16.     Object.prototype.validateIntegerRange = function (value, variableName, minValue, maxValue) {
  17.         if (typeof (value) != 'number') {
  18.             throw new Error(variableName + " should be a number!");
  19.         }
  20.  
  21.         if (value !== parseInt(value, 10)) {
  22.             throw new Error(variableName + " should be integer!");
  23.         }
  24.  
  25.         if (value < minValue || value > maxValue) {
  26.             throw new Error(variableName + " should be integer in the range [" + minValue + "..." + maxValue + "]!");
  27.         }
  28.     }
  29.  
  30.     Object.prototype.validateBoolean = function (value, variableName) {
  31.         if (typeof (value) != 'boolean') {
  32.             throw new Error(variableName + " should be a boolean value!");
  33.         }
  34.     }
  35.  
  36.     Object.prototype.validateNonEmptyObject = function (value, className, variableName) {
  37.         if (! (value instanceof className)) {
  38.             throw new Error(variableName + " should be non-empty " + className.prototype.constructor.name + "!");
  39.         }
  40.     }
  41.  
  42.     var Estate = (function () {
  43.  
  44.         var MIN_AREA = 1;
  45.         var MAX_AREA = 10000;
  46.  
  47.         function Estate(name, area, location, isFurnitured) {
  48.  
  49.             if (this.constructor === Estate) {
  50.                 throw new Error("Can't instantiate abstract class Estate!");
  51.             }
  52.  
  53.             this.setName(name);
  54.             this.setArea(area);
  55.             this.setLocation(location);
  56.             this.setIsFurnitured(isFurnitured);
  57.         }
  58.  
  59.         Estate.prototype.getName = function () {
  60.             return this._name;
  61.         }
  62.  
  63.         Estate.prototype.setName = function (name) {
  64.             this.validateNonEmptyString(name, "name");
  65.             this._name = name;
  66.         }
  67.  
  68.         Estate.prototype.getArea = function () {
  69.             return this._area;
  70.         }
  71.  
  72.         Estate.prototype.setArea = function (area) {
  73.             this.validateIntegerRange(area, "area", MIN_AREA, MAX_AREA);
  74.             this._area = area;
  75.         }
  76.  
  77.         Estate.prototype.getLocation = function () {
  78.             return this._location;
  79.         }
  80.  
  81.         Estate.prototype.setLocation = function (location) {
  82.             this.validateNonEmptyString(location, "location");
  83.             this._location = location;
  84.         }
  85.  
  86.         Estate.prototype.getIsFurnitured = function () {
  87.             return this._isFurnitured;
  88.         }
  89.  
  90.         Estate.prototype.setIsFurnitured = function (isFurnitured) {
  91.             this.validateBoolean(isFurnitured, "isFurnitured");
  92.             this._isFurnitured = isFurnitured;
  93.         }
  94.  
  95.         // House: Name = houseBankya, Area = 206, Location = Bankya, Furnitured = Yes, Floors: 3
  96.         Estate.prototype.toString = function () {
  97.             var furitured = this.getIsFurnitured() ? "Yes" : "No";
  98.             return this.constructor.name + ": Name = " + this.getName() +
  99.                 ", Area = " + this.getArea() +
  100.                 ", Location = " + this.getLocation() +
  101.                 ", Furnitured = " + furitured;
  102.         }
  103.  
  104.         return Estate;
  105.     }());
  106.  
  107.  
  108.     var BuildingEstate = (function () {
  109.  
  110.         var MIN_ROOMS = 0;
  111.         var MAX_ROOMS = 100;
  112.  
  113.         function BuildingEstate(name, area, location, isFurnitured, rooms, hasElevator) {
  114.  
  115.             if (this.constructor === BuildingEstate) {
  116.                 throw new Error("Can't instantiate abstract class BuildingEstate!");
  117.             }
  118.  
  119.             Estate.call(this, name, area, location, isFurnitured);
  120.             this.setRooms(rooms);
  121.             this.setHasElevator(hasElevator);
  122.         }
  123.  
  124.         BuildingEstate.extends(Estate);
  125.  
  126.         BuildingEstate.prototype.getRooms = function () {
  127.             return this._rooms;
  128.         }
  129.  
  130.         BuildingEstate.prototype.setRooms = function (rooms) {
  131.             this.validateIntegerRange(rooms, "rooms", MIN_ROOMS, MAX_ROOMS);
  132.             this._rooms = rooms;
  133.         }
  134.  
  135.         BuildingEstate.prototype.getHasElevator = function () {
  136.             return this._hasElevator;
  137.         }
  138.  
  139.         BuildingEstate.prototype.setHasElevator = function (hasElevator) {
  140.             this.validateBoolean(hasElevator, "hasElevator");
  141.             this._hasElevator = hasElevator;
  142.         }
  143.  
  144.  
  145.         // Apartment: Name = aptLozenec24, Area = 150, Location = Sofia, Furnitured = Yes, Rooms: 4, Elevator: Yes
  146.         BuildingEstate.prototype.toString = function () {
  147.             var elevator = this.getHasElevator() ? "Yes" : "No";
  148.             return Estate.prototype.toString.call(this) +
  149.                 ", Rooms: " + this.getRooms() +
  150.                 ", Elevator: " + elevator;
  151.         }
  152.  
  153.         return BuildingEstate;
  154.     }());
  155.  
  156.  
  157.     var Apartment = (function () {
  158.         function Apartment(name, area, location, isFurnitured, rooms, hasElevator) {
  159.             BuildingEstate.call(this, name, area, location, isFurnitured, rooms, hasElevator);
  160.         }
  161.  
  162.         Apartment.extends(BuildingEstate);
  163.  
  164.         return Apartment;
  165.     }());
  166.  
  167.  
  168.     var Office = (function () {
  169.         function Office(name, area, location, isFurnitured, rooms, hasElevator) {
  170.             BuildingEstate.call(this, name, area, location, isFurnitured, rooms, hasElevator);
  171.         }
  172.  
  173.         Office.extends(BuildingEstate);
  174.  
  175.         return Office;
  176.     }());
  177.  
  178.  
  179.     var House = (function () {
  180.  
  181.         var MIN_FLOORS = 1;
  182.         var MAX_FLOORS = 10;
  183.  
  184.         function House(name, area, location, isFurnitured, floors) {
  185.             Estate.call(this, name, area, location, isFurnitured);
  186.             this.setFloors(floors);
  187.         }
  188.  
  189.         House.extends(Estate);
  190.  
  191.         House.prototype.getFloors = function () {
  192.             return this._floors;
  193.         }
  194.  
  195.         House.prototype.setFloors = function (floors) {
  196.             this.validateIntegerRange(floors, "floors", MIN_FLOORS, MAX_FLOORS);
  197.             this._floors = floors;
  198.         }
  199.  
  200.         // House: Name = houseBankya, Area = 206, Location = Bankya, Furnitured = Yes, Floors: 3
  201.         House.prototype.toString = function () {
  202.             return Estate.prototype.toString.call(this) +
  203.                 ", Floors: " + this.getFloors();
  204.         }
  205.  
  206.         return House;
  207.  
  208.     }());
  209.  
  210.  
  211.     var Garage = (function () {
  212.  
  213.         var MIN_WIDTH_HEIGH = 1;
  214.         var MAX_WIDTH_HEIGH = 500;
  215.  
  216.         function Garage(name, area, location, isFurnitured, width, height) {
  217.             Estate.call(this, name, area, location, isFurnitured);
  218.             this.setWidth(width);
  219.             this.setHeigth(height);
  220.  
  221.         }
  222.  
  223.         Garage.extends(Estate);
  224.  
  225.         Garage.prototype.getWidth = function () {
  226.             return this._width;
  227.         }
  228.  
  229.         Garage.prototype.setWidth = function (width) {
  230.             this.validateIntegerRange(width, "width", MIN_WIDTH_HEIGH, MAX_WIDTH_HEIGH);
  231.             this._width = width;
  232.         }
  233.  
  234.         Garage.prototype.getHeigth = function () {
  235.             return this._height;
  236.         }
  237.  
  238.         Garage.prototype.setHeigth = function (height) {
  239.             this.validateIntegerRange(height, "height", MIN_WIDTH_HEIGH, MAX_WIDTH_HEIGH);
  240.             this._height = height;
  241.         }
  242.  
  243.         // Garage: Name = garageLozenec, Area = 18, Location = Sofia, Furnitured = No, Width: 3, Height: 6
  244.         Garage.prototype.toString = function () {
  245.             return Estate.prototype.toString.call(this) +
  246.                 ", Width: " + this.getWidth() +
  247.                 ", Height: " + this.getHeigth();
  248.         }
  249.  
  250.         return Garage;
  251.  
  252.     }());
  253.  
  254.  
  255.     var Offer = (function () {
  256.  
  257.         var MIN_PRICE = 0;
  258.         var MAX_PRICE = Number.MAX_VALUE;
  259.  
  260.         function Offer(estate, price) {
  261.  
  262.             if (this.constructor === Offer) {
  263.                 throw new Error("Can't instantiate abstract class Offer!");
  264.             }
  265.  
  266.             this.setEstate(estate);
  267.             this.setPrice(price);
  268.         }
  269.  
  270.         Offer.prototype.getEstate = function () {
  271.             return this._estate;
  272.         }
  273.  
  274.         Offer.prototype.setEstate = function (estate) {
  275.             this.validateNonEmptyObject(estate, Estate, "estate");
  276.  
  277.             this._estate = estate;
  278.         }
  279.  
  280.         Offer.prototype.getPrice = function () {
  281.             return this._price;
  282.         }
  283.  
  284.         Offer.prototype.setPrice = function (price) {
  285.             this.validateIntegerRange(price, "price", MIN_PRICE, MAX_PRICE);
  286.             this._price = price;
  287.         }
  288.  
  289.         // Rent: Estate = aptLozenec24, Location = Sofia, Price = 750
  290.         Offer.prototype.toString = function () {
  291.             return "Estate = " + this.getEstate().getName() +
  292.                 ", Location = " + this.getEstate().getLocation() +
  293.                 ", Price = " + this.getPrice();
  294.         }
  295.  
  296.         return Offer;
  297.     }());
  298.  
  299.  
  300.     var RentOffer = (function () {
  301.         function RentOffer(estate, price) {
  302.             Offer.call(this, estate, price);
  303.         }
  304.  
  305.         RentOffer.extends(Offer);
  306.  
  307.         RentOffer.prototype.toString = function () {
  308.             return "Rent: " + Offer.prototype.toString.call(this);
  309.         }
  310.  
  311.         return RentOffer;
  312.     }());
  313.  
  314.  
  315.     var SaleOffer = (function () {
  316.         function SaleOffer(estate, price) {
  317.             Offer.call(this, estate, price);
  318.         }
  319.  
  320.         SaleOffer.extends(Offer);
  321.  
  322.         SaleOffer.prototype.toString = function () {
  323.             return "Sale: " + Offer.prototype.toString.call(this);
  324.         }
  325.  
  326.         return SaleOffer;
  327.     }());
  328.  
  329.  
  330.     var EstatesEngine = (function () {
  331.         var _estates;
  332.         var _uniqueEstateNames;
  333.         var _offers;
  334.  
  335.         function initialize() {
  336.             _estates = [];
  337.             _uniqueEstateNames = {};
  338.             _offers = [];
  339.         }
  340.  
  341.         function executeCommand(command) {
  342.             var cmdParts = command.split(' ');
  343.             var cmdName = cmdParts[0];
  344.             var cmdArgs = cmdParts.splice(1);
  345.             switch (cmdName) {
  346.                 case 'create':
  347.                     return executeCreateCommand(cmdArgs);
  348.                 case 'status':
  349.                     return executeStatusCommand();
  350.                 case 'find-sales-by-location':
  351.                     return executeFindSalesByLocationCommand(cmdArgs[0]);
  352.                 case 'find-rents-by-location':
  353.                     return executeFindRentsByLocationCommand(cmdArgs[0]);
  354.                 case 'find-rents-by-price':
  355.                     return executeFindRentsByPriceCommand(Number(cmdArgs[0]), Number(cmdArgs[1]));
  356.                 default:
  357.                     throw new Error('Unknown command: ' + cmdName);
  358.             }
  359.         }
  360.  
  361.         function executeCreateCommand(cmdArgs) {
  362.             var objType = cmdArgs[0];
  363.             switch (objType) {
  364.                 case 'Apartment':
  365.                     var apartment = new Apartment(cmdArgs[1], Number(cmdArgs[2]), cmdArgs[3],
  366.                         parseBoolean(cmdArgs[4]), Number(cmdArgs[5]), parseBoolean(cmdArgs[6]));
  367.                     addEstate(apartment);
  368.                     break;
  369.                 case 'Office':
  370.                     var office = new Office(cmdArgs[1], Number(cmdArgs[2]), cmdArgs[3],
  371.                         parseBoolean(cmdArgs[4]), Number(cmdArgs[5]), parseBoolean(cmdArgs[6]));
  372.                     addEstate(office);
  373.                     break;
  374.                 case 'House':
  375.                     var house = new House(cmdArgs[1], Number(cmdArgs[2]), cmdArgs[3],
  376.                         parseBoolean(cmdArgs[4]), Number(cmdArgs[5]));
  377.                     addEstate(house);
  378.                     break;
  379.                 case 'Garage':
  380.                     var garage = new Garage(cmdArgs[1], Number(cmdArgs[2]), cmdArgs[3],
  381.                         parseBoolean(cmdArgs[4]), Number(cmdArgs[5]), Number(cmdArgs[6]));
  382.                     addEstate(garage);
  383.                     break;
  384.                 case 'RentOffer':
  385.                     var estate = findEstateByName(cmdArgs[1]);
  386.                     var rentOffer = new RentOffer(estate, Number(cmdArgs[2]));
  387.                     addOffer(rentOffer);
  388.                     break;
  389.                 case 'SaleOffer':
  390.                     estate = findEstateByName(cmdArgs[1]);
  391.                     var saleOffer = new SaleOffer(estate, Number(cmdArgs[2]));
  392.                     addOffer(saleOffer);
  393.                     break;
  394.                 default:
  395.                     throw new Error('Unknown object to create: ' + objType);
  396.             }
  397.             return objType + ' created.';
  398.         }
  399.  
  400.         function parseBoolean(value) {
  401.             switch (value) {
  402.                 case "true":
  403.                     return true;
  404.                 case "false":
  405.                     return false;
  406.                 default:
  407.                     throw new Error("Invalid boolean value: " + value);
  408.             }
  409.         }
  410.  
  411.         function findEstateByName(estateName) {
  412.             for (var i = 0; i < _estates.length; i++) {
  413.                 if (_estates[i].getName() == estateName) {
  414.                     return _estates[i];
  415.                 }
  416.             }
  417.             return undefined;
  418.         }
  419.  
  420.         function addEstate(estate) {
  421.             if (_uniqueEstateNames[estate.getName()]) {
  422.                 throw new Error('Duplicated estate name: ' + estate.getName());
  423.             }
  424.             _uniqueEstateNames[estate.getName()] = true;
  425.             _estates.push(estate);
  426.         }
  427.  
  428.         function addOffer(offer) {
  429.             _offers.push(offer);
  430.         }
  431.  
  432.         function executeStatusCommand() {
  433.             var result = '', i;
  434.             if (_estates.length > 0) {
  435.                 result += 'Estates:\n';
  436.                 for (i = 0; i < _estates.length; i++) {
  437.                     result += "  " + _estates[i].toString() + '\n';
  438.                 }
  439.             } else {
  440.                 result += 'No estates\n';
  441.             }
  442.  
  443.             if (_offers.length > 0) {
  444.                 result += 'Offers:\n';
  445.                 for (i = 0; i < _offers.length; i++) {
  446.                     result += "  " + _offers[i].toString() + '\n';
  447.                 }
  448.             } else {
  449.                 result += 'No offers\n';
  450.             }
  451.  
  452.             return result.trim();
  453.         }
  454.  
  455.         function executeFindSalesByLocationCommand(location) {
  456.             return executeFindOffersByLocationCommand(location, SaleOffer);
  457.         }
  458.  
  459.         function executeFindRentsByLocationCommand(location) {
  460.             return executeFindOffersByLocationCommand(location, RentOffer);
  461.         }
  462.  
  463.         function executeFindOffersByLocationCommand(location, offerType) {
  464.             if (!location) {
  465.                 throw new Error("Location cannot be empty.");
  466.             }
  467.  
  468.             var selectedOffers = _offers.filter(function (offer) {
  469.                 return offer.getEstate().getLocation() === location &&
  470.                     offer instanceof offerType;
  471.             });
  472.             selectedOffers.sort(function (a, b) {
  473.                 return a.getEstate().getName().localeCompare(b.getEstate().getName());
  474.             });
  475.  
  476.             return formatQueryResults(selectedOffers);
  477.         }
  478.  
  479.         function executeFindRentsByPriceCommand(minPrice, maxPrice) {
  480.             Object.prototype.validateIntegerRange(minPrice, "minPrice", 0, Number.MAX_VALUE);
  481.             Object.prototype.validateIntegerRange(maxPrice, "maxPrice", 0, Number.MAX_VALUE);
  482.  
  483.             var selectedOffers = _offers.filter(function (offer) {
  484.                 return offer.getPrice() >= minPrice && offer.getPrice() <= maxPrice && offer instanceof RentOffer;
  485.             });
  486.             selectedOffers.sort(function (a, b) {
  487.                 var result = a.getPrice() - b.getPrice();
  488.                 if (result == 0) {
  489.                     result = a.getEstate().getName().localeCompare(b.getEstate().getName());
  490.                 }
  491.  
  492.                 return result;
  493.             });
  494.  
  495.             return formatQueryResults(selectedOffers);
  496.         }
  497.  
  498.         function formatQueryResults(offers) {
  499.             var result = '';
  500.             if (offers.length == 0) {
  501.                 result += 'No Results\n';
  502.             } else {
  503.                 result += 'Query Results:\n';
  504.                 for (var i = 0; i < offers.length; i++) {
  505.                     var offer = offers[i];
  506.                     result += '  [Estate: ' + offer.getEstate().getName() +
  507.                         ', Location: ' + offer.getEstate().getLocation() +
  508.                         ', Price: ' + offer.getPrice() + ']\n';
  509.                 }
  510.             }
  511.             return result.trim();
  512.         }
  513.  
  514.         return {
  515.             initialize: initialize,
  516.             executeCommand: executeCommand
  517.         };
  518.     }());
  519.  
  520.  
  521.     // Process the input commands and return the results
  522.     var results = '';
  523.     EstatesEngine.initialize();
  524.     commands.forEach(function (cmd) {
  525.         if (cmd != '') {
  526.             try {
  527.                 var cmdResult = EstatesEngine.executeCommand(cmd);
  528.                 results += cmdResult + '\n';
  529.             } catch (err) {
  530.                 // console.log(err);
  531.                 results += 'Invalid command.\n';
  532.             }
  533.         }
  534.     });
  535.     return results.trim();
  536.  
  537. }
  538.  
  539. // ------------------------------------------------------------
  540. // Read the input from the console as array and process it
  541. // Remove all below code before submitting to the judge system!
  542. // ------------------------------------------------------------
  543.  
  544. (function () {
  545.     var arr = [];
  546.     if (typeof (require) == 'function') {
  547.         // We are in node.js --> read the console input and process it
  548.         require('readline').createInterface({
  549.             input: process.stdin,
  550.             output: process.stdout
  551.         }).on('line', function (line) {
  552.             arr.push(line);
  553.         }).on('close', function () {
  554.             console.log(processEstatesAgencyCommands(arr));
  555.         });
  556.     }
  557. })();
Advertisement
Add Comment
Please, Sign In to add comment