From 9ff3ddc498fb9a04a141e3bd12d8eba718cf9ea1 Mon Sep 17 00:00:00 2001 From: Sergey Gogolev Date: 2016年10月11日 17:53:02 +0500 Subject: [PATCH 1/3] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 15 ++++++++++ .eslintrc.json | 3 ++ .gitignore | 3 ++ .npmrc | 2 ++ .travis.yml | 3 ++ README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++- index.js | 44 ++++++++++++++++++++++++++++++ package.json | 13 +++++++++ phone-book.js | 62 ++++++++++++++++++++++++++++++++++++++++++ phone-book.spec.js | 61 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .travis.yml create mode 100644 index.js create mode 100644 package.json create mode 100644 phone-book.js create mode 100644 phone-book.spec.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..936d024 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true + +[*.json] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..db814bf --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "hrundel/node" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d48db5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +/node_modules +*.log diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..f5357d5 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +save=true +save-exact=true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4909f83 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "6" diff --git a/README.md b/README.md index 07fbe88..133405a 100644 --- a/README.md +++ b/README.md @@ -1 +1,67 @@ -# javascript-task-2 \ No newline at end of file +# Задача «Телефонная книга» + +Перед выполнением задания внимательно прочитайте: + +- [О всех этапах проверки задания](https://github.com/urfu-2016/guides/blob/master/workflow/extra.md) +- [Как отправить пулл](https://github.com/urfu-2016/guides/blob/master/workflow/pull.md) +- [Как пройти тесты](https://github.com/urfu-2016/guides/blob/master/workflow/test.md) +- Правила оформления [javascript](https://github.com/urfu-2016/guides/blob/master/codestyle/js.md), [HTML](https://github.com/urfu-2016/guides/blob/master/codestyle/html.md) и [CSS](https://github.com/urfu-2016/guides/blob/master/codestyle/css.md) кода +- [Лекцию «Типы данных»](https://urfu-2016.github.io/javascript-slides/02-types/#/) + + +## Основное задание + +> Мы очень хотим, чтобы код вы написали сами, а не пользовались внешними библиотеками. + +Как известно, каждый уважающий себя разработчик должен в жизни сделать три вещи: +- [x] посадить DOM дерево +- [x] построить абстракцию +- [ ] ~~вырастить~~ написать телефонную книгу + +Предлагаем вам пройти легкий путь становления уважающего себя разработчика и реализовать для скрипта телефонной книги __phone-book.js__ ряд необходимых методов. + +Метод __add__ для добавления записей: +* На вход принимает «Телефон», «Имя» и «Электронную почту» +* Возвращает true или false в зависимости от успеха опереации +* Телефоны принимаются **только** в формате 5556667788 (без кода) + +Метод __update__ для обновления записей: +* На вход принимает «Телефон», «Имя» и «Электронную почту» +* Обновляет «Имя» и «Электронную почту» по заданному «Телефону» +* Возвращает true или false в зависимости от успеха опереации +* «Электронную почту» можно стереть (не передав последний параметр), а «Имя» – нет + +Метод __find__ для поиска записей: +* На вход принимает запрос в виде строки +* Ищет вхождение этой строки хотя бы в одно из полей «Телефон», «Имя» и «Электронную почту» +* Возвращает отсортированный по «Имени» массив строк в формате `name, phone, email` +* «Имя» и «Электронную почту» выводит как есть, а «Телефон» в формате `+7 (555) 666-77-88` +* Пустой запрос не должен ничего не находить +* Запрос «*» находит все записи + +Метод __findAndRemove__ для удаления записей: +* На вход принимает запрос в виде строки +* Находит (смотри __find__) и удаляет все найденные записи +* Возвращает число удаленных записей + +В файле _index.js_ вы можете найти примеры использования получившегося скриптика. + +## Дополнительное задание + +> Перед выполнением внимательно прочитайте [про особенности](https://github.com/urfu-2016/guides/blob/master/workflow/extra.md) + +По одной добавлять записи в книгу не очень удобно, поэтому будет здорово, если вы добавите в решение импорт данных из csv. Для этого реализуйте код метода __importFromCsv__. + +На вход метод принимает строку в формате csv. Если запись в телефонной книги уже есть – обновляет/дополняет её данными из csv строки. На выходе метод возвращает одно число добавленных/обновленных записей. + +Пример работы этого метода вы может отыскать в _index.js_ и в тестах. + +## Полезные ссылки + +- [Знакомимся с массивами](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array) +- [Пытаемся знакомиться с регулярными выражениями](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp) +- [Перебираем ключи объектов](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) +- [Метод indexOf для строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) +- [Метод slice для строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/slice) + +Позвони мне, позвони diff --git a/index.js b/index.js new file mode 100644 index 0000000..9b259f5 --- /dev/null +++ b/index.js @@ -0,0 +1,44 @@ +'use strict'; + +var phoneBook = require('./phone-book'); + +// Эти записи добавятся, вернется true +phoneBook.add('5554440044', 'Григорий', 'grisha@example.com'); +phoneBook.add('5552220022', 'Борис', 'boris@example.com'); +phoneBook.add('5551110011', 'Алекс'); +phoneBook.add('5553330033', 'Валерий', 'valera@example.com'); + +// Эти запись не добавятся +phoneBook.add('3330033', 'Неизвестный', 'unknown@example.com'); +phoneBook.add('5551110011', 'Алексей'); +phoneBook.add('5555550055'); + +// Обновление +phoneBook.update('5551110011', 'Алексей', 'alex@example.com'); +phoneBook.update('5553330033', 'Валерий'); + +// В следующих примерах вернутся все записи +console.info(phoneBook.find('*')); +console.info(phoneBook.find('555')); +// Вывод будет следующий +// [ +// 'Алексей, +7 (555) 111-00-11, alex@example.com', +// 'Борис, +7 (555) 222-00-22, boris@example.com', +// 'Валерий, +7 (555) 333-00-33', +// 'Григорий, +7 (555) 444-00-44, grisha@example.com' +// ] + +// Удаление +phoneBook.findAndRemove('@'); // returns 3 + +if (phoneBook.isStar) { + // Импортируем из csv + var csv = [ + 'Борис;5552220022;boris@example.com', + 'Григорий;5554440044;grisha@example.com', + 'Алексей;5551110011;alex@example.com', + 'Валерий;5553330033;valera@example.com', + 'Неизвестный;3330033;unknown@example.com' + ].join('\n'); + phoneBook.importFromCsv(csv); // returns 4 +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1400772 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "main": "phone-book.js", + "scripts": { + "lint": "eslint .", + "test": "eslint . && mocha *.spec.js" + }, + "dependencies": { + "eslint": "3.7.0", + "eslint-config-hrundel": "latest", + "mocha": "3.1.0" + } +} diff --git a/phone-book.js b/phone-book.js new file mode 100644 index 0000000..69fb468 --- /dev/null +++ b/phone-book.js @@ -0,0 +1,62 @@ +'use strict'; + +/** + * Сделано задание на звездочку + * Реализован метод importFromCsv + */ +exports.isStar = true; + +/** + * Телефонная книга + */ +var phoneBook; + +/** + * Добавление записи в телефонную книгу + * @param {String} phone + * @param {String} name + * @param {String} email + */ +exports.add = function (phone, name, email) { + +}; + +/** + * Обновление записи в телефонной книге + * @param {String} phone + * @param {String} name + * @param {String} email + */ +exports.update = function (phone, name, email) { + +}; + +/** + * Удаление записей по запросу из телефонной книги + * @param {String} query + */ +exports.findAndRemove = function (query) { + +}; + +/** + * Поиск записей по запросу в телефонной книге + * @param {String} query + */ +exports.find = function (query) { + +}; + +/** + * Импорт записей из csv-формата + * @star + * @param {String} csv + * @returns {Number} – количество добавленных и обновленных записей + */ +exports.importFromCsv = function (csv) { + // Парсим csv + // Добавляем в телефонную книгу + // Либо обновляем, если запись с таким телефоном уже существует + + return csv.split('\n').length; +}; diff --git a/phone-book.spec.js b/phone-book.spec.js new file mode 100644 index 0000000..1b62a1a --- /dev/null +++ b/phone-book.spec.js @@ -0,0 +1,61 @@ +/* eslint-env mocha */ +'use strict'; + +var assert = require('assert'); + +var phoneBook = require('./phone-book'); + +describe('phone-book', function () { + it('должен добавлять записи', function () { + assert.ok(phoneBook.add('5554440044', 'Григорий', 'grisha@example.com')); + assert.ok(phoneBook.add('5552220022', 'Борис', 'boris@example.com')); + assert.ok(phoneBook.add('5551110011', 'Алекс')); + assert.ok(phoneBook.add('5553330033', 'Валерий', 'valera@example.com')); + }); + + it('не должен добавлять неправильные записи', function () { + assert.ok(!phoneBook.add('3330033', 'Неизвестный', 'unknown@example.com')); + assert.ok(!phoneBook.add('5551110011', 'Алексей')); + assert.ok(!phoneBook.add('5555550055')); + }); + + it('должен обновлять существующие записи', function () { + assert.ok(phoneBook.update('5551110011', 'Алексей', 'alex@example.com')); + assert.ok(phoneBook.update('5553330033', 'Валерий')); + }); + + it('должен искать все записи по запросу "*"', function () { + assert.deepStrictEqual(phoneBook.find('*'), [ + 'Алексей, +7 (555) 111-00-11, alex@example.com', + 'Борис, +7 (555) 222-00-22, boris@example.com', + 'Валерий, +7 (555) 333-00-33', + 'Григорий, +7 (555) 444-00-44, grisha@example.com' + ]); + }); + + it('должен искать все записи по запросу "555"', function () { + assert.deepStrictEqual(phoneBook.find('555'), [ + 'Алексей, +7 (555) 111-00-11, alex@example.com', + 'Борис, +7 (555) 222-00-22, boris@example.com', + 'Валерий, +7 (555) 333-00-33', + 'Григорий, +7 (555) 444-00-44, grisha@example.com' + ]); + }); + + it('должен удалять элементы из телефонной книги', function () { + assert.strictEqual(phoneBook.findAndRemove('@'), 3); + }); + + if (phoneBook.isStar) { + it('должен экспортировать из cvs', function () { + var csv = [ + 'Борис;5552220022;boris@example.com', + 'Григорий;5554440044;grisha@example.com', + 'Алексей;5551110011;alex@example.com', + 'Валерий;5553330033;valera@example.com', + 'Неизвестный;3330033;unknown@example.com' + ].join('\n'); + assert.strictEqual(phoneBook.importFromCsv(csv), 4); + }); + } +}); From 5f06998908a0ce4bbbe20d6fe1cb1befe15b400b Mon Sep 17 00:00:00 2001 From: irina Date: 2016年10月14日 01:18:44 +0500 Subject: [PATCH 2/3] =?UTF-8?q?=D0=A2=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D0=BA=D0=BD=D0=B8=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phone-book.js | 147 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 25 deletions(-) diff --git a/phone-book.js b/phone-book.js index 69fb468..f0425d1 100644 --- a/phone-book.js +++ b/phone-book.js @@ -9,42 +9,127 @@ exports.isStar = true; /** * Телефонная книга */ -var phoneBook; +var phoneBook = []; + + + // Добавление записи в телефонную книгу + // @param {String} phone + // @param {String} name + // @param {String} email -/** - * Добавление записи в телефонную книгу - * @param {String} phone - * @param {String} name - * @param {String} email - */ exports.add = function (phone, name, email) { + if (phone.length !== 10 || isNaN(Number(phone)) || typeof name !== 'string' || name === '') { + return false; + } + if (takevalueOnKey('phone').indexOf(phone) === -1) { + phoneBook.push({ 'phone': phone, 'name': name, 'email': email }); + + return true; + } + return false; }; +function takevalueOnKey(key) { + var phones = []; + phoneBook.forEach(function takePhones(item) { + phones.push(item[key]); + }); -/** - * Обновление записи в телефонной книге - * @param {String} phone - * @param {String} name - * @param {String} email - */ + return phones; +} + + + // Обновление записи в телефонной книге + // @param {String} phone + // @param {String} name + // @param {String} email exports.update = function (phone, name, email) { + if (typeof name !== 'string' || name === '') { + return false; + } + if (phone.length !== 10 || isNaN(Number(phone))) { + return false; + } + var index = takevalueOnKey('phone').indexOf(phone); + if (index !== -1) { + phoneBook[index].name = name; + phoneBook[index].email = email; + + return true; + } + + return false; }; -/** - * Удаление записей по запросу из телефонной книги - * @param {String} query - */ + + // Удаление записей по запросу из телефонной книги + // @param {String} query + exports.findAndRemove = function (query) { + var indexs = findIndexs(query); + var newBookPhone = []; + phoneBook.forEach(function remove(item, ind) { + if (indexs.indexOf(ind) === -1) { + newBookPhone.push(item); + } + }); + phoneBook = newBookPhone; + return indexs.length; }; -/** - * Поиск записей по запросу в телефонной книге - * @param {String} query - */ + + // Поиск записей по запросу в телефонной книге + // @param {String} query + +function createFindBook(indexes) { + var newBook = []; + var str = ''; + var phone = ''; + phoneBook.forEach(function choise(item, index) { + if (indexes.indexOf(index) !== -1) { + phone = phoneBook[index].phone; + var temp = '+7 (' + phone.slice(0, 3) + ') ' + phone.slice(3, 6); + temp += '-' + phone.slice(6, 8) + '-' + phone.slice(8, 10); + var email = phoneBook[index].email; + email = typeof email === 'undefined' ? '' : ', ' + email; + str = phoneBook[index].name + ', ' + temp + email; + newBook.push(str); + } + }); + + return newBook; +} + +function findIndexs(query) { + if (query === '' || typeof query !== 'string') { + return []; + } + var indexs = []; + if (query === '*') { + phoneBook.forEach(function generateInd(item, ind) { + indexs.push(ind); + }); + } else { + phoneBook.forEach(function findInd(item, ind) { + var сondition = item.phone.indexOf(query) !== -1 || item.name.indexOf(query) !== -1; + if (typeof item.email !== 'undefined') { + сondition = сondition || item.email.indexOf(query) !== -1; + } + if (сondition) { + indexs.push(ind); + } + }); + } + + return indexs; +} + + exports.find = function (query) { + return createFindBook(findIndexs(query)).sort(); }; /** @@ -54,9 +139,21 @@ exports.find = function (query) { * @returns {Number} – количество добавленных и обновленных записей */ exports.importFromCsv = function (csv) { - // Парсим csv - // Добавляем в телефонную книгу - // Либо обновляем, если запись с таким телефоном уже существует + var count = 0; + csv = csv.split('\n'); + csv.forEach(function pasre(item) { + var values = item.split(';'); + var name = values[0]; + var phone = values[1]; + var email = values[2]; + if (!exports.update(phone, name, email)) { + if (exports.add(phone, name, email)) { + count++; + } + } else { + count++; + } + }); - return csv.split('\n').length; + return count; }; From 31a99dc82035709a1273707129b3b1e53cfed654 Mon Sep 17 00:00:00 2001 From: irina Date: 2016年10月14日 02:03:00 +0500 Subject: [PATCH 3/3] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=D0=B0=20=D0=B5=D1=89=D1=91=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BA=D0=BE=D1=80=D1=80?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D1=84=D0=BE=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phone-book.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/phone-book.js b/phone-book.js index f0425d1..7001fea 100644 --- a/phone-book.js +++ b/phone-book.js @@ -18,9 +18,13 @@ var phoneBook = []; // @param {String} email exports.add = function (phone, name, email) { - if (phone.length !== 10 || isNaN(Number(phone)) || typeof name !== 'string' || name === '') { + if (typeof name !== 'string' || name === '') { + return false; + } + if (notCorrectPhone(phone)) { return false; } + if (takevalueOnKey('phone').indexOf(phone) === -1) { phoneBook.push({ 'phone': phone, 'name': name, 'email': email }); @@ -38,6 +42,9 @@ function takevalueOnKey(key) { return phones; } +function notCorrectPhone(phone) { + return (phone.match(/^\d+$/) === null || phone.length !== 10 || isNaN(Number(phone))); +} // Обновление записи в телефонной книге // @param {String} phone @@ -47,7 +54,7 @@ exports.update = function (phone, name, email) { if (typeof name !== 'string' || name === '') { return false; } - if (phone.length !== 10 || isNaN(Number(phone))) { + if (notCorrectPhone(phone)) { return false; }

AltStyle によって変換されたページ (->オリジナル) /