{"id":283543,"date":"2017-03-19T17:35:20","date_gmt":"2017-03-19T14:35:20","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=283543"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=283543","title":{"rendered":"\u0418\u0433\u0440\u0430 \u00ab\u0421\u043b\u043e\u0432\u0430 \u0438\u0437 \u0441\u043b\u043e\u0432\u0430\u00bb. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435"},"content":{"rendered":"<p>\u041f\u0440\u043e\u0448\u043b\u044b\u043c \u043b\u0435\u0442\u043e\u043c \u044f \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b <a href=\"https:\/\/habrahabr.ru\/post\/308256\/\">\u0441\u0442\u0430\u0442\u044c\u044e<\/a> \u043e \u043c\u043e\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u0443\u0447\u0435\u0431\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435-\u0438\u0433\u0440\u0435 &quot;\u0421\u043b\u043e\u0432\u0430 \u0438\u0437 \u0441\u043b\u043e\u0432\u0430&quot;, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u043d\u0430 JavaScript. \u0412\u0440\u0435\u043c\u044f \u0438\u0434\u0435\u0442 \u0438, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0438\u0434\u0435\u0442 \u043d\u0435 \u043d\u0430\u043f\u0440\u0430\u0441\u043d\u043e. \u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0430\u0431\u0438\u0440\u0430\u044f\u0441\u044c \u0437\u043d\u0430\u043d\u0438\u0439, \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0438\u0434\u0435\u044e \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u043e\u0431\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043f\u043b\u043e\u0449\u0430\u0434\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u0433\u0440\u044b \u0441\u043e \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/fa0\/823\/767\/fa082376738e4e56af3233b39b651670.png\" alt=\"wordsgames.by\"\/><\/p>\n<p>  <a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"o-proekte\">\u041e \u043f\u0440\u043e\u0435\u043a\u0442\u0435<\/h2>\n<p>  <\/p>\n<p>\u0418\u0433\u0440\u043e\u0432\u043e\u0439 \u0441\u0430\u0439\u0442 \u00ab\u0418\u0433\u0440\u044b \u0441\u043e \u0441\u043b\u043e\u0432\u0430\u043c\u0438\u00bb \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0438\u0433\u0440 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438.<br \/>  \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438\u0433\u0440\u043e\u043a\u0438 \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0441\u044f \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u0438\u0433\u0440\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0442 \u0432 \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0435, \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c\u043e\u043c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041e\u043f\u044b\u0442 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 GitHub: <a href=\"https:\/\/github.com\/Ghivan\/wordsgames\">https:\/\/github.com\/Ghivan\/wordsgames<\/a><br \/>  \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: <a href=\"https:\/\/wordsgames.by\/login\/\">https:\/\/wordsgames.by\/login\/<\/a><\/p>\n<p>  <\/p>\n<h4 id=\"instrumenty-sozdaniya\">\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f<\/h4>\n<p>  <\/p>\n<p>\u0424\u0440\u043e\u043d\u0442\u044d\u043d\u0434 \u2014 Typescript, SCSS, Bootstrap, JQuery.<br \/>  \u0411\u044d\u043a\u044d\u043d\u0434 \u2014 PHP 7, MySQL.<\/p>\n<p>  <\/p>\n<h2 id=\"baza-dannyh\">\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0445\u0435\u043c\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/ca0\/e4f\/7ac\/ca0e4f7ac8d84295940977a769c48aaf.png\" alt=\"database schema\"\/><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0448\u0435\u0441\u0442\u0438 \u0442\u0430\u0431\u043b\u0438\u0446:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0440\u0435\u0441\u0443\u0440\u0441\u0430:<br \/> \n<ul>\n<li>dictionary \u2014 \u0442\u043e\u043b\u043a\u043e\u0432\u044b\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u044c;<\/li>\n<li>players \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0438\u0433\u0440\u043e\u043a\u0430\u0445;<\/li>\n<li>games \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0433\u0440;<\/li>\n<\/ul>\n<\/li>\n<li>\u0422\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u0433\u0440\u044b &quot;\u0421\u043b\u043e\u0432\u0430 \u0438\u0437 \u0441\u043b\u043e\u0432\u0430&quot;:<br \/> \n<ul>\n<li>wfw_levels \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u044d\u0442\u0430\u043f\u0430\u0445;<\/li>\n<li>wfw_scoreTable \u2014 \u043e\u0447\u043a\u0438 (\u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f) \u0438\u0433\u0440\u043e\u043a\u0430 ;<\/li>\n<li>wfw_levelsPassed \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u044d\u0442\u0430\u043f\u043e\u0432. <\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u044b players, wfw_levelsPassed \u0438 wfw_scoreTable \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0447\u0435\u0440\u0435\u0437 id \u0438\u0433\u0440\u043e\u043a\u0430. \u0422\u0430\u0431\u043b\u0438\u0446\u044b wfw_levels \u0438 wfw_levelsPassed \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u043b\u0435 word (\u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0443\u0440\u043e\u0432\u043d\u044f \u043d\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043e \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438).<br \/>  \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430 \u0435\u0441\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c (\u0434\u0430\u043d\u044c RPG), \u043e\u0431\u0449\u0438\u0439 \u0434\u043b\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u0430. \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u043f\u044b\u0442\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0438\u0438. \u0417\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0443\u0440\u043e\u0432\u043d\u044f \u0438\u0433\u0440\u043e\u043a\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432 \u0421\u0423\u0411\u0414, \u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0438 \u0442\u0440\u0438\u0433\u0433\u0435\u0440<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"sql\">DELIMITER $$  CREATE FUNCTION `countExp`(`lvl` INT) RETURNS int(11)     NO SQL     SQL SECURITY INVOKER     COMMENT '\u041f\u043e\u0434\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u043f\u044b\u0442\u0430 \u0434\u043b\u044f \u0443\u0440\u043e\u0432\u043d\u044f' BEGIN   DECLARE exp int; SET exp = FLOOR(1000 * (POW(1.1, lvl) - 1)); RETURN exp; END$$  DELIMITER ; -- \u0422\u0440\u0438\u0433\u0433\u0435\u0440, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0438\u0433\u0440\u043e\u043a\u0430: DELIMITER \/\/ CREATE TRIGGER `lvlCount` BEFORE UPDATE ON `players`  FOR EACH ROW BEGIN IF (NEW.exp &lt;&gt; OLD.exp AND NEW.exp &gt; 0) THEN IF NEW.exp &gt;= countExp(NEW.`level`) THEN WHILE NEW.exp &gt;= countExp(NEW.`level`)   DO     set NEW.level = NEW.level + 1;   END WHILE; ELSEIF  NEW.exp &lt; countExp(NEW.`level` - 1) THEN   WHILE NEW.exp &lt; countExp(NEW.`level` - 1)   DO     set NEW.level = NEW.level - 1;   END WHILE; END IF; END IF; END \/\/ DELIMITER ;<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<h2 id=\"soedinenie-s-bazoy-dannyh-iz-php\">\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 PHP<\/h2>\n<p>  <\/p>\n<p>\u0417\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0430\u0441\u0441 DB<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">class DB {     private static $dbc = null;      protected static function getConnection()     {          if (!self::$dbc){             try {                 self::$dbc = new PDO(&quot;mysql:host=&quot;.HOST.&quot;;dbname=&quot;.DB_NAME.&quot;;charset=UTF8&quot;, DB_USER, DB_PASSWORD);             } catch (Throwable $e) {                 ErrorLogger::logException($e);                 return null;             }         }         return self::$dbc;     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0438\u0433\u0440\u0430\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">class DBGamesGlobalInfo extends DB {     private static $queries = array(         'globalInfo' =&gt; 'SELECT id, name, rules, status, author, path  FROM games'     );      static function getGlobalInfo(){         try {             $stmt = parent::getConnection()-&gt;prepare(self::$queries['globalInfo']);             if (!$stmt-&gt;execute()){                 ErrorLogger::logFailedDBRequest($stmt-&gt;errorInfo(), $stmt-&gt;queryString,__LINE__, __FILE__);                 $message = '\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0438\u0433\u0440\u0430\u0445';                 throw new Exception($message);             }             return $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);         } catch (Throwable $e){             ErrorLogger::logException($e);             return null;         }     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<h2 id=\"avtorizaciya\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f, \u043a\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f id \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0412 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u043e\u0441\u0438\u0442 \u0443\u0447\u0435\u0431\u043d\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440 \u043f\u043e\u043a\u0430 \u0432\u0435\u0437\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0441\u0432\u043e\u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">class Authorization {     public static function check(){         if (session_status() !== PHP_SESSION_ACTIVE){             session_start();         }         return (isset($_SESSION['pl_id'])) ? true : false;     }     public static function logIn($playerId){         if (!defined('LOGIN_SCRIPT') || LOGIN_SCRIPT !== '\/login\/server_scenarios\/index.php') return false;          if (session_status() !== PHP_SESSION_ACTIVE){             session_start();         }         $_SESSION['pl_id'] = $playerId;         return (isset($_SESSION['pl_id'])) ? true : false;     }      public static function logOut(){         if (session_status() !== PHP_SESSION_ACTIVE){             session_start();         }         unset($_SESSION['pl_id']);         unset($_SESSION['cur_level']);     }      public static function getAuthorizedPlayerId(){         if (session_status() !== PHP_SESSION_ACTIVE){             session_start();         }         return isset($_SESSION['pl_id']) ? $_SESSION['pl_id'] : null;     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<h2 id=\"igra-slova-iz-slova\">\u0418\u0433\u0440\u0430 &quot;\u0421\u043b\u043e\u0432\u0430 \u0438\u0437 \u0441\u043b\u043e\u0432\u0430&quot;<\/h2>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u043e \u043d\u0430\u043f\u043e\u043c\u043d\u044e \u043f\u0440\u0430\u0432\u0438\u043b\u0430: \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043b\u043e\u0432\u0430 \u0438\u0437 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0441\u043b\u043e\u0432\u0430. \u0421\u043b\u043e\u0432\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0430\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0447\u0438\u0441\u043b\u0435. \u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u0435\u043b\u044c\u043d\u043e-\u043b\u0430\u0441\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f. \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u0441\u043b\u043e\u0432\u0430 \u2014 3 \u0431\u0443\u043a\u0432\u044b. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u0433\u0430\u0434\u0430\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 30% \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0441\u043b\u043e\u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412\u0438\u0434 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/555\/cf5\/d15\/555cf5d150df473395b7a59be1291460.png\" alt=\"Word from word\"\/><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c Ajax. <\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u043a\u0435\u043b\u0435\u0442 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0434\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;div class=&quot;row&quot;&gt;         &lt;div class=&quot;col-xs-4 col-sm-3 player-info&quot;&gt;             &lt;img src=&quot;\/_app_files\/players_avatars\/no_avatar.png&quot; alt=&quot;\u0412\u0430\u0448 \u0430\u0432\u0430\u0442\u0430\u0440&quot; class=&quot;img-responsive img-circle center-block avatar&quot; id=&quot;userAvatar&quot;&gt;             &lt;h2 id=&quot;userLoginLabel&quot;&gt;\u0418\u0433\u0440\u043e\u043a&lt;\/h2&gt;             &lt;p class=&quot;link-to-cabinet&quot;&gt;&lt;a href=&quot;\/cabinet\/&quot;&gt;\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043b\u0438\u0447\u043d\u044b\u0439 \u043a\u0430\u0431\u0438\u043d\u0435\u0442&lt;\/a&gt;&lt;\/p&gt;              &lt;div class=&quot;tablescore&quot;&gt;                 &lt;div&gt;\u042d\u0442\u0430\u043f: &lt;span id=&quot;level-number&quot;&gt;0&lt;\/span&gt;&lt;\/div&gt;                 &lt;div&gt;\u041e\u0447\u043a\u0438: &lt;span id=&quot;score-value&quot;&gt;0&lt;\/span&gt;&lt;\/div&gt;             &lt;\/div&gt;              &lt;div class=&quot;progress&quot;&gt;                 &lt;span&gt;\u0421\u043b\u043e\u0432 \u043e\u0442\u0433\u0430\u0434\u0430\u043d\u043e: &lt;span id=&quot;found-words-number&quot;&gt;0&lt;\/span&gt;\/&lt;span id=&quot;total-words-number&quot;&gt;0&lt;\/span&gt;&lt;\/span&gt;                 &lt;div id=&quot;user-progress-bar&quot; class=&quot;progress-bar&quot; role=&quot;progressbar&quot; aria-valuenow=&quot;0&quot; aria-valuemin=&quot;0&quot; aria-valuemax=&quot;0&quot;&gt; &lt;\/div&gt;             &lt;\/div&gt;              &lt;div class=&quot;level-map-box&quot;&gt;                 &lt;div class=&quot;label label-info&quot;&gt;\u041a\u0430\u0440\u0442\u0430 \u044d\u0442\u0430\u043f\u043e\u0432 &lt;span class=&quot;glyphicon glyphicon-triangle-bottom&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;                 &lt;div class=&quot;btn-group-sm&quot; id=&quot;level-buttons-container&quot;&gt;&lt;\/div&gt;             &lt;\/div&gt;              &lt;div class=&quot;tips&quot;&gt;                 &lt;div class=&quot;label label-info&quot;&gt;\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 &lt;span class=&quot;glyphicon glyphicon-triangle-bottom&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;                 &lt;div class=&quot;btn-group-sm&quot;&gt;                     &lt;a class=&quot;btn&quot;&gt;                         &lt;img id=&quot;word-definition-tip&quot; title=&quot;\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0442\u0433\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430.&quot; alt=&quot;\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0442\u0433\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430.&quot; src=&quot;images\/tips\/definition_gray.png&quot; draggable=&quot;false&quot;&gt;                     &lt;\/a&gt;                     &lt;a class=&quot;btn&quot;&gt;                         &lt;img id=&quot;hole-word-tip&quot; title=&quot;\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435\u043e\u0442\u0433\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c.&quot; alt=&quot;\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435\u043e\u0442\u0433\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c.&quot; src=&quot;images\/tips\/word_gray.png&quot; draggable=&quot;false&quot;&gt;                     &lt;\/a&gt;                 &lt;\/div&gt;             &lt;\/div&gt;          &lt;\/div&gt;          &lt;div class=&quot;col-xs-8 col-sm-9 gamefield&quot;&gt;             &lt;div id=&quot;missions-icon&quot; class=&quot;row missions&quot;&gt;                  &lt;img id=&quot;mission1-icon&quot; src=&quot;images\/missions\/incomplete.png&quot; alt=&quot;\u041f\u0435\u0440\u0432\u0430\u044f \u0437\u0432\u0435\u0437\u0434\u0430&quot; title=&quot;\u041e\u0442\u0433\u0430\u0434\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 40% \u0441\u043b\u043e\u0432&quot;&gt;                 &lt;img id=&quot;mission2-icon&quot; src=&quot;images\/missions\/incomplete.png&quot; alt=&quot;\u0412\u0442\u043e\u0440\u0430\u044f \u0437\u0432\u0435\u0437\u0434\u0430&quot;&gt;                 &lt;img id=&quot;mission3-icon&quot; src=&quot;images\/missions\/incomplete.png&quot; alt=&quot;\u0422\u0440\u0435\u0442\u044c\u044f \u0437\u0432\u0435\u0437\u0434\u0430&quot; title=&quot;\u041e\u0442\u0433\u0430\u0434\u0430\u0442\u044c 100% \u0441\u043b\u043e\u0432&quot;&gt;             &lt;\/div&gt;              &lt;div id=&quot;help-button&quot;&gt;&lt;a href=&quot;#help-box&quot; data-toggle=&quot;modal&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-question-sign&quot;&gt;&lt;\/span&gt;&lt;\/a&gt; &lt;\/div&gt;             &lt;!--\u0411\u043b\u043e\u043a \u043f\u043e\u043c\u043e\u0449\u0438--&gt;             &lt;div id=&quot;help-box&quot; class=&quot;modal fade&quot;&gt;                  &lt;!-- \u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e --&gt;                 &lt;div class=&quot;modal-dialog&quot;&gt;                      &lt;!--\u0412\u0441\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;                     &lt;div class=&quot;modal-content&quot;&gt;                          &lt;!-- \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;                         &lt;div class=&quot;modal-header&quot;&gt;                             &lt;button type=&quot;button&quot; class=&quot;close&quot; data-dismiss=&quot;modal&quot; aria-hidden=&quot;true&quot;&gt;\u00d7&lt;\/button&gt;                             &lt;h4 class=&quot;modal-title&quot;&gt;\u041f\u043e\u043c\u043e\u0449\u044c&lt;\/h4&gt;                         &lt;\/div&gt;                          &lt;!-- \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0434                         \u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;                         &lt;div class=&quot;modal-body&quot;&gt;                             &lt;!-- \u0422\u0435\u043a\u0441\u0442 \u043f\u0440\u0430\u0432\u0438\u043b --&gt;                         &lt;\/div&gt;                      &lt;\/div&gt;                     &lt;!--\u041a\u043e\u043d\u0435\u0446 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;                  &lt;\/div&gt;                 &lt;!--\u041a\u043e\u043d\u0435\u0446 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;              &lt;\/div&gt;             &lt;!--\u041a\u043e\u043d\u0435\u0446 \u0431\u043b\u043e\u043a\u0430 \u043f\u043e\u043c\u043e\u0449\u0438--&gt;              &lt;div id=&quot;user-input-word&quot; class=&quot;row&quot;&gt;&lt;\/div&gt;              &lt;div id=&quot;user-input-controls-btn&quot; class=&quot;row&quot;&gt;                 &lt;div id=&quot;clear-letter-btn&quot;&gt;\u0421\u0442\u0435\u0440\u0435\u0442\u044c \u0431\u0443\u043a\u0432\u0443&lt;\/div&gt;                 &lt;div id=&quot;clear-word-btn&quot;&gt;\u0421\u0442\u0435\u0440\u0435\u0442\u044c \u0432\u0441\u0435 \u0441\u043b\u043e\u0432\u043e&lt;\/div&gt;             &lt;\/div&gt;              &lt;div id=&quot;level-main-word&quot; class=&quot;row&quot;&gt;&lt;\/div&gt;              &lt;div id=&quot;user-found-words-box&quot; class=&quot;row&quot;&gt;&lt;\/div&gt;         &lt;\/div&gt;     &lt;\/div&gt;     &lt;!--\u043e\u043a\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439--&gt;     &lt;div id=&quot;message-modal-box&quot; class=&quot;modal fade&quot;&gt;          &lt;!-- \u041c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e --&gt;         &lt;div class=&quot;modal-dialog&quot;&gt;              &lt;!--\u0412\u0441\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;             &lt;div class=&quot;modal-content&quot;&gt;                 &lt;div class=&quot;modal-header&quot;&gt;                     &lt;button type=&quot;button&quot; class=&quot;close&quot; data-dismiss=&quot;modal&quot; aria-hidden=&quot;true&quot;&gt;\u00d7&lt;\/button&gt;                     &lt;h4 id=&quot;message-modal-header&quot;&gt;\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430&lt;\/h4&gt;                 &lt;\/div&gt;                  &lt;!-- \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;                 &lt;div class=&quot;modal-body&quot;&gt;                      &lt;p id=&quot;message-modal-content&quot;&gt;&lt;\/p&gt;                  &lt;\/div&gt;              &lt;\/div&gt;             &lt;!--\u041a\u043e\u043d\u0435\u0446 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;          &lt;\/div&gt;         &lt;!--\u041a\u043e\u043d\u0435\u0446 \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 --&gt;      &lt;\/div&gt;<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>class Controller{     private model: Model;     private view: View;     private freezeState: boolean = false;      constructor(){         this.view = new View();         this.model = new Model(this.onReceiveInitialData.bind(this), this.onError.bind(this));          $(document).on('tipClick',this.useTip.bind(this));         $(document).on('lvlBtnClick',this.changeLevel.bind(this));         $(document).on('letterClick', this.onLetterClick.bind(this));         $(document).on('foundWordClick',this.getWordDefinition.bind(this));         $(document).on('keydown', this.keyControls.bind(this));          $('#clear-letter-btn').on('click', this.removeLastLetter.bind(this));         $('#clear-word-btn').on('click', this.clearUserInput.bind(this));     } .......... }  class Model{     readonly tipsCost = {         holeWord: 250,         wordDefinition: 100     };     private login: string;     private avatar: string;     private level: number;     private totalLevelsNumber: number;     private levelsPassedNumber: number;     private levelWord: string;     private wordVariants: Array&lt;string&gt;;     private foundWords: Array&lt;string&gt;;     private score: number;     private userWord: string = '';     private missions: {         1: boolean,         2: boolean,         3: boolean     };     private missionUnique;     private dictionary = {};      constructor(success: ()=&gt; any, error: (message: string)=&gt;any, lvl?: number){         let that = this;         $.ajax({             url: 'server_scenarios\/index.php',             type: 'post',             data: {                 'action': 'getInitialInfo',                 'lvl' : (lvl) ? lvl : null             },             success: function (data) {                 if (data.state){                     that.initialize(data);                     success();                 } else {                     error(data.message);                 }             },             error: function(){                 error('\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c');             }         })     }      public initialize(data: ServerAnswerInitialData){         this.login = data.login;         this.avatar = data.avatar;         this.level = parseInt(data.level);         this.totalLevelsNumber = parseInt(data.totalLevelsNumber);         this.levelsPassedNumber = parseInt(data.levelsPassedNumber);         this.levelWord = data.levelWord;         this.wordVariants = data.wordVariants;         this.foundWords = data.foundWords;         this.score = parseInt(data.score);         this.missions = data.missions;         this.missionUnique = data.missionUnique;     } ........ }  class View{     private playerInfo: PlayerInfo;     private gamefield: Gamefield;     public loader: Loader;     constructor(){         this.loader = new Loader();         this.playerInfo = new PlayerInfo();         this.gamefield = new Gamefield();     }      public initializePlayerInfoBox(data: UserInfoData){         this.playerInfo.setNewAvatar(data.avatar);         this.playerInfo.setLoginLabel(data.login);         this.playerInfo.setLevelLabel(data.level.toString());         this.playerInfo.setScoreLabel(data.score);         this.playerInfo.setFoundWordsLabel(data.foundWordsNumber.toString());         this.playerInfo.setTotalWordsLabel(data.totalWordsNumber.toString());         this.playerInfo.setProgressBar(data.foundWordsNumber, data.totalWordsNumber);         this.playerInfo.createLevelMap(data.totalLevelsNumber, data.level, data.levelsPassedNumber);         if (data.tipsState.wordDefinition){             this.playerInfo.enableTip('wordDefinition');         }         if (data.tipsState.holeWord){             this.playerInfo.enableTip('holeWord');         }     }      public initializeGameField(data: GamefieldData){         for (let prop in data.missions){             if (data.missions.hasOwnProperty(prop)){                 (data.missions[prop]) ? this.showCompleteMissionStateIcon(parseInt(prop)): this.showIncompleteMissionStateIcon(parseInt(prop));             }         }         this.updateUserInputWord();         this.gamefield.printMainWordLetters(data.levelMainWord);          this.gamefield.clearFoundWordsBox();         if (data.foundWords){             for (let i = 0; i &lt; data.foundWords.length; i++){                 this.addFoundWord(data.foundWords[i]);             }         }         this.gamefield.setUniqueMissionTitle(data.missionUnique);     } .... }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">if (!defined('PLAYER_ID') || !defined('CURRENT_LEVEL')) exit(); header('Content-Type: application\/json');  $playerGlobalInfo = DBPlayerGlobalInfo::getGlobalInfo(PLAYER_ID); $playerProgressInfo = DBPlayerProgress::getProgressOnLvl(PLAYER_ID, CURRENT_LEVEL); $levelInfo = DBGameInfo::getLevelInfo(CURRENT_LEVEL);  echo json_encode(array(     'state' =&gt; true,     'login' =&gt; $playerGlobalInfo['login'],     'avatar' =&gt; file_exists($_SERVER['DOCUMENT_ROOT'] . $playerGlobalInfo['avatar']) ? $playerGlobalInfo['avatar'] : '\/_app_files\/players_avatars\/no_avatar.png',     'level' =&gt; CURRENT_LEVEL,     'totalLevelsNumber' =&gt; DBGameInfo::getLevelsQuantity(),     'levelsPassedNumber' =&gt; DBPlayerProgress::getPassedLvlQuantity(PLAYER_ID),     'levelWord' =&gt; $levelInfo['word'],     'wordVariants' =&gt; $levelInfo['wordVariants'],     'foundWords' =&gt; (empty($playerProgressInfo['foundWords'])) ? array() : $playerProgressInfo['foundWords'],     'score' =&gt; DBPlayerProgress::getScore(PLAYER_ID),     'missions' =&gt; array(         1 =&gt; (boolean) $playerProgressInfo['star1status'],         2 =&gt; (boolean) $playerProgressInfo['star2status'],         3 =&gt; (boolean) $playerProgressInfo['star3status']     ),     'missionUnique' =&gt; $levelInfo['missionUnique'] ));<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0438 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u044d\u0442\u0430\u043f\u0430. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u043d\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0441\u043a\u0443\u0448\u0435\u043d\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043b\u0435\u0437\u0442\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432 \u0441\u043a\u0440\u0438\u043f\u0442, \u0430 \u043f\u043e\u0442\u043e\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 100% \u0441\u043b\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0443 \u0440\u0430\u0434, \u0435\u0441\u043b\u0438 \u043a\u0442\u043e \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442 \u0432 \u043a\u0430\u043a\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043a\u043e\u043f\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430.<\/p>\n<p>  <\/p>\n<h3 id=\"proverka-slova-vvodimogo-igrokom\">\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043b\u043e\u0432\u0430, \u0432\u0432\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u043e\u043c<\/h3>\n<p>  <\/p>\n<p>\u0421\u043b\u043e\u0432\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 div&#8217;\u043e\u0432 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u043a\u0432\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0438. \u041f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043d\u0430 \u0431\u0443\u043a\u0432\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0431\u0443\u043a\u0432\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u0430, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u043c\u043e\u043c\u0443 \u0441\u043b\u043e\u0432\u0443 \u0438, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u0438\u043d\u0430 \u0441\u043b\u043e\u0432\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043b\u0438\u0431\u043e \u0440\u0430\u0432\u043d\u0430, \u0442\u043e \u043e\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435. \u0414\u0430\u043b\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u0430, \u0441\u043b\u043e\u0432\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043e\u0447\u043a\u043e\u0432 \u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<br \/>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u0431\u0443\u043a\u0432\u0430 \u0431\u044b\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430, \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0435\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0441\u043b\u043e\u0432\u0435. \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0439\u043d\u044f\u044f \u2014 \u0441\u0442\u0438\u0440\u0430\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u2014 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<br \/>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043b\u0438\u043a\u0430 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043a\u043b\u0438\u043a\u0430 \u043f\u043e \u0431\u0443\u043a\u0432\u0435<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>onLetterClick(e: CustomEvent): void{         if (this.freezeState) return;         this.freeze();         let letter = e.detail,             userWord = this.model.getUserInputWord();         if (!letter.hasClass('active')){             userWord += letter.text();             letter.data('order', userWord.length);             this.view.setActiveLetterState(letter);             this.view.updateUserInputWord(userWord);             this.model.updateUserInputWord(userWord);             if (userWord.length &gt;= 3){                 this.model.checkUserWord(userWord, this.onAlreadyFoundWord.bind(this), this.onNewFoundWord.bind(this), );             }         } else {             if (letter.data().order === userWord.length){                 letter.data('order', 0);                 userWord = userWord.substr(0, userWord.length-1);                 this.view.removeActiveLetterState(letter);                 this.view.updateUserInputWord(userWord);                 this.model.updateUserInputWord(userWord);             }         }     }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>checkUserWord(word: string, onAlreadyFound: (word) =&gt; any, onNewFound:(data: ServerAnswerCheckWord)=&gt;any){         let model = this;          if (this.foundWords.indexOf(word) &gt; -1){             onAlreadyFound(word);             return;         }         if (this.wordVariants.indexOf(word) &gt; -1){             $.ajax({                 url: 'server_scenarios\/index.php',                 type: 'post',                 data: {                     'action': 'checkWord',                     'userWord' : word                 },                 success: function (data) {                     if (data.state){                         model.score = data.score;                         model.foundWords = data.foundWords;                         let level_status = false;                         if ((data.lvl_status) &amp;&amp; (model.totalLevelsNumber &gt;= (model.level + 1))){                             level_status = true;                         }                          onNewFound({                             word: data.word,                             score: data.score,                             experience: data.experience,                             points: data.points,                             missions: data.missions,                             foundWordsNumber: data.foundWords.length,                             lvl_status: level_status                         });                     }                 }             })         }     }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">if (!defined('PLAYER_ID') || !defined('CURRENT_LEVEL') || empty($_POST['userWord'])) exit; header('Content-Type: application\/json');  $checker = new AddingWordChecker(PLAYER_ID,CURRENT_LEVEL,$_POST['userWord']);  echo json_encode(     $checker-&gt;getChangedData() );  class AddingWordChecker {     const POINTS_PER_LETTER = 4;     const EXPERIENCE_PER_WORD = 1;      const POINTS_FOR_LEVEL_COMPLETE = 150;     const EXPERIENCE_FOR_LEVEL_COMPLETE = 20;      const POINTS_FOR_FIRST_STAR = 1000;     const EXPERIENCE_FOR_FIRST_STAR = 50;      const POINTS_FOR_SECOND_STAR = 500;     const EXPERIENCE_FOR_SECOND_STAR = 30;      const POINTS_FOR_THIRD_STAR = 10000;     const EXPERIENCE_FOR_THIRD_STAR = 250;      const PERCENT_FOUND_FOR_LEVEL_COMPLETE = 0.3;     const PERCENT_FOUND_FOR_FIRST_STAR = 0.4;     const PERCENT_FOUND_FOR_THIRD_STAR = 1;      private $playerId;     private $state = false;     private $gameLevel;     private $levelStatus;     private $wordToCheck;     private $wordVariants;     private $foundWords;     private $star1status;     private $star2status;     private $star3status;     private $changedData = array();      function __construct($playerId, $gameLevel, $wordToCheck)     {         $wordToCheck = strip_tags($wordToCheck);          $this-&gt;playerId = $playerId;         $this-&gt;gameLevel = $gameLevel;         $this-&gt;wordVariants = DBGameInfo::getWordVariantsOnLvl(CURRENT_LEVEL);          $playerProgress = DBPlayerProgress::getProgressOnLvl($playerId, $gameLevel);         $this-&gt;levelStatus = $playerProgress['lvl_status'];         $this-&gt;foundWords = (empty($playerProgress['foundWords'])) ? array()  : $playerProgress['foundWords'];         $this-&gt;star1status = $playerProgress['star1status'];         $this-&gt;star2status = $playerProgress['star2status'];         $this-&gt;star3status = $playerProgress['star3status'];          $this-&gt;wordToCheck = $wordToCheck;          if (!$this-&gt;checkWord()){             $this-&gt;changedData['state']  = false;             $this-&gt;changedData['message'] = '\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e';             return;         }          $this-&gt;addWord();     }      public function getChangedData(){         $this-&gt;changedData['state'] = $this-&gt;state;         $this-&gt;changedData['score'] = DBPlayerProgress::getScore($this-&gt;playerId);         $this-&gt;changedData['word'] = $this-&gt;wordToCheck;         return $this-&gt;changedData;     }      private function checkWord(){         if ((array_search($this-&gt;wordToCheck, $this-&gt;foundWords) !== false) ||             (array_search($this-&gt;wordToCheck, $this-&gt;wordVariants) === false)) {             $this-&gt;state = false;         } else {             $this-&gt;state = true;         }         return $this-&gt;state;     }      private function addWord(){         if (!$this-&gt;state) return;          array_push($this-&gt;foundWords, $this-&gt;wordToCheck);         DBPlayerProgress::updateFoundWords($this-&gt;playerId, $this-&gt;gameLevel, $this-&gt;foundWords);         $this-&gt;changedData['foundWords'] = $this-&gt;foundWords;          $this-&gt;calculatePointsForWordLength();         $this-&gt;checkLvlStatus();         $this-&gt;checkMissions();         DBPlayerProgress::augmentScore($this-&gt;playerId, $this-&gt;changedData['points']);         DBPlayerGlobalInfo::augmentExperience($this-&gt;playerId, $this-&gt;changedData['experience']);     }      private function addPoints($points){         if (isset($this-&gt;changedData['points'])){             $this-&gt;changedData['points'] += $points;         } else {             $this-&gt;changedData['points'] = $points;         }     }      private function addExperience($experience){         if (isset($this-&gt;changedData['experience'])){             $this-&gt;changedData['experience'] += $experience;         } else {             $this-&gt;changedData['experience'] = $experience;         }     }      private function calculatePointsForWordLength(){         $wordLength = mb_strlen($this-&gt;wordToCheck);         $points = $wordLength * $this::POINTS_PER_LETTER;         $experience = $this::EXPERIENCE_PER_WORD;         switch ($wordLength){             case (($wordLength &gt; 3) &amp;&amp; ($wordLength &lt;= 5)):                 $points *= 1.1;                 $experience *= 2;                 break;             case (($wordLength &gt; 5) &amp;&amp; ($wordLength &lt;= 7)):                 $points *= 1.2;                 $experience *= 3;                 break;             case (($wordLength &gt; 7) &amp;&amp; ($wordLength &lt;= 9)):                 $points *= 1.3;                 $experience *= 4;                 break;             case ($wordLength &gt;= 10):                 $points *= 2;                 $experience *= 10;                 break;         }          $this-&gt;addPoints(floor($points));         $this-&gt;addExperience(floor($experience));     }      private function checkLvlStatus(){         if ((!$this-&gt;levelStatus) &amp;&amp;             (count($this-&gt;foundWords) &gt;= count($this-&gt;wordVariants)* $this::PERCENT_FOUND_FOR_LEVEL_COMPLETE)){             $this-&gt;levelStatus = true;             DBPlayerProgress::completeLevel($this-&gt;playerId, $this-&gt;gameLevel);             $this-&gt;changedData['lvl_status'] = $this-&gt;levelStatus;              $this-&gt;addPoints($this::POINTS_FOR_LEVEL_COMPLETE);             $this-&gt;addExperience($this::EXPERIENCE_FOR_LEVEL_COMPLETE);         }     }      private function checkMissions(){         $this-&gt;changedData['missions'] = array();         $this-&gt;checkFirstStarMission();         $this-&gt;checkSecondStarMission();         $this-&gt;checkThirdStarMission();     }      private function checkFirstStarMission(){         if ($this-&gt;star1status) return;         if (count($this-&gt;foundWords) &gt;= count($this-&gt;wordVariants)* $this::PERCENT_FOUND_FOR_FIRST_STAR){             $this-&gt;star1status = true;             DBPlayerProgress::setCompleteStatusOnMission($this-&gt;playerId, $this-&gt;gameLevel, 1);             $this-&gt;changedData['missions']['star1status'] = $this-&gt;star1status;              $this-&gt;addPoints($this::POINTS_FOR_FIRST_STAR);             $this-&gt;addExperience($this::EXPERIENCE_FOR_FIRST_STAR);         }     }      private function checkSecondStarMission(){         if ($this-&gt;star2status) return;         $uniqueMission = DBGameInfo::getUniqueMission($this-&gt;gameLevel);         $letter = array_keys($uniqueMission)[0];         $quantity = array_values($uniqueMission)[0];         $pattern = '\/^'.$letter.'+\/u';         $matches = preg_grep($pattern, $this-&gt;foundWords);         if (count($matches) &gt;= $quantity){             $this-&gt;star2status = true;             DBPlayerProgress::setCompleteStatusOnMission($this-&gt;playerId, $this-&gt;gameLevel, 2);             $this-&gt;changedData['missions']['star2status'] = $this-&gt;star2status;              $this-&gt;addPoints($this::POINTS_FOR_SECOND_STAR);             $this-&gt;addExperience($this::EXPERIENCE_FOR_SECOND_STAR);         }     }      private function checkThirdStarMission(){         if ($this-&gt;star3status) return;         if (count($this-&gt;foundWords) &gt;= count($this-&gt;wordVariants)* $this::PERCENT_FOUND_FOR_THIRD_STAR){             $this-&gt;star3status = true;             DBPlayerProgress::setCompleteStatusOnMission($this-&gt;playerId, $this-&gt;gameLevel, 3);             $this-&gt;changedData['missions']['star3status'] = $this-&gt;star3status;              $this-&gt;addPoints($this::POINTS_FOR_THIRD_STAR);             $this-&gt;addExperience($this::EXPERIENCE_FOR_THIRD_STAR);         }     } } <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<h2 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e\u0442, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0438 \u0432\u043a\u0440\u0430\u0442\u0446\u0435 \u043e \u043c\u043e\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0415\u0441\u043b\u0438 \u043a\u043e\u0433\u043e-\u0442\u043e \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u0441 \u0440\u0430\u0434\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u0432\u0435\u0447\u0443. \u0411\u0443\u0434\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d \u0437\u0430 \u043b\u044e\u0431\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f, \u0430 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430 \u0441\u043e\u0432\u0435\u0442, \u0447\u0442\u043e \u0438 \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0443\u0447\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>  <\/p>\n<p>@\u0413\u0443\u043c\u0430\u043d\u0438\u0442\u0430\u0440\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0447\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0442\u0435\u0445\u043d\u0430\u0440\u0435\u043c<\/p>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/324282\/\"> https:\/\/habrahabr.ru\/post\/324282\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u043e\u0448\u043b\u044b\u043c \u043b\u0435\u0442\u043e\u043c \u044f \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b <a href=\"https:\/\/habrahabr.ru\/post\/308256\/\">\u0441\u0442\u0430\u0442\u044c\u044e<\/a> \u043e \u043c\u043e\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u0443\u0447\u0435\u0431\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435-\u0438\u0433\u0440\u0435 &quot;\u0421\u043b\u043e\u0432\u0430 \u0438\u0437 \u0441\u043b\u043e\u0432\u0430&quot;, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u043d\u0430 JavaScript. \u0412\u0440\u0435\u043c\u044f \u0438\u0434\u0435\u0442 \u0438, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0438\u0434\u0435\u0442 \u043d\u0435 \u043d\u0430\u043f\u0440\u0430\u0441\u043d\u043e. \u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0430\u0431\u0438\u0440\u0430\u044f\u0441\u044c \u0437\u043d\u0430\u043d\u0438\u0439, \u044f \u0440\u0435\u0448\u0438\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0438\u0434\u0435\u044e \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u043e\u0431\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043f\u043b\u043e\u0449\u0430\u0434\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u0433\u0440\u044b \u0441\u043e \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/fa0\/823\/767\/fa082376738e4e56af3233b39b651670.png\" alt=\"wordsgames.by\"\/><\/p>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-283543","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/283543","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=283543"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/283543\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=283543"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=283543"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=283543"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}