diff --git a/index.js b/index.js index 0253060..c38efb8 100644 --- a/index.js +++ b/index.js @@ -5,26 +5,26 @@ var lib = require('./lib'); var friends = [ { name: 'Sam', - friends: ['Mat', 'Sharon'], + friends: ['Sharon', 'Mat'], gender: 'male', best: true }, { name: 'Sally', - friends: ['Brad', 'Emily'], + friends: ['Emily', 'Brad'], gender: 'female', best: true }, - { - name: 'Mat', - friends: ['Sam', 'Sharon'], - gender: 'male' - }, { name: 'Sharon', friends: ['Sam', 'Itan', 'Mat'], gender: 'female' }, + { + name: 'Mat', + friends: ['Sam', 'Sharon'], + gender: 'male' + }, { name: 'Brad', friends: ['Sally', 'Emily', 'Julia'], diff --git a/lib.js b/lib.js index 60f30ab..9787333 100644 --- a/lib.js +++ b/lib.js @@ -1,15 +1,74 @@ 'use strict'; -/** +function getFriendByName(name, friends) { + return friends.filter(function (friend) { + return friend.name === name; + })[0]; +} + +function getInvitedFriends(friends) { + var currentFriendsCircle = friends.filter(function (friend) { + return friend.best; + }); + var result = []; + var currentLevel = 1; + var friendsNames = []; + while (currentFriendsCircle.length !== 0) { + var nextLevelNames = []; + currentFriendsCircle = currentFriendsCircle.sort(function (a, b) { + return a.name.localeCompare(b.name); + }); + for (var i = 0; i < currentFriendsCircle.length; i++) { + var friend = currentFriendsCircle[i]; + result.push({ + level: currentLevel, + friend: friend + }); + friendsNames.push(friend.name); + nextLevelNames = nextLevelNames.concat(friend.friends); + } + currentFriendsCircle = nextLevelNames.filter(function (name) { + return friendsNames.indexOf(name) === -1; + }) + .map(function (name) { + return getFriendByName(name, friends); + }); + currentLevel++; + } + + return result; +} + + /** * Итератор по друзьям * @constructor * @param {Object[]} friends * @param {Filter} filter */ function Iterator(friends, filter) { - console.info(friends, filter); + if (!(filter instanceof Filter)) { + throw new TypeError('no filter'); + } + this.invitedFriends = getInvitedFriends(friends) + .filter(function (item) { + return filter.test(item.friend); + }); + + this.index = 0; } +Iterator.prototype.done = function () { + return this.invitedFriends.length <= this.index; +}; + +Iterator.prototype.next = function () { + if (this.done()) { + return null; + } + + return this.invitedFriends[this.index++].friend; +}; + /** * Итератор по друзям с ограничением по кругу * @extends Iterator @@ -19,15 +78,23 @@ function Iterator(friends, filter) { * @param {Number} maxLevel – максимальный круг друзей */ function LimitedIterator(friends, filter, maxLevel) { - console.info(friends, filter, maxLevel); + Iterator.call(this, friends, filter); + + this.invitedFriends = this.invitedFriends.filter(function (item) { + return item.level <= maxLevel; + }); } +LimitedIterator.prototype = Object.create(Iterator.prototype); + /** * Фильтр друзей * @constructor */ function Filter() { - console.info('Filter'); + this.test = function () { + return true; + }; } /** @@ -36,8 +103,11 @@ function Filter() { * @constructor */ function MaleFilter() { - console.info('MaleFilter'); + this.test = function (item) { + return item.gender === 'male'; + }; } +MaleFilter.prototype = Object.create(Filter.prototype); /** * Фильтр друзей-девушек @@ -45,8 +115,11 @@ function MaleFilter() { * @constructor */ function FemaleFilter() { - console.info('FemaleFilter'); + this.test = function (item) { + return item.gender === 'female'; + }; } +FemaleFilter.prototype = Object.create(Filter.prototype); exports.Iterator = Iterator; exports.LimitedIterator = LimitedIterator; diff --git a/lib.spec.js b/lib.spec.js index 91de106..92814e9 100644 --- a/lib.spec.js +++ b/lib.spec.js @@ -67,7 +67,8 @@ describe('Итераторы', function () { while (!femaleIterator.done()) { invitedFriends.push(femaleIterator.next()); } - + // console.info(friends); + // console.info(invitedFriends); assert.deepStrictEqual(invitedFriends, [ [friend('Sam'), friend('Sally')], [friend('Brad'), friend('Emily')],