Advertisement
cherokee

JavaScript OOP - 09 July 2015 - 18:00

Jul 10th, 2015
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function solve() {
  2.     var module = (function () {
  3.         var item,
  4.             book,
  5.             media,
  6.             catalog,
  7.             bookCatalog,
  8.             mediaCatalog;
  9.  
  10.         item = (function () {
  11.             var itemId = 0,
  12.                 item = Object.create({});
  13.  
  14.             Object.defineProperties(item, {
  15.                 init: {
  16.                     value: function (name, description) {
  17.                         this.description = description;
  18.                         this.name = name;
  19.                         this._id = ++itemId;
  20.  
  21.                         return this;
  22.                     },
  23.                     enumerable: true,
  24.                     configurable: false
  25.                 },
  26.                 id: {
  27.                     get: function () {
  28.                         return this._id;
  29.                     },
  30.                     enumerable: true,
  31.                     configurable: true
  32.                 },
  33.                 name: {
  34.                     get: function () {
  35.                         return this._name;
  36.                     },
  37.                     set: function (value) {
  38.                         if (typeof(value) !== 'string' || value.length < 2 || value.length > 40) {
  39.                             throw new Error('Invalid name provided.');
  40.                         }
  41.  
  42.                         this._name = value;
  43.                     },
  44.                     enumerable: true,
  45.                     configurable: true
  46.                 },
  47.                 description: {
  48.                     get: function () {
  49.                         return this._description;
  50.                     },
  51.                     set: function (value) {
  52.                         if (typeof(value) !== 'string' || value.length < 1) {
  53.                             throw new Error('Invalid description provided.');
  54.                         }
  55.  
  56.                         this._description = value;
  57.                     },
  58.                     enumerable: true,
  59.                     configurable: true
  60.                 }
  61.             });
  62.             return item;
  63.         }());
  64.  
  65.         book = (function (parent) {
  66.             var book = Object.create(parent);
  67.             Object.defineProperties(book, {
  68.                 init: {
  69.                     value: function (name, isbn, genre, description) {
  70.                         parent.init.call(this, name, description);
  71.                         this.isbn = isbn;
  72.                         this.genre = genre;
  73.  
  74.                         return this;
  75.                     },
  76.                     enumerable: true,
  77.                     configurable: false
  78.                 },
  79.                 isbn: {
  80.                     get: function () {
  81.                         return this._isbn;
  82.                     },
  83.                     set: function (value) {
  84.                         if (typeof (value) !== 'string' || !(/[0-9]/g.test(value))
  85.                             || (value.length !== 10 && value.length !== 13)) {
  86.                             throw new Error('Invalid isbn provided.');
  87.                         }
  88.  
  89.                         this._isbn = value;
  90.                     },
  91.                     enumerable: true,
  92.                     configurable: true
  93.                 },
  94.                 genre: {
  95.                     get: function () {
  96.                         return this._genre;
  97.                     },
  98.                     set: function (value) {
  99.                         if (typeof(value) !== 'string' || value.length < 2 || value.length > 20) {
  100.                             throw new Error('Invalid genre provided.');
  101.                         }
  102.  
  103.                         this._genre = value;
  104.                     },
  105.                     enumerable: true,
  106.                     configurable: true
  107.                 }
  108.             });
  109.             return book;
  110.         }(item));
  111.  
  112.         media = (function (parent) {
  113.             var media = Object.create(parent);
  114.             Object.defineProperties(media, {
  115.                 init: {
  116.                     value: function (name, rating, duration, description) {
  117.                         parent.init.call(this, name, description);
  118.                         this.rating = rating;
  119.                         this.duration = duration;
  120.  
  121.  
  122.                         return this;
  123.                     },
  124.                     enumerable: true,
  125.                     configurable: false
  126.                 },
  127.                 duration: {
  128.                     get: function () {
  129.                         return this._duration;
  130.                     },
  131.                     set: function (value) {
  132.                         if (typeof(value) !== 'number' || value <= 0) {
  133.                             throw new Error('Invalid duration provided.');
  134.                         }
  135.  
  136.                         this._duration = value;
  137.                     },
  138.                     enumerable: true,
  139.                     configurable: true
  140.                 },
  141.                 rating: {
  142.                     get: function () {
  143.                         return this._rating;
  144.                     },
  145.                     set: function (value) {
  146.                         if (typeof(value) !== 'number' || value < 1 || value > 5) {
  147.                             throw new Error('Invalid rating provided.');
  148.                         }
  149.  
  150.                         this._rating = value;
  151.                     },
  152.                     enumerable: true,
  153.                     configurable: true
  154.                 }
  155.             });
  156.             return media;
  157.         }(item));
  158.  
  159.         catalog = (function () {
  160.             var catalogId = 0,
  161.                 findFilterHelper,
  162.                 catalog = Object.create({});
  163.  
  164.             findFilterHelper = function (value) {
  165.                 return function (item) {
  166.                     var id = item.id;
  167.                     var name = item.name.toLowerCase();
  168.                     if (!value.id || id == value.id) {
  169.                         if (!value.name || name == value.name.toLowerCase()) {
  170.                             return true;
  171.                         }
  172.                     }
  173.                     return false;
  174.                 };
  175.             };
  176.  
  177.             Object.defineProperties(catalog, {
  178.                 init: {
  179.                     value: function (name) {
  180.                         this._id = ++catalogId;
  181.                         this.name = name;
  182.                         this._items = [];
  183.                         this._findFilter = findFilterHelper;
  184.  
  185.                         return this;
  186.                     },
  187.                     enumerable: true,
  188.                     configurable: false
  189.                 },
  190.                 id: {
  191.                     get: function () {
  192.                         return this._id;
  193.                     }
  194.                 },
  195.                 items: {
  196.                     get: function () {
  197.                         return this._items;
  198.                     },
  199.                     set: function (value) {
  200.                         this._items = value;
  201.                     },
  202.                     enumerable: true,
  203.                     configurable: true
  204.                 },
  205.                 name: {
  206.                     get: function () {
  207.                         return this._name;
  208.                     },
  209.                     set: function (value) {
  210.                         if (typeof(value) !== 'string' || value.length < 2 || value.length > 40) {
  211.                             throw new Error('Invalid name provided.');
  212.                         }
  213.  
  214.                         this._name = value;
  215.                     },
  216.                     enumerable: true,
  217.                     configurable: true
  218.                 },
  219.                 add: {
  220.                     value: function (values) {
  221.                         var arrOfItems,
  222.                             i, len;
  223.  
  224.                         if (Array.isArray(arguments[0])) {
  225.                             arrOfItems = arguments[0];
  226.                         } else {
  227.                             arrOfItems = Array.prototype.slice.call(arguments);
  228.                         }
  229.  
  230.                         if (arrOfItems.length === 0) {
  231.                             throw new Error('ValidateArrayOfItems - Empty array or no items provided.');
  232.                         }
  233.  
  234.                         arrOfItems.forEach(function (item) {
  235.                             if (item === undefined || item.id === undefined
  236.                                 || item.name === undefined || item.description === undefined) {
  237.                                 throw new Error('ValidateArrayOfItems - non valid item-like object provided')
  238.                             }
  239.                         });
  240.  
  241.                         for (i = 0, len = arrOfItems.length; i < len; i += 1) {
  242.                             this._items.push(arrOfItems[i]);
  243.                         }
  244.  
  245.                         return this;
  246.                     },
  247.                     enumerable: true,
  248.                     configurable: true,
  249.                     writable: false
  250.                 },
  251.                 find: {
  252.                     value: function (value) {
  253.                         var i, len, foundItems = [];
  254.  
  255.                         if (typeof (value) === 'object') { //&& (value.id || value.name)) {
  256.                             foundItems = this.items.filter(this._findFilter(value));
  257.                             return foundItems;
  258.  
  259.                         } else if (typeof(value) === 'number') {
  260.                             for (i = 0, len = this.items.length; i < len; i += 1) {
  261.                                 if (this.items[i].id === value) {
  262.                                     return this.items[i];
  263.                                 }
  264.                             }
  265.                             return null;
  266.                         }
  267.  
  268.                         throw new Error('find - No argument provided or invalid ones')
  269.                     },
  270.                     enumerable: true,
  271.                     configurable: true,
  272.                     writable: false
  273.                 },
  274.                 search: {
  275.                     value: function (pattern) {
  276.                         var result = [],
  277.                             i, len,
  278.                             item,
  279.                             patternLower;
  280.  
  281.                         if (typeof(pattern) !== 'string' || pattern.length < 1) {
  282.                             throw new Error("search - Invalid pattern");
  283.                         }
  284.  
  285.                         patternLower = pattern.toLowerCase();
  286.                         for (i = 0, len = this.items.length; i < len; i += 1) {
  287.                             item = this.items[i];
  288.                             if (item.name.toLowerCase().indexOf(patternLower) > -1 || item.description.toLowerCase().indexOf(patternLower) > -1) {
  289.                                 result.push(item);
  290.                             }
  291.                         }
  292.                         return result;
  293.                     },
  294.                     enumerable: true,
  295.                     configurable: true,
  296.                     writable: false
  297.                 }
  298.             });
  299.             return catalog;
  300.         }());
  301.  
  302.         bookCatalog = (function (parent) {
  303.             var bookCatalog,
  304.                 findFilterHelper;
  305.  
  306.             findFilterHelper = function (value) {
  307.                 return function (item) {
  308.                     var id = item.id;
  309.                     var name = item.name.toLowerCase();
  310.                     var gen = item.genre.toLowerCase();
  311.                     if (!value.id || id === value.id) {
  312.                         if (!value.name || name === value.name.toLowerCase()) {
  313.                             if (!value.genre || gen === value.genre.toLowerCase()) {
  314.                                 return true;
  315.                             }
  316.                         }
  317.                     }
  318.                     return false;
  319.                 };
  320.             };
  321.  
  322.             bookCatalog = Object.create(parent);
  323.             Object.defineProperties(bookCatalog, {
  324.                 init: {
  325.                     value: function (name) {
  326.                         parent.init.call(this, name);
  327.                         this._findFilter = findFilterHelper;
  328.  
  329.                         return this;
  330.                     },
  331.                     enumerable: true,
  332.                     configurable: false
  333.                 },
  334.                 add: {
  335.                     value: function (values) {
  336.  
  337.                         var arrOfItems;
  338.  
  339.                         if (Array.isArray(arguments[0])) {
  340.                             arrOfItems = arguments[0];
  341.                         } else {
  342.                             arrOfItems = Array.prototype.slice.call(arguments);
  343.                         }
  344.  
  345.                         arrOfItems.forEach(function (item) {
  346.                             if (item.isbn === undefined || item.genre === undefined) {
  347.                                 throw new Error('ValidateArrayOfItems - non valid book-like object provided')
  348.                             }
  349.                         });
  350.  
  351.                         parent.add.apply(this, arrOfItems);
  352.  
  353.                         return this;
  354.                     },
  355.                     enumerable: true,
  356.                     configurable: true,
  357.                     writable: false
  358.                 },
  359.                 getGenres: {
  360.                     value: function () {
  361.  
  362.                         var uniqueGenresInLowerCase = [],
  363.                             uniqueGenresItems = {},
  364.                             i, j, len;
  365.  
  366.                         for (j = 0, len = this.items.length; j < len; j += 1) {
  367.                             uniqueGenresItems[this.items[j].genre] = '';
  368.                         }
  369.  
  370.                         uniqueGenresItems = Object.keys(uniqueGenresItems);
  371.  
  372.                         for (i = 0, len = uniqueGenresItems.length; i < len; i += 1) {
  373.                             uniqueGenresInLowerCase.push(uniqueGenresItems[i].toLowerCase());
  374.                         }
  375.  
  376.                         return uniqueGenresInLowerCase;
  377.                     },
  378.                     enumerable: true,
  379.                     configurable: true,
  380.                     writable: false
  381.                 },
  382.                 find: {
  383.                     value: function (value) {
  384.                         return parent.find.call(this, value);
  385.                     },
  386.                     enumerable: true,
  387.                     configurable: true,
  388.                     writable: false
  389.                 }
  390.             });
  391.             return bookCatalog;
  392.         }(catalog));
  393.  
  394.         mediaCatalog = (function (parent) {
  395.             var mediaCatalog,
  396.                 findFilterHelper;
  397.  
  398.             findFilterHelper = function (value) {
  399.                 return function (item) {
  400.                     var id = item.id;
  401.                     var name = item.name.toLowerCase();
  402.                     var ret = item.rating;
  403.                     var dur = item.duration;
  404.                     if (!value.id || id === value.id) {
  405.                         if (!value.name || name === value.name.toLowerCase()) {
  406.                             if (!value.rating || ret === value.rating) {
  407.                                 if (!value.duration || dur === value.duration) {
  408.                                     return true;
  409.                                 }
  410.                             }
  411.                         }
  412.                     }
  413.                     return false;
  414.                 };
  415.             };
  416.  
  417.             mediaCatalog = Object.create(parent);
  418.             Object.defineProperties(mediaCatalog, {
  419.                 init: {
  420.                     value: function (name) {
  421.                         parent.init.call(this, name);
  422.                         this._findFilter = findFilterHelper;
  423.  
  424.                         return this;
  425.                     },
  426.                     enumerable: true,
  427.                     configurable: false
  428.                 },
  429.                 add: {
  430.                     value: function (values) {
  431.                         var arrOfItems;
  432.  
  433.                         if (Array.isArray(arguments[0])) {
  434.                             arrOfItems = arguments[0];
  435.                         } else {
  436.                             arrOfItems = Array.prototype.slice.call(arguments);
  437.                         }
  438.  
  439.                         arrOfItems.forEach(function (item) {
  440.                             if (item.duration === undefined || item.rating === undefined) {
  441.                                 throw new Error('ValidateArrayOfItems - non valid book-like object provided')
  442.                             }
  443.                         });
  444.  
  445.                         parent.add.apply(this, arrOfItems);
  446.  
  447.                         return this;
  448.                     },
  449.                     enumerable: true,
  450.                     configurable: true,
  451.                     writable: false
  452.                 },
  453.                 find: {
  454.                     value: function (value) {
  455.                         return parent.find.call(this, value);
  456.                     },
  457.                     enumerable: true,
  458.                     configurable: true,
  459.                     writable: false
  460.                 },
  461.                 getTop: {
  462.                     value: function (count) {
  463.                         if (typeof(count) !== 'number' || count < 1) {
  464.                             throw new Error();
  465.                         }
  466.                         return this.items.slice(0)
  467.                             .sort(function (a, b) {
  468.                                 return a.rating - b.rating;
  469.                             })
  470.                             .slice(0, count)
  471.                             .map(function (element) {
  472.                                 return {id: element.id, name: element.name}
  473.                             });
  474.                     },
  475.                     enumerable: true,
  476.                     configurable: true,
  477.                     writable: false
  478.                 },
  479.                 getSortedByDuration: {
  480.                     value: function () {
  481.                         return this.items.slice(0)
  482.                             .sort(function (a, b) {
  483.                                 if (a.duration === b.duration) {
  484.                                     return a.id - b.id
  485.                                 }
  486.  
  487.                                 return (a.duration - b.duration) * -1;
  488.                             });
  489.                     },
  490.                     enumerable: true,
  491.                     configurable: true,
  492.                     writable: false
  493.                 }
  494.  
  495.             });
  496.             return mediaCatalog;
  497.         }(catalog));
  498.  
  499.         return {
  500.             getBook: function (name, isbn, genre, description) {
  501.                 return Object.create(book).init(name, isbn, genre, description);
  502.             },
  503.             getMedia: function (name, rating, duration, description) {
  504.                 return Object.create(media).init(name, rating, duration, description);
  505.             },
  506.             getBookCatalog: function (name) {
  507.                 return Object.create(bookCatalog).init(name);
  508.             },
  509.             getMediaCatalog: function (name) {
  510.                 return Object.create(mediaCatalog).init(name);
  511.             }
  512.         };
  513.     }());
  514.  
  515.     return module;
  516. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement