Skip to content

Commit f627098

Browse files
author
KonstantinSimeonov
committed
2 parents 2e2e24b + 316e3ca commit f627098

File tree

30 files changed

+1339
-1027
lines changed

30 files changed

+1339
-1027
lines changed

Additional-Resources/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- OOP in JavaScript with ES2015
1010
- [Video Course](https://app.pluralsight.com/library/courses/javascript-es6-object-oriented-programming/table-of-contents)
1111
- [Article MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes)
12+
- [ES2015 Classes essentials](http://exploringjs.com/es6/ch_classes.html)
13+
- [Rich article on when and why you should avoid ES2015 classes](https://github.com/joshburgess/not-awesome-es6-classes)
1214
- Mixins
1315
- [Article MDN] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes#Mix-ins)
1416
- [Article](http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/)

Practical Exams/academy-online-catalogs/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ has the following:
108108
* Each item **must contain** the pattern as substring either in its **name** or in its **description**
109109
* **Returns an empty array**, if **none of the items** contain the pattern
110110
* The `pattern` is a string containing at least 1 character
111-
* The search is **case insensitive**
111+
* The search is **case sensitive**
112112

113113
##`BookCatalog`
114114
has the following:
@@ -157,7 +157,9 @@ has the following:
157157
* The media must sorted by:
158158
* descending by duration
159159
* ascending by id
160-
160+
* find(options)
161+
* Extends find(options) from parent, but adds a key `rating`
162+
* i.e. books can be found by `id`, `name` and/or `rating`
161163

162164
##Example:
163165

@@ -168,11 +170,11 @@ has the following:
168170
},
169171
getMedia: function (name, rating, duration, description) {
170172
//return a media instance
171-
}
173+
},
172174
getBookCatalog: function (name) {
173175
//return a book catalog instance
174176
},
175177
getMediaCatalog: function (name) {
176178
//return a media catalog instance
177179
}
178-
};
180+
};
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
2-
"name": "test-driven-hw-mocha",
3-
"version": "1.0.0",
4-
"description": "",
5-
"main": "index.js",
6-
"scripts": {
7-
"test": "mocha -R spec tests"
8-
},
9-
"author": "",
10-
"license": "ISC",
11-
"devDependencies": {
12-
"chai": "^3.0.0"
13-
}
14-
}
2+
"name": "test-driven-hw-mocha",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "node_modules/mocha/bin/mocha -R spec tests"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"devDependencies": {
12+
"chai": "^3.0.0",
13+
"mocha": "^3.0.2"
14+
}
15+
}
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
function solve() {
2+
const getId = (function() {
3+
let id = 0;
4+
5+
return function() {
6+
id += 1;
7+
return id;
8+
};
9+
}());
10+
11+
class Item {
12+
constructor(description, name) {
13+
this.id = getId();
14+
this.description = description;
15+
this.name = name;
16+
}
17+
18+
get description() {
19+
return this._description;
20+
}
21+
set description(description) {
22+
if(typeof description !== 'string') {
23+
throw 'Description should be a string';
24+
}
25+
if(description === '') {
26+
throw 'Description should not be empty';
27+
}
28+
this._description = description;
29+
}
30+
31+
get name() {
32+
return this._name;
33+
}
34+
set name(name) {
35+
if(typeof name !== 'string') {
36+
throw 'Name should be a string';
37+
}
38+
if(name.length < 2 || name.length > 40) {
39+
throw 'Name length should be between 2 and 40';
40+
}
41+
this._name = name;
42+
}
43+
}
44+
45+
class Book extends Item {
46+
constructor(description, name, isbn, genre) {
47+
super(description, name);
48+
this.isbn = isbn;
49+
this.genre = genre;
50+
}
51+
52+
get isbn() {
53+
return this._isbn;
54+
}
55+
set isbn(isbn) {
56+
if(typeof isbn !== 'string') {
57+
throw 'Isbn should be a string';
58+
}
59+
if(isbn.length !== 10 && isbn.length !== 13) {
60+
throw 'Isbn length should be either 10 or 13';
61+
}
62+
if(!isbn.match(/^[0-9]*$/)) {
63+
throw 'Isbn should be only digits';
64+
}
65+
66+
this._isbn = isbn;
67+
}
68+
69+
get genre() {
70+
return this._genre;
71+
}
72+
set genre(genre) {
73+
if(typeof genre !== 'string') {
74+
throw 'Genre should be a string';
75+
}
76+
if(genre.length < 2 || genre.length > 20) {
77+
throw 'Genre length should be between 2 and 20';
78+
}
79+
80+
this._genre = genre;
81+
}
82+
}
83+
84+
class Media extends Item {
85+
constructor(description, name, duration, rating) {
86+
super(description, name);
87+
this.duration = duration;
88+
this.rating = rating;
89+
}
90+
91+
get duration() {
92+
return this._duration;
93+
}
94+
set duration(duration) {
95+
if(typeof duration !== 'number') {
96+
throw 'Duration should be a number';
97+
}
98+
if(duration <= 0) {
99+
throw 'Duration must be a number greater than 0';
100+
}
101+
102+
this._duration = duration;
103+
}
104+
105+
get rating() {
106+
return this._rating;
107+
}
108+
set rating(rating) {
109+
if(typeof rating !== 'number') {
110+
throw 'Rating should be a number';
111+
}
112+
if(rating < 1 || rating > 5) {
113+
throw 'Rating must be a number between 1 and 5';
114+
}
115+
116+
this._rating = rating;
117+
}
118+
}
119+
120+
class Catalog {
121+
constructor(name) {
122+
this.id = getId();
123+
this.name = name;
124+
this.items = [];
125+
}
126+
127+
get name() {
128+
return this._name;
129+
}
130+
set name(name) {
131+
if(typeof name !== 'string') {
132+
throw 'Name should be a string';
133+
}
134+
if(name.length < 2 || name.length > 40) {
135+
throw 'Name length should be between 2 and 40';
136+
}
137+
this._name = name;
138+
}
139+
140+
add(...items) {
141+
if(Array.isArray(items[0])) {
142+
items = items[0];
143+
}
144+
145+
if(items.length === 0) {
146+
throw 'No items are added';
147+
}
148+
149+
this.items.push(...items);
150+
151+
return this;
152+
}
153+
154+
find(x) {
155+
if(typeof x === 'number') {
156+
for(let item of this.items) {
157+
if(item.id === x) {
158+
return item;
159+
}
160+
}
161+
162+
return null;
163+
}
164+
165+
if(x !== null && typeof x === 'object') {
166+
return this.items.filter(function(item) {
167+
return Object.keys(x).every(function(prop) {
168+
return x[prop] === item[prop];
169+
});
170+
});
171+
}
172+
173+
throw 'Invalid options or id';
174+
}
175+
176+
search(pattern) {
177+
if(typeof pattern !== 'string' || pattern === '') {
178+
throw 'Search pattern should be non-empty a string';
179+
}
180+
181+
return this.items.filter(function(item) {
182+
return item.name.indexOf(pattern) >= 0
183+
|| item.description.indexOf(pattern) >= 0;
184+
});
185+
}
186+
}
187+
188+
class BookCatalog extends Catalog {
189+
constructor(name) {
190+
super(name);
191+
}
192+
193+
add(...books) {
194+
if(Array.isArray(books[0])) {
195+
books = books[0];
196+
}
197+
198+
books.forEach(function(x) {
199+
if(!(x instanceof Book)) {
200+
throw 'Must add only books';
201+
}
202+
});
203+
204+
return super.add(...books);
205+
}
206+
207+
getGenres() {
208+
let uniq = {};
209+
this.items.forEach(x => uniq[x.genre] = true);
210+
return Object.keys(uniq);
211+
}
212+
213+
find(x) {
214+
return super.find(x);
215+
}
216+
}
217+
218+
class MediaCatalog extends Catalog {
219+
constructor(name) {
220+
super(name);
221+
}
222+
223+
add(...medias) {
224+
if(Array.isArray(medias[0])) {
225+
medias = medias[0];
226+
}
227+
228+
medias.forEach(function(x) {
229+
if(!(x instanceof Media)) {
230+
throw 'Must add only medias';
231+
}
232+
});
233+
234+
return super.add(...medias);
235+
}
236+
237+
getTop(count) {
238+
if(typeof count !== 'number') {
239+
throw 'Count should be a number';
240+
}
241+
if(count < 1) {
242+
throw 'Count must be more than 1';
243+
}
244+
245+
return this.items
246+
.sort((a, b) => a.rating < b.rating)
247+
.filter((_, ind) => ind < count)
248+
.map(x => ({id: x.id, name: x.name}));
249+
}
250+
251+
getSortedByDuration() {
252+
return this.items
253+
.sort((a, b) => {
254+
if(a.duration === b.duration) {
255+
return a.id < b.id;
256+
}
257+
258+
return a.duration > b.duration;
259+
});
260+
}
261+
}
262+
263+
return {
264+
getBook(name, isbn, genre, description) {
265+
return new Book(description, name, isbn, genre);
266+
},
267+
getMedia(name, rating, duration, description) {
268+
return new Media(description, name, duration, rating);
269+
},
270+
getBookCatalog(name) {
271+
return new BookCatalog(name);
272+
},
273+
getMediaCatalog(name) {
274+
return new MediaCatalog(name);
275+
}
276+
};
277+
}
278+
279+
module.exports = solve;

0 commit comments

Comments
 (0)