Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function solve() {
- var item, book, media, catalogue, mediaCatalogue, bookCatalogue;
- //TODO: constants
- function isNumber(value) {
- return !isNaN(value);
- }
- function isObject(value) {
- return typeof(value) === 'object';
- }
- function isNonEmptyString(value) {
- return typeof(value) === 'string' && value.length > 0;
- }
- function isValidStringLength(value, min, max) {
- return isNonEmptyString(value) && value.length >= min && value.length <= max;
- }
- function isValidIsbn(value) {
- return isNonEmptyString(value) && value.match(/^\d+$/) && (value.length === 10 || value.length === 13)
- }
- function isPositiveNumber(value) {
- return isNumber(value) && value > 0;
- }
- function isInRange(value, min, max) {
- return isNumber(value) && value >= min && value <= max;
- }
- function getUnique(value, index, self) {
- return self.indexOf(value) === index;
- }
- function sortDescendingByRating(first, second) {
- return second.rating - first.rating;
- }
- function getSortingFunction(firstParameter, secondParameter) {
- return function(first, second) {
- if (first[firstParameter] > second[firstParameter]) {
- return -1;
- } else if (first[firstParameter] < second[firstParameter]) {
- return 1;
- }
- if (first[secondParameter] < second[secondParameter]) {
- return -1;
- } else if (first[secondParameter] > second[secondParameter]) {
- return 1;
- } else {
- return 0;
- }
- }
- }
- Object.prototype.extend = function(parent) {
- this.prototype = Object.create(parent.prototype);
- this.prototype.constructor = this;
- };
- item = (function() {
- var idCounter = 0,
- item = Object.create({});
- Object.defineProperties(item, {
- init: {
- value: function(name, description) {
- this.id = ++idCounter;
- this.description = description;
- this.name = name;
- return this;
- }
- },
- id: {
- get: function() {
- return this._id;
- },
- set: function(value) {
- this._id = value;
- }
- },
- name: {
- get: function() {
- return this._name;
- },
- set: function(value) {
- if (!isValidStringLength(value, 2, 40)) {
- throw new Error('Name must be a string between 2 and 40 characters.');
- }
- this._name = value;
- }
- },
- description: {
- get: function() {
- return this._description;
- },
- set: function(value) {
- if (!isNonEmptyString(value)) {
- throw new Error('Description must be a non-empty string.');
- }
- this._description = value;
- }
- }
- });
- return item;
- }());
- book = (function(parent) {
- var book = Object.create(parent);
- Object.defineProperties(book, {
- init: {
- value: function(name, isbn, genre, description) {
- parent.init.call(this, name, description);
- this.isbn = isbn;
- this.genre = genre;
- return this;
- }
- },
- isbn: {
- get: function() {
- return this._isbn;
- },
- set: function(value) {
- if (!isValidIsbn(value)) {
- throw new Error('ISBN must be a 10 or 13 digits.');
- }
- this._isbn = value;
- }
- },
- genre: {
- get: function() {
- return this._genre;
- },
- set: function(value) {
- if (!isValidStringLength(value, 2, 20)) {
- throw new Error('Genre must be a string between 2 and 20 characters.');
- }
- this._genre = value;
- }
- }
- });
- return book;
- }(item));
- media = (function(parent) {
- var media = Object.create(parent);
- Object.defineProperties(media, {
- init: {
- value: function(name, rating, duration, description) {
- parent.init.call(this, name, description);
- this.duration = duration;
- this.raiting = raiting;
- return this;
- }
- },
- duration: {
- get: function() {
- return this._duration;
- },
- set: function(value) {
- if (!isPositiveNumber(value)) {
- throw new Error('Duration must be a positive number.');
- }
- this._duration = value;
- }
- },
- raiting: {
- get: function() {
- return this._raiting;
- },
- set: function(value) {
- if (!isInRange(value, 1, 5)) {
- throw new Error('Rating must be between 1 and 5.');
- }
- this._raiting = value;
- }
- }
- });
- return media;
- }(item));
- catalogue = (function() {
- var idCounter = 0,
- catalogue = Object.create({});
- Object.defineProperties(catalogue, {
- init: {
- value: function(name) {
- this.id = ++idCounter;
- this.name = name;
- this._items = [];
- return this;
- }
- },
- id: {
- get: function() {
- return this._id;
- },
- set: function(value) {
- this._id = value;
- }
- },
- name: {
- get: function() {
- return this._name;
- },
- set: function(value) {
- if (!isValidStringLength(value, 2, 40)) {
- throw new Error('Name must be a string between 2 and 40 characters.');
- }
- this._name = value;
- }
- },
- items: {
- get: function() {
- return this._items;
- }
- },
- add: {
- value: function(items) {
- var allItems = [],
- areBooks;
- if (!arguments[0]) {
- throw new Error('Items cannot be empty.');
- }
- if (Array.isArray(arguments[0])) {
- allItems = arguments[0];
- if (allItems.length === 0) {
- throw new Error('Items cannot be empty.');
- }
- } else {
- for (var i = 0, len = arguments.length; i < len; i += 1) {
- allItems.push(arguments[i]);
- }
- }
- for (var i = 0, len = allItems.length; i < len; i += 1) {
- this.items.push(allItems[i]);
- }
- return this;
- }
- },
- find: {
- value: function(options) {
- //console.log(this.items);
- var result = [];
- if (!options || (!isNumber(options) && !isObject(options))) {
- throw new Error('You must provide a valid id or options.');
- }
- if (isNumber(options)) {
- result = this.items.filter(function(item) {
- return item.id == options;
- });
- if (result.length > 0) {
- //console.log(result[0]);
- return result[0];
- } else {
- return null;
- }
- } else {
- if (options.hasOwnProperty('id') && options.hasOwnProperty('name')) {
- result = this.items.filter(function(item) {
- return item.id == options.id && item.name.toLowerCase() == options.name.toLowerCase();
- });
- } else {
- result = this.items.filter(function(item) {
- return item.id == options.id || item.name.toLowerCase() == options.name.toLowerCase();
- });
- }
- }
- return result;
- }
- },
- search: {
- value: function(pattern) {
- var result = [];
- if (!pattern) {
- throw new Error('You need to provide a search pattern.');
- }
- if (pattern.length < 1) {
- throw new Error('Pattern cannot be blank.');
- }
- pattern = pattern.toLowerCase();
- for (var i = 0, len = this.items.length; i < len; i += 1) {
- if (this.items[i].name.toLowerCase().indexOf(pattern) > -1 || this.items[i].description.toLowerCase().indexOf(pattern) > -1) {
- result.push(this.items[i]);
- }
- }
- return result;
- }
- }
- });
- return catalogue;
- }());
- bookCatalogue = (function(parent) {
- var bookCatalogue = Object.create(parent);
- Object.defineProperties(bookCatalogue, {
- init: {
- value: function(name) {
- parent.init.call(this, name);
- return this;
- }
- },
- add: {
- value: function(items) {
- var allItems = [],
- areBooks;
- if (!arguments[0]) {
- throw new Error('Items cannot be empty.');
- }
- if (Array.isArray(arguments[0])) {
- allItems = arguments[0];
- if (allItems.length === 0) {
- throw new Error('Items cannot be empty.');
- }
- } else {
- for (var i = 0, len = arguments.length; i < len; i += 1) {
- allItems.push(arguments[i]);
- }
- }
- areBooks = allItems.every(function(item) {
- return Object.getPrototypeOf(item) === book;
- });
- if (!areBooks) {
- throw new Error('All items must be books.');
- }
- parent.add.call(this, items);
- return this;
- }
- },
- getGenres: {
- value: function() {
- var allGenres = this.items.map(function(item) {
- return item.genre.toLowerCase();
- });
- return allGenres.filter(getUnique);
- }
- },
- find: {
- value: function(options) {
- //var result = [];
- if (options.hasOwnProperty('genre')) {
- //TODO
- } else {
- parent.find.call(this, options);
- }
- }
- }
- });
- return bookCatalogue;
- }(catalogue));
- mediaCatalogue = (function(parent) {
- var mediaCatalogue = Object.create(parent);
- Object.defineProperties(mediaCatalogue, {
- init: {
- value: function(name) {
- parent.init.call(this, name);
- return this;
- }
- },
- add: {
- value: function(items) {
- var allItems = [],
- areBooks;
- if (!arguments[0]) {
- throw new Error('Items cannot be empty.');
- }
- if (Array.isArray(arguments[0])) {
- allItems = arguments[0];
- if (allItems.length === 0) {
- throw new Error('Items cannot be empty.');
- }
- } else {
- for (var i = 0, len = arguments.length; i < len; i += 1) {
- allItems.push(arguments[i]);
- }
- }
- areBooks = allItems.every(function(item) {
- return Object.getPrototypeOf(item) === media;
- });
- if (!areBooks) {
- throw new Error('All items must be books.');
- }
- parent.add.call(this, items);
- return this;
- }
- },
- getTop: {
- value: function(count) {
- if (!isPositiveNumber(count)) {
- throw new Error('Count must be a positive number');
- }
- var sorted = this.items.sort(sortDescendingByRating);
- return sorted.slice(0, count - 1);
- }
- },
- getSortedByDuration: {
- value: function() {
- return this.items.sort(getSortingFunction('duration', 'id')); //TODO: slice?
- }
- }
- });
- return mediaCatalogue;
- }(catalogue));
- return {
- getBook: function(name, isbn, genre, description) {
- //return a book instance
- return Object.create(book).init(name, isbn, genre, description);
- },
- getMedia: function(name, rating, duration, description) {
- //return a media instance
- return Object.create(book).init(name, rating, duration, description);
- },
- getBookCatalog: function(name) {
- //return a book catalog instance
- return Object.create(bookCatalogue).init(name);
- },
- getMediaCatalog: function(name) {
- //return a media catalog instance
- return Object.create(mediaCatalogue).init(name);
- }
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement