Advertisement
svetlai

Catalogue

Jul 10th, 2015
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function solve() {
  2.     var item, book, media, catalogue, mediaCatalogue, bookCatalogue;
  3.     //TODO: constants
  4.  
  5.     function isNumber(value) {
  6.         return !isNaN(value);
  7.     }
  8.  
  9.     function isObject(value) {
  10.         return typeof(value) === 'object';
  11.     }
  12.  
  13.     function isNonEmptyString(value) {
  14.         return typeof(value) === 'string' && value.length > 0;
  15.     }
  16.  
  17.     function isValidStringLength(value, min, max) {
  18.         return isNonEmptyString(value) && value.length >= min && value.length <= max;
  19.     }
  20.  
  21.     function isValidIsbn(value) {
  22.         return isNonEmptyString(value) && value.match(/^\d+$/) && (value.length === 10 || value.length === 13)
  23.     }
  24.  
  25.     function isPositiveNumber(value) {
  26.         return isNumber(value) && value > 0;
  27.     }
  28.  
  29.     function isInRange(value, min, max) {
  30.         return isNumber(value) && value >= min && value <= max;
  31.     }
  32.  
  33.     function getUnique(value, index, self) {
  34.         return self.indexOf(value) === index;
  35.     }
  36.  
  37.     function sortDescendingByRating(first, second) {
  38.         return second.rating - first.rating;
  39.     }
  40.  
  41.     function getSortingFunction(firstParameter, secondParameter) {
  42.         return function(first, second) {
  43.             if (first[firstParameter] > second[firstParameter]) {
  44.                 return -1;
  45.             } else if (first[firstParameter] < second[firstParameter]) {
  46.                 return 1;
  47.             }
  48.  
  49.             if (first[secondParameter] < second[secondParameter]) {
  50.                 return -1;
  51.             } else if (first[secondParameter] > second[secondParameter]) {
  52.                 return 1;
  53.             } else {
  54.                 return 0;
  55.             }
  56.         }
  57.     }
  58.  
  59.     Object.prototype.extend = function(parent) {
  60.         this.prototype = Object.create(parent.prototype);
  61.         this.prototype.constructor = this;
  62.     };
  63.  
  64.     item = (function() {
  65.         var idCounter = 0,
  66.             item = Object.create({});
  67.  
  68.         Object.defineProperties(item, {
  69.             init: {
  70.                 value: function(name, description) {
  71.                     this.id = ++idCounter;
  72.                     this.description = description;
  73.                     this.name = name;
  74.                     return this;
  75.                 }
  76.             },
  77.             id: {
  78.                 get: function() {
  79.                     return this._id;
  80.                 },
  81.                 set: function(value) {
  82.                     this._id = value;
  83.                 }
  84.             },
  85.             name: {
  86.                 get: function() {
  87.                     return this._name;
  88.                 },
  89.  
  90.                 set: function(value) {
  91.                     if (!isValidStringLength(value, 2, 40)) {
  92.                         throw new Error('Name must be a string between 2 and 40 characters.');
  93.                     }
  94.                     this._name = value;
  95.                 }
  96.             },
  97.             description: {
  98.                 get: function() {
  99.                     return this._description;
  100.                 },
  101.  
  102.                 set: function(value) {
  103.                     if (!isNonEmptyString(value)) {
  104.                         throw new Error('Description must be a non-empty string.');
  105.                     }
  106.                     this._description = value;
  107.                 }
  108.             }
  109.         });
  110.  
  111.         return item;
  112.     }());
  113.  
  114.     book = (function(parent) {
  115.         var book = Object.create(parent);
  116.  
  117.         Object.defineProperties(book, {
  118.             init: {
  119.                 value: function(name, isbn, genre, description) {
  120.                     parent.init.call(this, name, description);
  121.                     this.isbn = isbn;
  122.                     this.genre = genre;
  123.                     return this;
  124.                 }
  125.             },
  126.             isbn: {
  127.                 get: function() {
  128.                     return this._isbn;
  129.                 },
  130.                 set: function(value) {
  131.                     if (!isValidIsbn(value)) {
  132.                         throw new Error('ISBN must be a 10 or 13 digits.');
  133.                     }
  134.  
  135.                     this._isbn = value;
  136.                 }
  137.             },
  138.             genre: {
  139.                 get: function() {
  140.                     return this._genre;
  141.                 },
  142.                 set: function(value) {
  143.                     if (!isValidStringLength(value, 2, 20)) {
  144.                         throw new Error('Genre must be a string between 2 and 20 characters.');
  145.                     }
  146.  
  147.                     this._genre = value;
  148.                 }
  149.             }
  150.         });
  151.  
  152.         return book;
  153.     }(item));
  154.  
  155.     media = (function(parent) {
  156.         var media = Object.create(parent);
  157.  
  158.         Object.defineProperties(media, {
  159.             init: {
  160.                 value: function(name, rating, duration, description) {
  161.                     parent.init.call(this, name, description);
  162.                     this.duration = duration;
  163.                     this.raiting = raiting;
  164.                     return this;
  165.                 }
  166.             },
  167.             duration: {
  168.                 get: function() {
  169.                     return this._duration;
  170.                 },
  171.                 set: function(value) {
  172.                     if (!isPositiveNumber(value)) {
  173.                         throw new Error('Duration must be a positive number.');
  174.                     }
  175.  
  176.                     this._duration = value;
  177.                 }
  178.             },
  179.             raiting: {
  180.                 get: function() {
  181.                     return this._raiting;
  182.                 },
  183.                 set: function(value) {
  184.                     if (!isInRange(value, 1, 5)) {
  185.                         throw new Error('Rating must be between 1 and 5.');
  186.                     }
  187.  
  188.                     this._raiting = value;
  189.                 }
  190.             }
  191.         });
  192.  
  193.         return media;
  194.     }(item));
  195.  
  196.     catalogue = (function() {
  197.         var idCounter = 0,
  198.             catalogue = Object.create({});
  199.  
  200.         Object.defineProperties(catalogue, {
  201.             init: {
  202.                 value: function(name) {
  203.                     this.id = ++idCounter;
  204.                     this.name = name;
  205.                     this._items = [];
  206.                     return this;
  207.                 }
  208.             },
  209. id: {
  210.                 get: function() {
  211.                     return this._id;
  212.                 },
  213.                 set: function(value) {
  214.                     this._id = value;
  215.                 }
  216.             },
  217.             name: {
  218.                 get: function() {
  219.                     return this._name;
  220.                 },
  221.  
  222.                 set: function(value) {
  223.                     if (!isValidStringLength(value, 2, 40)) {
  224.                         throw new Error('Name must be a string between 2 and 40 characters.');
  225.                     }
  226.                     this._name = value;
  227.                 }
  228.             },
  229.             items: {
  230.                 get: function() {
  231.                     return this._items;
  232.                 }
  233.             },
  234.             add: {
  235.                 value: function(items) {
  236.                     var allItems = [],
  237.                         areBooks;
  238.  
  239.                     if (!arguments[0]) {
  240.                         throw new Error('Items cannot be empty.');
  241.                     }
  242.  
  243.                     if (Array.isArray(arguments[0])) {
  244.                         allItems = arguments[0];
  245.                         if (allItems.length === 0) {
  246.                             throw new Error('Items cannot be empty.');
  247.                         }
  248.                     } else {
  249.                         for (var i = 0, len = arguments.length; i < len; i += 1) {
  250.                             allItems.push(arguments[i]);
  251.                         }
  252.                     }
  253.  
  254.                     for (var i = 0, len = allItems.length; i < len; i += 1) {
  255.                         this.items.push(allItems[i]);
  256.                     }
  257.  
  258.                     return this;
  259.                 }
  260.             },
  261.             find: {
  262.                 value: function(options) {
  263.                     //console.log(this.items);
  264.                     var result = [];
  265.                     if (!options || (!isNumber(options) && !isObject(options))) {
  266.                         throw new Error('You must provide a valid id or options.');
  267.                     }
  268.  
  269.                     if (isNumber(options)) {
  270.                         result = this.items.filter(function(item) {
  271.                             return item.id == options;
  272.                         });
  273.  
  274.                         if (result.length > 0) {
  275.                             //console.log(result[0]);
  276.                             return result[0];
  277.                         } else {
  278.                             return null;
  279.                         }
  280.  
  281.                     } else {
  282.  
  283.                         if (options.hasOwnProperty('id') && options.hasOwnProperty('name')) {
  284.                             result = this.items.filter(function(item) {
  285.                                 return item.id == options.id && item.name.toLowerCase() == options.name.toLowerCase();
  286.                             });
  287.                         } else {
  288.                             result = this.items.filter(function(item) {
  289.                                 return item.id == options.id || item.name.toLowerCase() == options.name.toLowerCase();
  290.                             });
  291.                         }
  292.                     }
  293.  
  294.                     return result;
  295.                 }
  296.             },
  297.             search: {
  298.                 value: function(pattern) {
  299.                     var result = [];
  300.                     if (!pattern) {
  301.                         throw new Error('You need to provide a search pattern.');
  302.                     }
  303.  
  304.                     if (pattern.length < 1) {
  305.                         throw new Error('Pattern cannot be blank.');
  306.                     }
  307.  
  308.                     pattern = pattern.toLowerCase();
  309.  
  310.                     for (var i = 0, len = this.items.length; i < len; i += 1) {
  311.                         if (this.items[i].name.toLowerCase().indexOf(pattern) > -1 || this.items[i].description.toLowerCase().indexOf(pattern) > -1) {
  312.                             result.push(this.items[i]);
  313.                         }
  314.                     }
  315.  
  316.                     return result;
  317.                 }
  318.             }
  319.         });
  320.  
  321.         return catalogue;
  322.     }());
  323.  
  324.     bookCatalogue = (function(parent) {
  325.         var bookCatalogue = Object.create(parent);
  326.  
  327.         Object.defineProperties(bookCatalogue, {
  328.             init: {
  329.                 value: function(name) {
  330.                     parent.init.call(this, name);
  331.                     return this;
  332.                 }
  333.             },
  334.             add: {
  335.                 value: function(items) {
  336.                     var allItems = [],
  337.                         areBooks;
  338.  
  339.                     if (!arguments[0]) {
  340.                         throw new Error('Items cannot be empty.');
  341.                     }
  342.  
  343.                     if (Array.isArray(arguments[0])) {
  344.                         allItems = arguments[0];
  345.                         if (allItems.length === 0) {
  346.                             throw new Error('Items cannot be empty.');
  347.                         }
  348.                     } else {
  349.                         for (var i = 0, len = arguments.length; i < len; i += 1) {
  350.                             allItems.push(arguments[i]);
  351.                         }
  352.                     }
  353.  
  354.                     areBooks = allItems.every(function(item) {
  355.                         return Object.getPrototypeOf(item) === book;
  356.                     });
  357.  
  358.                     if (!areBooks) {
  359.                         throw new Error('All items must be books.');
  360.                     }
  361.  
  362.                     parent.add.call(this, items);
  363.  
  364.                     return this;
  365.                 }
  366.             },
  367.             getGenres: {
  368.                 value: function() {
  369.                     var allGenres = this.items.map(function(item) {
  370.                         return item.genre.toLowerCase();
  371.                     });
  372.  
  373.                     return allGenres.filter(getUnique);
  374.                 }
  375.             },
  376.             find: {
  377.                 value: function(options) {
  378.                     //var result = [];
  379.                     if (options.hasOwnProperty('genre')) {
  380.                         //TODO
  381.                     } else {
  382.                         parent.find.call(this, options);
  383.                     }
  384.                 }
  385.             }
  386.         });
  387.  
  388.         return bookCatalogue;
  389.     }(catalogue));
  390.  
  391.     mediaCatalogue = (function(parent) {
  392.         var mediaCatalogue = Object.create(parent);
  393.  
  394.         Object.defineProperties(mediaCatalogue, {
  395.             init: {
  396.                 value: function(name) {
  397.                     parent.init.call(this, name);
  398.                     return this;
  399.                 }
  400.             },
  401.             add: {
  402.                 value: function(items) {
  403.                     var allItems = [],
  404.                         areBooks;
  405.  
  406.                     if (!arguments[0]) {
  407.                         throw new Error('Items cannot be empty.');
  408.                     }
  409.  
  410.                     if (Array.isArray(arguments[0])) {
  411.                         allItems = arguments[0];
  412.                         if (allItems.length === 0) {
  413.                             throw new Error('Items cannot be empty.');
  414.                         }
  415.                     } else {
  416.                         for (var i = 0, len = arguments.length; i < len; i += 1) {
  417.                             allItems.push(arguments[i]);
  418.                         }
  419.                     }
  420.  
  421.                     areBooks = allItems.every(function(item) {
  422.                         return Object.getPrototypeOf(item) === media;
  423.                     });
  424.  
  425.                     if (!areBooks) {
  426.                         throw new Error('All items must be books.');
  427.                     }
  428.  
  429.                     parent.add.call(this, items);
  430.  
  431.                     return this;
  432.                 }
  433.             },
  434.             getTop: {
  435.                 value: function(count) {
  436.                     if (!isPositiveNumber(count)) {
  437.                         throw new Error('Count must be a positive number');
  438.                     }
  439.  
  440.                     var sorted = this.items.sort(sortDescendingByRating);
  441.  
  442.                     return sorted.slice(0, count - 1);
  443.                 }
  444.             },
  445.             getSortedByDuration: {
  446.                 value: function() {
  447.                     return this.items.sort(getSortingFunction('duration', 'id')); //TODO: slice?
  448.                 }
  449.             }
  450.         });
  451.  
  452.         return mediaCatalogue;
  453.     }(catalogue));
  454.  
  455.     return {
  456.         getBook: function(name, isbn, genre, description) {
  457.             //return a book instance
  458.             return Object.create(book).init(name, isbn, genre, description);
  459.         },
  460.         getMedia: function(name, rating, duration, description) {
  461.             //return a media instance
  462.             return Object.create(book).init(name, rating, duration, description);
  463.         },
  464.         getBookCatalog: function(name) {
  465.             //return a book catalog instance
  466.             return Object.create(bookCatalogue).init(name);
  467.         },
  468.         getMediaCatalog: function(name) {
  469.             //return a media catalog instance
  470.             return Object.create(mediaCatalogue).init(name);
  471.         }
  472.     };
  473. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement