Venciity

Restaurant Manager 100/100 with validation

Nov 11th, 2014
286
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function processRestaurantManagerCommands(commands) {
  2.     'use strict';
  3.  
  4.     Object.prototype.extends = function (parent) {
  5.         this.prototype = Object.create(parent.prototype);
  6.         this.prototype.constructor = this;
  7.     }
  8.  
  9.     Object.prototype.validateNonEmptyString = function (value, variableName) {
  10.         if (typeof (value) != 'string' || !value) {
  11.             throw new Error(variableName + " should be non-empty string!");
  12.         }
  13.     }
  14.  
  15.     Object.prototype.validatePositiveNumber = function (value, variableName) {
  16.         if (value < 0) {
  17.             throw new Error(variableName + " should be positive!");
  18.         }
  19.     }
  20.  
  21.     var RestaurantEngine = (function () {
  22.         var _restaurants, _recipes;
  23.  
  24.         function initialize() {
  25.             _restaurants = [];
  26.             _recipes = [];
  27.         }
  28.  
  29.         // ---------- Restaurant ----------
  30.         var Restaurant = (function () {
  31.             function Restaurant(name, location) {
  32.                 this.setName(name);
  33.                 this.setLocation(location);
  34.                 this._recipes = [];
  35.             }
  36.  
  37.             Restaurant.prototype.getName = function () {
  38.                 return this._name;
  39.             }
  40.  
  41.             Restaurant.prototype.setName = function (name) {
  42.                 this.validateNonEmptyString(name, "name");
  43.                 this._name = name;
  44.             }
  45.  
  46.             Restaurant.prototype.getLocation = function () {
  47.                 return this._location;
  48.             }
  49.  
  50.             Restaurant.prototype.setLocation = function (location) {
  51.                 this.validateNonEmptyString(location, "location");
  52.                 this._location = location;
  53.             }
  54.  
  55.             Restaurant.prototype.addRecipe = function (recipe) {
  56.                 this._recipes.push(recipe);
  57.             }
  58.  
  59.             Restaurant.prototype.removeRecipe = function (recipe) {
  60.                 var index = this._recipes.indexOf(recipe);
  61.                 this._recipes.splice(index, 1);
  62.             }
  63.  
  64.             Restaurant.prototype.printRestaurantMenu = function () {
  65.                 var nameString = "***** " + this.getName() + " - " + this.getLocation() + " *****\n";
  66.                 var result = nameString;
  67.  
  68.                 if (this._recipes.length === 0) {
  69.                     var noRecipesString = "No recipes... yet\n";
  70.                     return nameString + noRecipesString;
  71.                 }
  72.  
  73.                 // ----- drinks -----
  74.                 var drinks = this._recipes.filter(function (recipe) {
  75.                     return recipe instanceof Drink;
  76.                 });
  77.                 drinks.sort(function (a, b) {
  78.                     return a.getName().localeCompare(b.getName());
  79.                 });
  80.  
  81.                 // ----- salads -----
  82.                 var salads = this._recipes.filter(function (recipe) {
  83.                     return recipe instanceof Salad;
  84.                 });
  85.                 salads.sort(function (a, b) {
  86.                     return a.getName().localeCompare(b.getName());
  87.                 });
  88.  
  89.                 // ----- mainCourses -----
  90.                 var mainCourses = this._recipes.filter(function (recipe) {
  91.                     return recipe instanceof MainCourse;
  92.                 });
  93.                 mainCourses.sort(function (a, b) {
  94.                     return a.getName().localeCompare(b.getName());
  95.                 });
  96.  
  97.                 // ----- desserts -----
  98.                 var desserts = this._recipes.filter(function (recipe) {
  99.                     return recipe instanceof Dessert;
  100.                 });
  101.                 desserts.sort(function (a, b) {
  102.                     return a.getName().localeCompare(b.getName());
  103.                 });
  104.  
  105.                 if (drinks.length > 0) {
  106.                     var drinksString = "~~~~~ DRINKS ~~~~~\n";
  107.                     result += drinksString;
  108.  
  109.                     drinks.forEach(function (drink) {
  110.                         result += drink.toString();
  111.                     });
  112.                 }
  113.  
  114.                 if (salads.length > 0) {
  115.                     var saladsString = "~~~~~ SALADS ~~~~~\n";
  116.                     result += saladsString;
  117.  
  118.                     salads.forEach(function (salad) {
  119.                         result += salad.toString();
  120.                     });
  121.                 }
  122.  
  123.                 if (mainCourses.length > 0) {
  124.                     var mainCoursesString = "~~~~~ MAIN COURSES ~~~~~\n";
  125.                     result += mainCoursesString;
  126.  
  127.                     mainCourses.forEach(function (mainCourse) {
  128.                         result += mainCourse.toString();
  129.                     });
  130.                 }
  131.  
  132.                 if (desserts.length > 0) {
  133.                     var dessertsString = "~~~~~ DESSERTS ~~~~~\n";
  134.                     result += dessertsString;
  135.  
  136.                     desserts.forEach(function (dessert) {
  137.                         result += dessert.toString();
  138.                     });
  139.                 }
  140.  
  141.                 return result;
  142.             }
  143.  
  144.             return Restaurant;
  145.         }());
  146.  
  147.         // ---------- Recipe ----------
  148.         var Recipe = (function () {
  149.             function Recipe(name, price, calories, quantity, timeToPrepare) {
  150.  
  151.                 if (this.constructor === Recipe) {
  152.                     throw new Error("Can't instantiate abstract class Recipe!");
  153.                 }
  154.  
  155.                 this.setName(name);
  156.                 this.setPrice(price);
  157.                 this.setCalories(calories);
  158.                 this.setQuantity(quantity);
  159.                 this.setTimeToPrepare(timeToPrepare);
  160.             }
  161.  
  162.             Recipe.prototype.getName = function () {
  163.                 return this._name;
  164.             };
  165.  
  166.             Recipe.prototype.setName = function (name) {
  167.                 this.validateNonEmptyString(name, "name");
  168.                 this._name = name;
  169.             };
  170.  
  171.             Recipe.prototype.getPrice = function () {
  172.                 return this._price;
  173.             };
  174.  
  175.             Recipe.prototype.setPrice = function (price) {
  176.                 this.validatePositiveNumber(price, "price");
  177.                 this._price = price;
  178.             };
  179.  
  180.             Recipe.prototype.getCalories = function () {
  181.                 return this._calories;
  182.             };
  183.  
  184.             Recipe.prototype.setCalories = function (calories) {
  185.                 this.validatePositiveNumber(calories, "calories");
  186.                 if (this.constructor === Drink) {
  187.                     if (calories > 100) {
  188.                         throw new Error("The calories must not be greater than 100");
  189.                     }
  190.                 }
  191.  
  192.                 this._calories = calories;
  193.             };
  194.  
  195.             Recipe.prototype.getQuantity = function () {
  196.                 return this._quantity;
  197.             };
  198.  
  199.             Recipe.prototype.setQuantity = function (quantity) {
  200.                 this.validatePositiveNumber(quantity, "quantity");
  201.                 this._quantity = quantity;
  202.             };
  203.  
  204.             Recipe.prototype.getTimeToPrepare = function () {
  205.                 return this._timeToPrepare;
  206.             };
  207.  
  208.             Recipe.prototype.setTimeToPrepare = function (timeToPrepare) {
  209.                 this.validatePositiveNumber(timeToPrepare, "timeToPrepare");
  210.                 if (this.constructor === Drink) {
  211.                     if (timeToPrepare > 20) {
  212.                         throw new Error("The time to prepare must not be greater than 20 minutes");
  213.                     }
  214.                 }
  215.  
  216.                 this._timeToPrepare = timeToPrepare;
  217.             };
  218.  
  219.             Recipe.prototype.toString = function () {
  220.                 var unit;
  221.                 if (this instanceof Drink) {
  222.                     unit = "ml";
  223.                 } else if (this instanceof Meal) {
  224.                     unit = "g";
  225.                 }
  226.  
  227.                 return "==  " + this.getName() + " == $" + this.getPrice().toFixed(2) + "\n" +
  228.                        "Per serving: " + this.getQuantity() + " " + unit + ", " + this.getCalories() + " kcal" + "\n" +
  229.                        "Ready in " + this.getTimeToPrepare() + " minutes";
  230.             }
  231.  
  232.             return Recipe;
  233.         }());
  234.  
  235.         // ---------- Drink ----------
  236.         var Drink = (function () {
  237.  
  238.             function Drink(name, price, calories, quantity, timeToPrepare, isCarbonated) {
  239.                 Recipe.call(this, name, price, calories, quantity, timeToPrepare);
  240.                 this.setIsCarbonated(isCarbonated);
  241.             }
  242.  
  243.             Drink.extends(Recipe);
  244.  
  245.             Drink.prototype.getIsCarbonated = function () {
  246.                 return this._isCarbonated;
  247.             }
  248.  
  249.             Drink.prototype.setIsCarbonated = function (isCarbonated) {
  250.                 // TODO: ADD VALIDATION
  251.                 this._isCarbonated = isCarbonated;
  252.             }
  253.  
  254.             Drink.prototype.toString = function () {
  255.                 var carbonated = this.getIsCarbonated() ? "yes" : "no";
  256.  
  257.                 return Recipe.prototype.toString.call(this) + "\n" +
  258.                     "Carbonated: " + carbonated + "\n";
  259.             }
  260.  
  261.             return Drink;
  262.         }());
  263.  
  264.         // ---------- Meal ----------
  265.         var Meal = (function () {
  266.  
  267.             function Meal(name, price, calories, quantity, timeToPrepare, isVegan) {
  268.  
  269.                 if (this.constructor === Meal) {
  270.                     throw new Error("Can't instantiate abstract class Meal!");
  271.                 }
  272.  
  273.                 Recipe.call(this, name, price, calories, quantity, timeToPrepare);
  274.                 this.setIsVegan(isVegan);
  275.             }
  276.  
  277.             Meal.extends(Recipe);
  278.  
  279.             Meal.prototype.getIsVegan = function () {
  280.                 return this._isVegan;
  281.             }
  282.  
  283.             Meal.prototype.setIsVegan = function (isVegan) {
  284.                 // TODO: ADD VALIDATION
  285.                 this._isVegan = isVegan;
  286.             }
  287.  
  288.             Meal.prototype.toggleVegan = function () {
  289.                 this._isVegan = !this._isVegan;
  290.             }
  291.  
  292.             Meal.prototype.toString = function () {
  293.                 var vegan = this.getIsVegan() ? "[VEGAN] " : "";
  294.  
  295.                 return vegan + Recipe.prototype.toString.call(this);
  296.             }
  297.  
  298.             return Meal;
  299.         }());
  300.  
  301.         // ---------- Dessert ----------
  302.         var Dessert = (function () {
  303.            
  304.             function Dessert(name, price, calories, quantity, timeToPrepare, isVegan) {
  305.                 Meal.call(this, name, price, calories, quantity, timeToPrepare, isVegan);
  306.                 this._withSugar = true;
  307.             }
  308.  
  309.             Dessert.extends(Meal);
  310.  
  311.             Dessert.prototype.toggleSugar = function () {
  312.                 this._withSugar = !this._withSugar;
  313.             }
  314.  
  315.             Dessert.prototype.toString = function () {
  316.                 var sugar = this._withSugar ? "" : "[NO SUGAR] ";
  317.  
  318.                 return sugar + Meal.prototype.toString.call(this) + "\n";
  319.             }
  320.  
  321.             return Dessert;
  322.         }());
  323.  
  324.         // ---------- MainCourse ----------
  325.         var MainCourse = (function () {
  326.            
  327.             function MainCourse(name, price, calories, quantity, timeToPrepare, isVegan, type) {
  328.                 Meal.call(this, name, price, calories, quantity, timeToPrepare, isVegan);
  329.                 this.setType(type);
  330.             }
  331.  
  332.             MainCourse.extends(Meal);
  333.  
  334.             MainCourse.prototype.getType = function () {
  335.                 return this._type;
  336.             }
  337.  
  338.             MainCourse.prototype.setType = function (type) {
  339.                 // TODO: ADD VALIDATION
  340.                 this._type = type;
  341.             }
  342.  
  343.             MainCourse.prototype.toString = function () {
  344.                 return Meal.prototype.toString.call(this) + "\n" +
  345.                        "Type: " + this.getType() + "\n";
  346.             }
  347.  
  348.             return MainCourse;
  349.         }());
  350.  
  351.         // ---------- Salad ----------
  352.         var Salad = (function () {
  353.            
  354.             function Salad(name, price, calories, quantity, timeToPrepare, containsPasta) {
  355.                 Meal.call(this, name, price, calories, quantity, timeToPrepare, true);
  356.                 this.setContainsPasta(containsPasta);
  357.             }
  358.  
  359.             Salad.extends(Meal);
  360.  
  361.             Salad.prototype.getContainsPasta = function () {
  362.                 return this._containsPasta;
  363.             }
  364.  
  365.             Salad.prototype.setContainsPasta = function (containsPasta) {
  366.                 this._containsPasta = containsPasta;
  367.             }
  368.  
  369.             Salad.prototype.toString = function () {
  370.                 var isContainsPasta = this.getContainsPasta() ? "yes" : "no";
  371.  
  372.                 return Meal.prototype.toString.call(this) + "\n" +
  373.                     "Contains pasta: " + isContainsPasta + "\n";
  374.             }
  375.  
  376.             return Salad;
  377.         }());
  378.  
  379.         var Command = (function () {
  380.  
  381.             function Command(commandLine) {
  382.                 this._params = new Array();
  383.                 this.translateCommand(commandLine);
  384.             }
  385.  
  386.             Command.prototype.translateCommand = function (commandLine) {
  387.                 var self, paramsBeginning, name, parametersKeysAndValues;
  388.                 self = this;
  389.                 paramsBeginning = commandLine.indexOf("(");
  390.  
  391.                 this._name = commandLine.substring(0, paramsBeginning);
  392.                 name = commandLine.substring(0, paramsBeginning);
  393.                 parametersKeysAndValues = commandLine
  394.                     .substring(paramsBeginning + 1, commandLine.length - 1)
  395.                     .split(";")
  396.                     .filter(function (e) { return true });
  397.  
  398.                 parametersKeysAndValues.forEach(function (p) {
  399.                     var split = p
  400.                         .split("=")
  401.                         .filter(function (e) { return true; });
  402.                     self._params[split[0]] = split[1];
  403.                 });
  404.             }
  405.  
  406.             return Command;
  407.         }());
  408.  
  409.         function createRestaurant(name, location) {
  410.             _restaurants[name] = new Restaurant(name, location);
  411.             return "Restaurant " + name + " created\n";
  412.         }
  413.  
  414.         function createDrink(name, price, calories, quantity, timeToPrepare, isCarbonated) {
  415.             _recipes[name] = new Drink(name, price, calories, quantity, timeToPrepare, isCarbonated);
  416.             return "Recipe " + name + " created\n";
  417.         }
  418.  
  419.         function createSalad(name, price, calories, quantity, timeToPrepare, containsPasta) {
  420.             _recipes[name] = new Salad(name, price, calories, quantity, timeToPrepare, containsPasta);
  421.             return "Recipe " + name + " created\n";
  422.         }
  423.  
  424.         function createMainCourse(name, price, calories, quantity, timeToPrepare, isVegan, type) {
  425.             _recipes[name] = new MainCourse(name, price, calories, quantity, timeToPrepare, isVegan, type);
  426.             return "Recipe " + name + " created\n";
  427.         }
  428.  
  429.         function createDessert(name, price, calories, quantity, timeToPrepare, isVegan) {
  430.             _recipes[name] = new Dessert(name, price, calories, quantity, timeToPrepare, isVegan);
  431.             return "Recipe " + name + " created\n";
  432.         }
  433.  
  434.         function toggleSugar(name) {
  435.             var recipe;
  436.  
  437.             if (!_recipes.hasOwnProperty(name)) {
  438.                 throw new Error("The recipe " + name + " does not exist");
  439.             }
  440.             recipe = _recipes[name];
  441.  
  442.             if (recipe instanceof Dessert) {
  443.                 recipe.toggleSugar();
  444.                 return "Command ToggleSugar executed successfully. New value: " + recipe._withSugar.toString().toLowerCase() + "\n";
  445.             } else {
  446.                 return "The command ToggleSugar is not applicable to recipe " + name + "\n";
  447.             }
  448.         }
  449.  
  450.         function toggleVegan(name) {
  451.             var recipe;
  452.  
  453.             if (!_recipes.hasOwnProperty(name)) {
  454.                 throw new Error("The recipe " + name + " does not exist");
  455.             }
  456.  
  457.             recipe = _recipes[name];
  458.             if (recipe instanceof Meal) {
  459.                 recipe.toggleVegan();
  460.                 return "Command ToggleVegan executed successfully. New value: " +
  461.                     recipe._isVegan.toString().toLowerCase() + "\n";
  462.             } else {
  463.                 return "The command ToggleVegan is not applicable to recipe " + name + "\n";
  464.             }
  465.         }
  466.  
  467.         function printRestaurantMenu(name) {
  468.             var restaurant;
  469.  
  470.             if (!_restaurants.hasOwnProperty(name)) {
  471.                 throw new Error("The restaurant " + name + " does not exist");
  472.             }
  473.  
  474.             restaurant = _restaurants[name];
  475.             return restaurant.printRestaurantMenu();
  476.         }
  477.  
  478.         function addRecipeToRestaurant(restaurantName, recipeName) {
  479.             var restaurant, recipe;
  480.  
  481.             if (!_restaurants.hasOwnProperty(restaurantName)) {
  482.                 throw new Error("The restaurant " + restaurantName + " does not exist");
  483.             }
  484.             if (!_recipes.hasOwnProperty(recipeName)) {
  485.                 throw new Error("The recipe " + recipeName + " does not exist");
  486.             }
  487.  
  488.             restaurant = _restaurants[restaurantName];
  489.             recipe = _recipes[recipeName];
  490.             restaurant.addRecipe(recipe);
  491.             return "Recipe " + recipeName + " successfully added to restaurant " + restaurantName + "\n";
  492.         }
  493.  
  494.         function removeRecipeFromRestaurant(restaurantName, recipeName) {
  495.             var restaurant, recipe;
  496.  
  497.             if (!_recipes.hasOwnProperty(recipeName)) {
  498.                 throw new Error("The recipe " + recipeName + " does not exist");
  499.             }
  500.             if (!_restaurants.hasOwnProperty(restaurantName)) {
  501.                 throw new Error("The restaurant " + restaurantName + " does not exist");
  502.             }
  503.  
  504.             restaurant = _restaurants[restaurantName];
  505.             recipe = _recipes[recipeName];
  506.             restaurant.removeRecipe(recipe);
  507.             return "Recipe " + recipeName + " successfully removed from restaurant " + restaurantName + "\n";
  508.         }
  509.  
  510.         function executeCommand(commandLine) {
  511.             var cmd, params, result;
  512.             cmd = new Command(commandLine);
  513.             params = cmd._params;
  514.  
  515.             switch (cmd._name) {
  516.                 case 'CreateRestaurant':
  517.                     result = createRestaurant(params["name"], params["location"]);
  518.                     break;
  519.                 case 'CreateDrink':
  520.                     result = createDrink(params["name"], parseFloat(params["price"]), parseInt(params["calories"]),
  521.                         parseInt(params["quantity"]), params["time"], parseBoolean(params["carbonated"]));
  522.                     break;
  523.                 case 'CreateSalad':
  524.                     result = createSalad(params["name"], parseFloat(params["price"]), parseInt(params["calories"]),
  525.                         parseInt(params["quantity"]), params["time"], parseBoolean(params["pasta"]));
  526.                     break;
  527.                 case "CreateMainCourse":
  528.                     result = createMainCourse(params["name"], parseFloat(params["price"]), parseInt(params["calories"]),
  529.                         parseInt(params["quantity"]), params["time"], parseBoolean(params["vegan"]), params["type"]);
  530.                     break;
  531.                 case "CreateDessert":
  532.                     result = createDessert(params["name"], parseFloat(params["price"]), parseInt(params["calories"]),
  533.                         parseInt(params["quantity"]), params["time"], parseBoolean(params["vegan"]));
  534.                     break;
  535.                 case "ToggleSugar":
  536.                     result = toggleSugar(params["name"]);
  537.                     break;
  538.                 case "ToggleVegan":
  539.                     result = toggleVegan(params["name"]);
  540.                     break;
  541.                 case "AddRecipeToRestaurant":
  542.                     result = addRecipeToRestaurant(params["restaurant"], params["recipe"]);
  543.                     break;
  544.                 case "RemoveRecipeFromRestaurant":
  545.                     result = removeRecipeFromRestaurant(params["restaurant"], params["recipe"]);
  546.                     break;
  547.                 case "PrintRestaurantMenu":
  548.                     result = printRestaurantMenu(params["name"]);
  549.                     break;
  550.                 default:
  551.                     throw new Error('Invalid command name: ' + cmdName);
  552.             }
  553.  
  554.             return result;
  555.         }
  556.  
  557.         function parseBoolean(value) {
  558.             switch (value) {
  559.                 case "yes":
  560.                     return true;
  561.                 case "no":
  562.                     return false;
  563.                 default:
  564.                     throw new Error("Invalid boolean value: " + value);
  565.             }
  566.         }
  567.  
  568.         return {
  569.             initialize: initialize,
  570.             executeCommand: executeCommand
  571.         };
  572.     }());
  573.  
  574.  
  575.     // Process the input commands and return the results
  576.     var results = '';
  577.     RestaurantEngine.initialize();
  578.     commands.forEach(function (cmd) {
  579.         if (cmd != "") {
  580.             try {
  581.                 var cmdResult = RestaurantEngine.executeCommand(cmd);
  582.                 results += cmdResult;
  583.             } catch (err) {
  584.                 results += err.message + "\n";
  585.             }
  586.         }
  587.     });
  588.  
  589.     return results.trim();
  590. }
  591.  
  592. // ------------------------------------------------------------
  593. // Read the input from the console as array and process it
  594. // Remove all below code before submitting to the judge system!
  595. // ------------------------------------------------------------
  596.  
  597. (function() {
  598.     var arr = [];
  599.     if (typeof (require) == 'function') {
  600.         // We are in node.js --> read the console input and process it
  601.         require('readline').createInterface({
  602.             input: process.stdin,
  603.             output: process.stdout
  604.         }).on('line', function(line) {
  605.             arr.push(line);
  606.         }).on('close', function() {
  607.             console.log(processRestaurantManagerCommands(arr));
  608.         });
  609.     }
  610. })();
Advertisement
Add Comment
Please, Sign In to add comment