Venciity

Restaurant Manager 100/100 with updated validation

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