рд╣реЗрд▓реЛ, рд╣реЗрдмреНрд░! рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ рдПрдХ рд╕рд░рд▓ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЪрд▓рддрд╛ рд╣реВрдБ - рдиреЛрдб.рдЬреЗрдПрд╕ рд▓рд┐рдВрдХ рд╢реЙрд░реНрдЯрдирд░ mysql-libmysqlclient, MooTools рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рд░реНрд╡рд░ рдкрд░, рдФрд░ jQuery рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ред рд▓реЗрдЦ рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рдкрд╛рдардХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА "рд╣реИрд▓реЛ рджреБрдирд┐рдпрд╛" рд╡реНрдпрд╛рдпрд╛рдо рдкреВрд░рд╛ рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░ рдиреЛрдб рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рд╕рдордЭ рдЪреБрдХреЗ рд╣реИрдВред
рдореБрдЭреЗ рдЖрдкрдХреЛ рддреБрд░рдВрдд рдЪреЗрддрд╛рд╡рдиреА рджреЗрдиреА рдЪрд╛рд╣рд┐рдП - рдореИрдВ рдЦреБрдж рдХреЛ рдиреЛрдб рдореЗрдВ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рдирд╣реАрдВ рдорд╛рдирддрд╛ рд╣реВрдВред рдореИрдВ рдХреЛрдб рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдФрд░ рдЖрджрд░реНрд╢ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рде рдЖрдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВред рд╢рд╛рдпрдж рдПрдХ рд╕рд╛рде рд╣рдо рд╢реБрд░реБрдЖрддреА рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╣рд╛рди рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдПрдВрдЧреЗред рдЗрд╕рд▓рд┐рдП - рд░рдЪрдирд╛рддреНрдордХ рдЖрд▓реЛрдЪрдирд╛ рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╕рд░реНрд╡рд░ MooTools
рдореИрдВ рдЖрд╡рд╢реНрдпрдХ-рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рд╣реЛрд▓реАрд╡реЗрдЯ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдореИрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдЖрдк рдЕрдиреНрдпрдерд╛ рдирд┐рд░реНрдгрдп рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрдк MooTools рдХреЛ рддреБрд░рдВрдд рдХрдиреЗрдХреНрдЯ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ - рдЖрдк рдЗрд╕реЗ рдмрд╕ рдирд╣реАрдВ рд▓реЗ рд╕рдХрддреЗ, рд╕рд░реНрд╡рд░ рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП ('./ MooTools') рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред
рдореБрдЭреЗ 12 рдЬреБрд▓рд╛рдИ рдХреЛ MooTools рдХреЗ рдЯреНрд╡реАрдЯ рдФрд░ рд▓рд┐рдВрдХ davidwalsh.name/mootools-node/s рджреНрд╡рд╛рд░рд╛ рдорджрдж рдорд┐рд▓реА рдереАред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЗрд╕ рддрд░рд╣ рдЬреБрдбрд╝рд╛:
require('./Lib/MooTools').apply(GLOBAL);
MySQL
рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХреБрдЫ NoSQL рдбреЗрдЯрд╛рдмреЗрд╕ рдЕрдзрд┐рдХ рдЙрдкрдпреБрдХреНрдд рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░рд╛ рд▓рдХреНрд╖реНрдп рдиреЛрдб рдореЗрдВ MySQL рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕реАрдЦрдирд╛ рдерд╛ред
рдореИрдВрдиреЗ рдмреБрдХрдорд╛рд░реНрдХ рд╕реЗ Node-mysql-libmysqlclient рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╡рд┐рд╖рдп рд▓рд┐рдпрд╛, рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рд▓реА рдФрд░ рдореИрдиреБрдЕрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдмрд┐рдирд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛ред
рдореИрдВрдиреЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ
Lib
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╣реА рдлреЗрдВрдХ рджрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрд╕рд╛рдиреА рд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
var conn = require('./Lib/mysql/mysql-libmysqlclient').createConnectionSync(); conn.connectSync('localhost', 'NAME', 'PASS', 'nodejs');
ServerResponse рдмрдврд╝рд╛рдПрдБ
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдореЗрдВ рд╣реЗрдбрд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ MooTools рд▓рд╛рдЧреВ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ ServerResponse рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк (рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ) рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛:
var http = require('http'); http.ServerResponse.implement({ // code - . , 200 (Ok) 404 (Not Found) // plain - true, - html header : function (code, plain) { this.writeHead(code, { 'Content-Type': plain ? 'text/plain' : 'text/html' }); }, // response.redirect('http://example.com') redirect : function (url, status) { this.writeHead(status || 302, { 'Content-Type' : 'text/plain', 'Location' : url }); this.write('Redirecting to ' + url); this.end(); } });
рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡рд╛рдпрд░рдлрд╝реНрд░реЗрдо
http.createServer(function (req, res) { // code will be here }).listen(8124, "127.0.0.1"); console.log('Server running at http://127.0.0.1:8124/');
рд▓рд┐рдВрдХ, Link.js
рдлрд╝рд╛рдЗрд▓
рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреАрди рдЧреБрдг рд╣реИрдВ - рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЖрдИрдбреА, рд╡рд╣ рдпреВрдЖрд░рдПрд▓ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╡рд╣ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреЛрдб рдЬреЛ рд╣рдорд╛рд░реЗ рд╢реЙрд░реНрдЯрдирд░ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред
рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╕реЗ рдХреЛрдб рдирд╣реАрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдЖрдИрдбреА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ, рдЗрд╕реЗ 36-рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рдгрд╛рд▓реА ([0-9a-z]) рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░реЗрдВрдЧреЗред
Link.getCode = function (id) { return id ? id.toString(36) : null; }; Link.fromCode = function (code) { return code ? parseInt(code, 36) : null; };
рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рд▓рд┐рдВрдХ рдХреНрд▓рд╛рд╕ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╕реНрд╡рдпрдВ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдо рд╕реНрдЯреИрдЯрд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рд╕реЗ рдкрд╣рд▓реЗ рд░рдЦрддреЗ рд╣реИрдВ:
Link = new Class({ initialize : function (obj) { // - this.setId(obj.id).id || this.setCode(obj.code); this.setUrl(obj.url); }, setId : function (id) { // id int this.id = (isNaN(id) || id <= 0) ? null : parseInt(id); return this; }, getId : function () { return this.id; }, setUrl : function (url) { this.url = url || null; return this; }, getUrl : function () { return this.url; }, setCode : function (code) { this.id = Link.fromCode(code); return this; }, getCode : function () { return Link.getCode(this.id); } });
рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рддрд╛рд▓рд┐рдХрд╛ рдмрдирд╛рдПрдВ рдФрд░ рд▓рд┐рдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдореЙрдбрд▓ рд▓рд┐рдЦреЗрдВ:
CREATE TABLE `shortLinks` ( `id` int(11) NOT NULL AUTO_INCREMENT, `url` varchar(512) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Model = new Class({ initialize : function (conn) { // this.conn = conn; }, create : function (args) { // , return new Link(args); }, get : function (link, fn) { // if (!link.getId()) throw 'EmptyId'; // . , link.id int var q = 'SELECT * FROM `shortLinks` WHERE `id` = ' + link.getId(); // . . this.conn.query(q, function (err, res) { if (err) throw err; res.fetchAll(function (err, rows) { if (err) throw err; // -, fn(rows.length ? link.setUrl(rows[0].url) : null); res.freeSync(); }); }); }, put : function (link, fn) { // url - , !! var q = 'INSERT INTO `shortLinks` (`id`, `url`) ' + 'VALUES (NULL , "' + this.conn.escapeSync(link.getUrl()) + '");' this.conn.query(q, function (err, res) { if (err) throw err; // fn(link.setId( // this.conn.lastInsertIdSync() )); }.bind(this)); } }); // exports.Link = Link; exports.Model = Model;
рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рдЗрди рдХреЛ рдЖрд░рдВрднреАрдХрд░рдг рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:
var linkModel = new (require('./Link').Model)(conn);
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрд╕рдкрд╛рд╕ рдХреЗ рдХреЛрд╖реНрдардХреЛрдВ рдХреА
require('./Link').Model
рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рдПрдХ
require
рд╡рд╕реНрддреБ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдЧрд╛ред
рд░реЗрдВрдбрд░рд░, Renderer.js
рдлрд╝рд╛рдЗрд▓
// require('./Lib/MooTools').apply(GLOBAL); // var url = require('url'); // var fs = require('fs'); exports.Renderer = new Class({ initialize : function (linkModel) { this.link = linkModel; } });
Link.Model рдХреА рддрд░рд╣ рд░реЗрдВрдбрд░рд░, рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬреЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдЙрд╕реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рд╣рдо рдХреАрдорддреА рдорд┐рд▓реАрд╕реЗрдХреЗрдВрдб рдирд╣реАрдВ рдЦреЛрддреЗ рд╣реИрдВред
рдЖрдзрд╛рд░ рд░рди рд╡рд┐рдзрд┐ рд╣реЛрдЧреА:
run : function (req, res) { var path = url.parse(req.url, true); if (path.query && 'add' in path.query) { var addUrl = path.query.add; // , , "example.com" // , default- if (!url.parse(addUrl).protocol) { addUrl = 'http://' + addUrl; } // this.add(res, addUrl); // ( url/!abc12 ) } else if (path.pathname.test(/^\/![0-9a-z]+$/)) { // (/!) this.send(res, path.pathname.substr(2)); } else { // this.index(res); } },
рд╣рдо рдЕрднреА рддрдХ рдирд╣реАрдВ рднреВрд▓реЗ рд╣реИрдВ - рд╣рдо рдереЛрдбрд╝рд╛ рд╕рдВрдкрд╛рджрд┐рдд
./init.js
var linkModel = new (require('./Link').Model)(conn); var renderer = new (require('./Renderer').Renderer)(linkModel); http.createServer(function (req, res) { renderer.run(req, res); }).listen(8124, "127.0.0.1");
рдХреНрдпреЛрдВрдХрд┐ рд▓рд┐рдВрдХ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ ajax, рд╣рдо рд╕рднреА рдХреА рдЬрд░реВрд░рдд рд╣реИ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рд▓рд┐рдЦрдиреЗ рдФрд░ рдЙрд╕рдХреЗ рдХреЛрдб рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ:
add : function (res, url) { res.header(200); this.link.put( this.link.create({ url : url }), function (link) { res.end(link.getCode()); } ); },
рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЫреЛрдЯреЗ рд▓рд┐рдВрдХ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ - рдЙрд╕реЗ рд╣реЗрд▓рдореЗрдЯ рднреЗрдЬреЗрдВ рдЬрд╣рд╛рдБ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рдпрд╛ рд╕реВрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдРрд╕рд╛ рдХреЛрдИ рд▓рд┐рдВрдХ рдирд╣реАрдВ рд╣реИ
send : function (res, code) { this.link.get( this.link.create({ code : code }), function (link) { if (link) { res.redirect(link.getUrl()); } else { res.header(404, true); res.end('There is not such url'); } } ); },
рдореБрдЦреНрдп рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП - рдмрд╕ index.html рдлрд╝рд╛рдЗрд▓ рдкреНрд░рд┐рдВрдЯ рдХрд░реЗрдВред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдореИрдВ рд╢реБрд░реБрдЖрдд рдореЗрдВ __dirname рдХреЗ рд╕рд╛рде рдкрде рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ рдЕрдиреНрдпрдерд╛ рдЖрдк рдкрд░реЗрд╢рд╛рдиреА рдореЗрдВ рдкрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ
index : function (res) { fs.readFile(__dirname + '/index.html', function (err, data) { if (err) throw err; res.header(200); res.end(data); }) }
рдореБрдЦреНрдп рдкреГрд╖реНрда
рдореБрдЦреНрдп рдкреГрд╖реНрда рдкрд░, рд╣рдо рдмрд╕ рдЗрддрдирд╛ рд╣реА рдХрд░реЗрдВрдЧреЗ - рд╣рдо Google gikvery рдХреЛ рд░реИрдк рд╕реЗ рдЬреЛрдбрд╝реЗрдВрдЧреЗ, рдПрдХ рдЗрдирдкреБрдЯ рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝реЗрдВрдЧреЗ рдФрд░ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓рд┐рдВрдХ рдХреЛ рдЫреЛрдЯрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдЧрд╛ - рддреЛ рд╣рдореЗрдВ ajax рдХреЗ рд╕рд╛рде рдирдП рд▓рд┐рдВрдХ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛, рд╣рдо рдЗрдирдкреБрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рддрд╣рдд рд╕реБрдВрджрд░ рдбрд┐рд╕реНрдкреНрд▓реЗ рдбрд┐рд╕реНрдкреНрд▓реЗ рдХрд░реЗрдВрдЧреЗред
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> node.js</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script>
$(function () { $('input[type=submit]').click(function() { var input = $('input[type=text]'); var url = input.val(); input.val(''); url && $.ajax({ url : './', data: ({ add : url }), success : function (data) { var result = location.protocol + '//' + location.host + '/!' + data; $('#url') .prepend( $('<dd>').append( $('<a>') .text(result) .attr('href', result) ) .hide() .fadeIn() ) .prepend( $('<dt>') .text(url) .hide() .fadeIn() ); } }); }) });
</script> </head> <body> <div id="form"> <input type="text" /> <input type="submit" /> </div> <dl id="url"></dl> </body> </html>
рд╡рд╣ рд╕рдм рд╣реИред
рдкрд░рд┐рдгрд╛рдо
рдореБрдЭреЗ рдЖрдкрдХреЛ рддреБрд░рдВрдд рдЪреЗрддрд╛рд╡рдиреА рджреЗрдиреА рдЪрд╛рд╣рд┐рдП - рдореИрдВ рдЖрдкрдХреЗ рд▓рд┐рдВрдХ рдХреА рд╕реБрд░рдХреНрд╖рд╛ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛, рд╕реЗрд╡рд╛ рдЕрддреНрдпрдВрдд рдкреНрд░рджрд░реНрд╢рдирдХрд╛рд░реА рд╣реИред
рдкреЗрд╕реНрдЯрдмрд┐рди рдкрд░ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рд╕рднреА рдХреЛрдб