commit 2dade963083b337681a2af11392327da0c5396d9 Author: Михаил Капелько Date: Tue Apr 13 14:39:39 2021 +0300 ввести Уведомитель и Мир diff --git a/001.мир.js b/001.мир.js new file mode 100644 index 0000000..22429e7 --- /dev/null +++ b/001.мир.js @@ -0,0 +1,182 @@ +/* + * + * Реализация шаблона "издатель-подписчик" + * + */ + +function Уведомитель() +{ + function Подписка(id, отклик, уведомитель) + { + this.id = id; + this.отклик = отклик; + this.уведомитель = уведомитель; + }; + + this.уведомить = function() + { + // Попутно собираем подписки без отклика. + var безотклика = []; + for (var номер in this.подписки) + { + var подписка = this.подписки[номер]; + if (подписка.отклик) + { + подписка.отклик(); + } + else + { + безотклика.push(подписка); + } + } + + // И удаляем их. + if (безотклика.length) + { + this._удалитьПодпискиБезОтклика(безотклика); + } + }; + + this.подписать = function(отклик) + { + var id = this._сгенерироватьUUID(); + var подписка = new Подписка(id, отклик, this); + this.подписки.push(подписка); + return подписка; + }; + + this.отписать = function(подписка) + { + подписка.отклик = null; + }; + + this._удалитьПодпискиБезОтклика = function(удалить) + { + var подписка = удалить.shift() + while (подписка) + { + var индекс = this.подписки.indexOf(подписка); + if (индекс !== -1) + { + this.подписки.splice(индекс, 1); + } + var подписка = удалить.shift() + } + }; + + this._сгенерироватьUUID = function() + { + // https://stackoverflow.com/a/2117523 + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( + /[xy]/g, + function(c) + { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + } + ); + }; + + // Конструктор. + this.подписки = []; +} + +/* + * + * Связь событий и реакций в виде последовательности (череды) + * + */ + +function Мир() +{ + // Разобрать события и реакции, выраженные в тексте. + this.разобрать = function(череда) + { + var соответствия = this._событияРеакции(череда); + for (var событие in соответствия) + { + if (!(событие in this.события)) + { + this.события[событие] = new Уведомитель(); + } + var реакции = соответствия[событие]; + for (var номер in реакции) + { + const реакция = реакции[номер]; + const название = this._имяФункцииИзРеакции(реакция); + const функция = eval(название); + var тут = this; + this.события[событие].подписать(function(){ + функция(тут); + }); + } + } + }; + + // Уведомить о событии при его наличии. + this.уведомить = function(событие) + { + if (событие in this.события) + { + this.события[событие].уведомить(); + } + }; + + // Разобрать текст с событиями и реакциями, вернуть словарь их соответствия. + this._событияРеакции = function(текст) + { + var соответствие = {}; + + var элементы = текст.split("\n"); + var имяСобытия = null; + for (var номер in элементы) + { + var элемент = элементы[номер]; + // Пропускаем комментарии. + if (элемент.charAt(0) == "#") + { + continue; + } + var имя = элемент.trim(); + // Пропускаем пустые строки. + if (!имя.length) + { + continue; + } + // Событие. + if (имя == элемент) + { + if (!(имя in соответствие)) + { + имяСобытия = имя; + соответствие[имя] = []; + } + } + // Реакция. + else + { + соответствие[имяСобытия].push(имя); + } + } + + return соответствие; + }; + + // Преобразовать имя реакции в название функции. + this._имяФункцииИзРеакции = function(реакция) + { + var имя = ""; + + var части = реакция.split(" "); + for (var номер in части) + { + var часть = части[номер]; + имя += часть.charAt(0).toUpperCase() + часть.slice(1); + } + + return имя; + }; + + // Конструктор. + this.события = {}; +} diff --git a/090.проверка.js b/090.проверка.js new file mode 100644 index 0000000..fa04507 --- /dev/null +++ b/090.проверка.js @@ -0,0 +1 @@ +console.debug("090") diff --git a/index.html b/index.html new file mode 100644 index 0000000..11287f0 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + КОЛОБОК + + + + + + +