Автор оригинала: Richard Leddy.
Петри чистый государственный процесс управления (как часть экспресс-сервера)
В этом руководстве предполагает некоторые знания JavaScript, HTML и Node.js
SVG Масштабируемая векторная графика – это часть HTML5. Это также язык разметки.
SVG Допускает рендеринг графики в виде линейных рисунков. Вы делаете чертежи, которые выглядят как HTML-страница. Или вы можете создавать художественные мастер-кусочки.
Продолжая от предыдущего поста, SVG часть 2
Мы уже прошли несколько шагов, чтобы получить файл готов:
- Создайте графику SVG для обслуживания на странице.
- Сделайте небольшую утилиту JavaScript для создания некоторых кода для инструментов анимации.
- Настройте простой сервер Node.js с использованием Express для обслуживания страницы
Последний шаг по сути сделан. Но есть все важная часть этого, которая связана с запуском чистого менеджера штата Петри, который не был полностью адресован. В последней части этого учебника SVG PART 2 WHE мы запустили дочерний процесс, который мог бы отправить информацию о состоянии веб-сервера, что, в свою очередь, отправит информацию всем клиентам прослушивания в веб-браузерах. Тем не менее, это сделало немного больше.
Итак, в этой части учебника Часть 3 , мы можем исследовать загрузку в настоящем Чистом штате Петри. Реальный относительно. Но мы можем использовать простой модуль узла, который запускает Petri-Net и может использоваться в небольшой встроенной системе для управления взаимосвязи между аппаратными элементами. Это модуль Node.js тоже называется Run-Petri Отказ И у меня есть это доступно на Github: Run-Petri Отказ
Итак, эта часть учебника заключается в том, что эта заметка:
- Включите рабочий детский процесс, который управляет государством Петри.
Следует пройти несколько шагов, прежде чем мы сможем получить живую страницу. Вот что осталось сделать:
- Создать JavaScript, который будет анимировать SVG
- Запустите страницу в браузере.
Оставаться с более легкой стороной вещей, будет что-то показывать, когда мы закончим.
Еще один скрипт поддержки
DevOps никогда не делается, то есть, если вы называете некоторые из наших сценариев поддержки DEVOPS. В первой части одной из этой учебной части части 1 мы нашли способ прочитать информацию от SVG и выпускающих структур JSON, которые описывают сеть Петри, наблюдаемую в SVG. Сурок, что приходилось делать умным с именами на имя SVG-элементов и использование факта, что SVG является своего рода формат XML.
Выход из инструментов, сделанных там созданных файлов JSON, которые окажутся полезными для настройки операций на веб-страницах. Но модуль узла мы скоро будем использовать, Run-Petri , использует немного другой структуру данных JSON для инициализации. На самом деле, у него примерно такая же информация, которую мы получили от графика. Итак, вы можете догадаться, что это будет легко сделать инструмент для преобразования одного представления JSON в другое. И это происходит так.
На самом деле, вот код для него:
var fs = require('fs'); // we will be reading from files. var scraperOutput = process.argv[2]; // named on the command line. // Here is how to turn the text into a JSON data structure // for use in JavaScritp var petridDef = fs.readFileSync(scraperOutput,'ascii').toString(); petridDef = JSON.parse(petridDef); // This is the high level structure of the JSON file // that is required input to a run-petri application. var runPetriConf = { "nodes" : [], "transitions" : [] }; // An easy -- cheesy -- way to ensure no duplicates in a node list. function nodeDuplicates(nodeList) { var asObject = {}; nodeList.forEach((name) => { asObject[name] = 1; }); nodeList = Object.keys(asObject); return(nodeList); } // // injectNodeList -- puts node objects into the config node list function injectNodeList(nodeList,nodeType) { nodeList = nodeDuplicates(nodeList) nodeList.forEach((nodeId) => { runPetriConf.nodes.push({ "id" : nodeId, "type" : nodeType }) }); } // injectNodes -- puts all the types into our list. // Here you can see the who the formats differ. // One uses an array for each type of node. // The other labels a node with its type. // And, the way run-petri works, it just wants to run through a list and setup // each node type. function injectNodes(petriData) { injectNodeList(petriData.inputs,"source"); injectNodeList(petriData.outputs,"exit"); injectNodeList(petriData.states,"state"); } // Transitions are a separate thing in both formats. // In fact, the are almost the same. But, this is a format switch // from an object with transition name keys, to an array of transition objects // each of which has a label to identify it. function injectTransitions(petriData) { var transObject = petriData.transitions; for ( var transName in transObject ) { runPetriConf.transitions.push({ "label" : transName, "inputs" : transObject[transName].inputs, "outputs" : transObject[transName].outputs }); } } // Put the nodes into the configuration injectNodes(petridDef); // Put the transitions into the configurations. injectTransitions(petridDef); // Be lazy and dump this to the console. console.log(JSON.stringify(runPetriConf,null,2))
Примечание : Stringify важно. Цитаты должны появиться в формате JSON.
Итак, вы видите, что большая часть разницы в форматах является то, что один формат использует объекты, клавиши которых определяют элемент чистого числа Petri, в то время как другой формат представляет собой перечисление массивов объектов, каждый из которых содержит метку NET PETRI NET.
Поскольку это отбрасывает формат в консоль, вы можете бросить его содержимое в файл правой командой оболочки как таковой:
node prepareRunPetri p1.json > petriConf.json
Выход в файл должен выглядеть похоже на это:
{ "nodes" : [ { "id" : "circle-input-C", "type" : "source" }, { "id" : "circle-input-A", "type" : "source" }, { "id" : "circle-input-D", "type" : "source" }, { "id" : "circle-input-E", "type" : "source" }, { "id" : "circle-input-B", "type" : "source" }, { "id" : "circle-output-Q", "type" : "exit" }, { "id" : "circle-output-P", "type" : "exit" }, { "id" : "circle-state-F", "type" : "state" }, { "id" : "circle-state-G", "type" : "state" }, { "id" : "circle-state-H", "type" : "state" } ], "transitions" : [ { "label" : "rect-transition-A:B-F", "inputs" : [ "circle-input-A", "circle-input-B" ], "outputs" : [ "circle-state-F" ] }, { "label" : "rect-transition-C-G", "inputs" : [ "circle-input-C" ], "outputs" : [ "circle-state-G" ] }, { "label" : "rect-transition-F:G-P", "inputs" : [ "circle-state-F", "circle-state-G" ], "outputs" : [ "circle-output-P" ] }, { "label" : "rect-transition-H-Q", "inputs" : [ "circle-state-H" ], "outputs" : [ "circle-output-Q" ] } ] }
Чистый государственный штат Петри
Теперь давайте обратим наше внимание на сценарий Node.js, который вырезан с сервера Express. Напомним, что мы создаем связь между ребенком в файле Petrustate.js В Express Server мы разработали во второй части этого учебника SVG Часть 2 Отказ
Но на данный момент код выглядит так:
process.on('message', (m) => { console.log('CHILD got message:', m); }); setInterval(() => { process.send({ state: 'OK', data: "ready" }); },1000)
Это довольно бессмысленный код.
Мы можем начать получать значимые, если мы по крайней мере, требуем Run-Petri модуль. Вот это для начала:
const PetriClasses = require('run-petri'); const pNode = PetriClasses.pNode; const RunPetri = PetriClasses.RunPetri; process.on('message', (m) => { console.log('CHILD got message:', m); }); setInterval(() => { process.send({ state: 'OK', data: "ready" }); },1000)
Обратите внимание на небольшое изменение кода в верхней части файла. PetricLasses – это модуль контейнера, который подвергает определениям классов. Первый – Pnode, узел Петри чистый. И, второй – класс RunPetri, который является классом, который ранит A Run-Petri Файл конфигурации (наш P1.JSON) и имеет методы, чтобы предпринять ресурсы, выходы излучения, и наступит в шаг сети Петри через последовательность изменений состояния.
Чтобы сделать все эти чистые линго, немного более яснее и, чтобы увидеть, как Run-Petri поможет с управлением ограниченным классом сетей, мы можем быстро перейти на тему чистую чистую петри. Я дам ссылки на более подробные обсуждения.
Немного глубже в Петри сетки и модуль Run-Petri
Итак, о Петри сетки. На верхней части страницы есть картина немаркированного на странице. Вы можете видеть, что они являются Directect Acyclic Gamps, которые имеют два типа узлов. Есть круги, ссылающиеся как Места и ящики, ссылающиеся как Переходы Отказ
Состояние чистота Петри – это Маркировка из Места с токены Отказ То есть каждый место это помечено, будет иметь черный круг в нем. Черный круг упоминается как токен Отказ
Когда государство меняется, какие изменения – маркировка. Вот простой до и после изменения состояния на картинке:
Петри сетки были в течение длительного времени. Итак, вы можете себе представить, что они хорошо описаны. И, прежде чем писать больше, я просто отправлю вас в другое место, чтобы узнать больше о Nets Nets и как они работают. Вот довольно хорошая ссылка на краткое описание Петри сетки Петри Nets пояснил Отказ
После того, как вы прочитали эту статью, вы можете оценить это Run-Petri попытки избежать путаница и конфликт Отказ Хотя он пытается сделать следующие режимы работы:
- последовательность
- параллельность
- синхронизация
- слияние
- Приоритет/ингибирование
Итак, пожалуйста, следуйте ссылкам и получите дополнительную информацию об этих шаблонах. Как Run-Petri Делает эти шаблоны возможными своеобразными для его собственной реализации. Обратите внимание, что я говорю: «Делает эти образцы возможными». Эти шаблоны будут определены, когда вы делаете конфигурацию для Run-Petri Отказ Это работа Run-Petri разрешить эти шаблоны работать.
То, что я хочу сделать сейчас, расскажет вам больше о модуле, который мы будем использовать, Run-Petri Отказ
Модуль Node.js Run-Petri
Вчера я сделал хорошую экспозицию здесь. Но я вернулся этим утром, чтобы найти все мои редактирование вчера, разрушенного системой кодамента. Итак, мне придется быть кратким.
Установка NPM
npm install run-petri
источники и выходы
Модуль Node.js, Run-Petri , идентифицирует два типа мест, узлов, которые позволяют данные для ввода и выхода из сети. Помещение данных в сеть соответствует, примерно, для создания более токенов для маркировки.
Модуль Node.js, Run-Petri Предоставляет средства для уточнения обработчиков и обратных вызовов для таких видов узлов.
Вот фрагмент кода, который устанавливает экземпляр RunPetri.
var pNet = new RunPetri(); // initialize the network here. note: two parameters, no special cases. pNet.setNetworkFromJson(net_def,callbackGenerator);
Вы можете увидеть метод, setnetworkfromjsson быть вызываемым. Это имеет недвижимость, который является обратным вызовом, callbackgenerator Отказ Это функция, которая генерирует обратные вызовы по типу. Он сам имеет два параметра, ID и CBType Первый – это идентификатор узла и второй – тип узла, «выход» и т. Д.
См. Пример ниже для получения дополнительной информации.
Ресурсы
Run-Petri Относится к счетам в случае по умолчанию в качестве ресурсов. В случае по умолчанию все жетоны являются только подсчитанным держателем места на узле. И все дуги проходят по одному токену. Вы можете сделать больше с Run-Petri Отказ Я не собираюсь здесь здесь. Для этого учебника я использую дело по умолчанию.
некоторые полезные факты о его реализации
Мне придется реконструировать то, что я сказал здесь на предыдущей дате. Вкратце, есть простой способ предотвратить путаница и конфликт Отказ То есть чтобы убедиться, что узел может быть введен только для одного перехода. Вентилятор из узла лучше всего реализован, когда узел будет вводиться в переход, который затем выходит. Итак, велосипед от перехода.
Если файл конфигурации имеет Смущение и Конфликты Экземпл RunPetri будет выбрасывать исключение.
В Run-Petri Один рода узла может действовать как ингибитор перехода, предотвращая его стрельба, если оно помечено. Это единственные узлы, которые могут быть использованы в качестве входа более одного раза. Они указаны как имеющие тип «inihibit», и они также требуют перехода целевого перехода. Если вы должны использовать их, формат их спецификации в списке узлов конфигурации JSON следующий следующим образом:
{ id: 'circle-input-C', type: 'inhibit', target : 'some transition label' }
Простой рабочий пример
Вот некоторые, изменение файла Petristate.js, созданного в последней части этого руководства, SVG часть 2
const fs = require('fs'); var PetriClasses = require('./index.js'); var pNode = PetriClasses.pNode; var RunPetri = PetriClasses.RunPetri; const nodeClasses = { pNode }; const gInterval = 2000; const filename = "./pstate.json"; // load a particular file. var jsonData = fs.readFileSync(filename,'ascii').toString(); var net_def = JSON.parse(jsonData); // into a data structure. /* */ function callbackGenerator(id,cbType) { if ( cbType === 'exit' ) { // An exit callback that send data back to the parent Server. var dataExitCb = (v) => { process.send({ state: 'data', id: nodeId, data: v }) } return(dataExitCb) } else if ( cbType === 'reduce' ) { // this is the default reducer... var reducer = (accumulator, currentValue) => accumulator + currentValue; return(reducer); } return((v) => { console.log(v); return(0); }) } var pNet = new RunPetri(); // initialize the network here. note: two parameters, no special cases. pNet.setNetworkFromJson(net_def,callbackGenerator); // >>======== ======== ======== ======== ======== ======== ======== process.on('message', (m) => { // A way to get data from the parent process. // Allow the parent process a kind of // message that feeds the network. // This is useful for testing. if ( m.mtype == "petri" ) { pNet.emit(m.sourceNode,m.value); } }); setInterval(() => { pNet.step(); // step the petriNet every gInterval miliseconds process.send({ state: 'report', data: pNet.report() }) },gInterval)
Теперь это настроено, чтобы принять направление от родительского процесса и отправлять его для него как для состояний, так и для данных. В коде ‘pnet.report’ отправляет данные обратно на веб-сервер, который клиент захочет использовать для анимации SVG. Но выброс данных выхода данных и вызов pnet.emit (m.sourcenode, m.value)
Также имейте дело с данными, идущими и с сервера. Эти последние две формы могут быть заменены в приложении, которое больше для реального мира, имеющих связь с аппаратными модулями – скажем. Филирование ввода не изменится, но Процес. Отказ
До последней части этого учебника
Теперь у нас есть процесс, который принимает вход от какого-то места, один мы можем измениться с реальными подсистемами. Он отправляет информацию на веб-сервер, который затем отправляет сообщения всем клиентам, чтобы обновить веб-страницы. И, наконец, хранитель государства Петри может выделять результаты для прослушивания процессов.
Итак, есть еще один шаг. Мы хотим увидеть графическое представление государственных изменений на наших веб-страницах. Это тема следующая и последняя часть этого учебника, часть 4. В части 4 мы можем работать Soley на клиенте, который загружает нашу страницу SVG и анимации, когда новые сообщения приходят вместе. Клиент получит json Description из сети, одинаковое описание, которое мы сделали в части 1. Клиент будет использовать это описание для идентификации элементов SVG, которое оно получает сообщения о сервере Express.js.