Pull to refresh

Comments 20

Диалоги с формами сверстаны моё почтение, любо дорого смотреть, простите очень бросилось в глаза.

Их похоже тоже deepseek верстал

DeepSeek приложился только к созданию "типичного" варианта. Оно, кстати, доступно на GitHab - е. Вот там все его - от кода до формы web-странички.

Остальное, поверьте, все натуральное :)

а может надо было просто объяснить что это за черная магия с LArc? Или это специально, с целью всех запутать, типа у нас тут: "автоматная технология параллельного программирования", попробуй разберись?

Объяснял и не раз. Удивляет только, что находятся те, для которых это все еще "магия". LArc - класс для кодировки (создание некой структуры) одного перехода (дуги) конечного автомата: LArc("текущее состояние", "следующее состояние", "условие перехода", "действия при переходе в новое состояние"). Вот и все волшебство. И совсем не "черное" ;)

а можно пальцем ткнуть откуда берутся Y-ки (игреки y5, y6, y4), например такие:

    else if (nCounter == 45) { y5(); }
    else if (nCounter == 46) { y6(); }
    else if (nCounter == 47) { y5(); }
    else if (nCounter == 48) { y6(); }
    else if (nCounter == 49) { y5(); }
    else if (nCounter == 50) { y4(); }

Если не секрет?

Да какой же тут секрет - наследуются от родителя - базового класса. Там они и находятся.

Так я не могу найти! Где в базовом классе? Я вижу эти УУ-игреки в строках передаются, в списке инициализации:

    LArc("G0",	"G1","--","y5y10"),		//R=0, Y=0, G=0, 1 sec
    LArc("G1",	"G01","--","y6y10"),	//R=0, Y=0, G=1, 1 sec
    LArc("G01",	"G10","--","y5y10"),	//R=0, Y=0, G=0, 1 sec

А как они в функции превращаются я что-то не вижу или не понимаю. Можете пояснить, ну , или пальцем ткнуть если я что-то в упор не вижу?

Это все виновато ООП :).

Дело в том, что наш базовый класc имеет свой базовый класс - автоматный класс LFsaAppl, который лежит в самом низу иерархии любого автоматного класса. Т.е. в нашем случае так: LFsaAppl<-FTrafficLights<-FLightCntrl (в другом варианте FLifhtEasy). LFsaAppl имеет виртуальные функции - те самые x-сы и y-ки. Последние уже перегружаются реальными функциями в дочерних классах. Ядро интерпретации из таблицы переходов (те самые структуры LArc) определяет какие x-сы, а затем и какие y-ки (если есть ситуация перехода) запускать.

Вот как-то так грубо и на пальцах. Но есть исходные коды на С++ из которых все это "вычисляется" конкретно. Но надо, конечно, знать и С++ и, конечно, понимать принципы ООП. Хотя по большому счету достаточно понимать на уровне "как есть".

С другой стороны, если автомат создается на уровне SWITCH, то заморочки интерпретации не работают. Правда при этом теряются важные свойства автоматной модели.

Так если вам (нам) нужна новая функция y555() и она у нас почему то должна быть виртуальная, получается мы должны где то в дебрях LFsaAppl<-FTrafficLights<-FLightCntrl (в другом варианте FLifhtEasy) написать эту функцию, потом перегрузить (я раньше думал что виртуальные функции надо переопределять, а не перегружать) реальными функциями в дочерних классах? Вам не кажется что это какая-то странная концепция, если только это не концепция "всех запутать"?

Да, нет, конечно. Просто всегда есть определенные ограничения. В данном случае с y555() будут проблемы. Речь, конечно, о классе LFsaAppl. Здесь ограничения даже на имена. Но Вы можете создать свой базовый автоматный класс и как-то решить эту проблему. Я уж как-то привык, если честно. Главное, не вызывает каких-то проблем. Да и зачем ломать то, что давно работает и работает надежно и эффективно.

LArc("текущее состояние", "следующее состояние", "условие перехода", "действия при переходе в новое состояние")

Т.е. эту строку можно записать в виде графики (функциональной модели нотации idef), как:

LArc -- внутри черного ящика, на левую грань которого давит AsIs, а на крышку ящика давит "условие перехода", подпираемое снизу пола ящика "действием при переходе в новое состояние" и, в конечном счёте, заканчивающееся выталкиванием с правой стороны стенки ящика на ТоВе (следующее состояние)?

Я правильно интерпретировал Вашу строку?

ЗЫ: сорян, вопрос от диназавров -- просто кайфую от светофора

Скорее нет, чем да. Это все же разные языки. Даже в смысле графики. Попробуйте любой автомат (граф переходов) изобразить в нотации idef и тогда все будет ясно. Когда-то я такие попытки делал. Безуспешно ;) Но, может, у Вас это получится.

Но на структурном уровне для описания сети автоматов эта нотация возможно и подойдет. Но в любом случае правильнее было бы сравнить сначала нотации UML и idef, а уж потом подбираться к более мелкой сущности - описанию переходов автомата.

Да. Через Вас вышел на статью Конечный автомат (FSM) — ловушка для программиста. Что можно сказать? Просто не нахожу слов. Действительно, - ловушка. ;)

Всё усложнено. Можно было в одном цикле всё сделать без всяких автоматов.

Можно, конечно. Но как говаривал один экземпляр - "можно, но зачем?". Здесь важно понимать - зачем. Можно проще - на лошади, на велосипеде или просто пешком. Другие варианты - машина, самолет или даже ракета. Несколько сложнее. Но дело в том, что появляются/открываются другие возможности.

Да, нужно немного напрячься, чтобы их освоить. Другое дело, что не хочется напрягаться. Потому-то один всю жизнь проходит пешком, а другой может и так, а может и на своей машине.

Понятно, что у "сложных вариантов" и возможностей гораздо больше. А по-большому счету даже проще, чем пешком - сиди, да рули :)

по мотивам статьи Конечный автомат - ловушка для программиста

Это исходная программа:

tablRec =  Table.firstRec();
while(true)
{
         setLampsState(tablRec.colors);
         timer  = setTimer(tablRec.period);
         waitFor(timer);
          tablRec = nextRec(Table);
         if(tablRec == 0)
                  tablRec =  Table.firstRec();
}

 А это эквивалентный ей автомат:

bool x1()  { return timer; }

bool x2(){ return tablRec == 0 }

y1()  { tablRec =  Table.firstRec();}

y2(){ setLampsState(tablRec.colors); }

y3(){ timer  = setTimer(tablRec.period); }

y4(){ tablRec = nextRec(Table); }

 

“s1”, “s2”, “-”, y1,

“s2”, “s3”, “-”, y2y3,

“s3”, “s3”, “x1”, -,

“s3”, “s4”, “^x1”, y4,

“s4”, “s2”, “x2”, y1,

“s4”, “s2”, “^x2”, -.

Переход к автомату (КА) делается по щелчку. !00 лет формальной процедуре перехода от любой мудреной программы к КА. Так что для знающего КА не ловушка, а идеальная игрушка! Просто нужно хорошо знать матчасть. :)

А теперь вспомните что у вас было ДО того как вы увидели и осознали как просто можно обойтись 10 (десятью!) строчками, у вас было так:

LArc TBL_LightCntr[] = {
    LArc("st",	"R","x1",	"--"),
    LArc("st",	"Y","x2",	"--"),
    LArc("st",	"G","x3",	"--"),
    LArc("R",	"RY","--","y2y3y5y7"),	//R=1, Y=0, G=0, 30sec
    LArc("RY",	"G","--",	"y4y8"),    	//R=1, Y=1, G=1, 5 sec
    LArc("G",	"G0","--","y1y3y6y9"),	//R=0, Y=0, G=1, 10 sec
    LArc("G0",	"G1","--","y5y10"),		//R=0, Y=0, G=0, 1 sec
    LArc("G1",	"G01","--","y6y10"),	//R=0, Y=0, G=1, 1 sec
    LArc("G01",	"G10","--","y5y10"),	//R=0, Y=0, G=0, 1 sec
    LArc("G10",	"G02","--","y6y10"),	//R=0, Y=0, G=1, 1 sec
    LArc("G02",	"Y","--",	"y5y10"),		//R=0, Y=0, G=0, 1 sec
    LArc("Y",	"R","--",	"y1y4y5y8"),	//R=0, Y=1, G=0, 5 sec
    LArc()
};

и в этом варианте Иксов и Игреков черт все ноги поломал, что называется. Кстати в варианте который вы сделали на основе моего кода, здесь:

bool x1()  { return timer; }

у вас не совсем корректно, точнее будет так:

bool x1()  { return isTimerReady(); }

мне кажется! И тогда совсем все понятно.

!00 лет формальной процедуре перехода от любой мудреной программы к КА.

почему же вам ваша формальная процедура не помогла вам сразу написать просто и понятно в терминах предметной области, а не в абстрактных Иксах и Игреках которые вы объясняете вот так:

Это все виновато ООП :).

Где сформулирована ваша формальная процедура? Как НЕ написать так как у вас в исходном варианте, а написать так как вы переписали на основе моих строчек?

У Вас специализированное решение, у меня - универсальное, где цвета могут гореть одновременно, есть действия по установке и сбросу действия. У Вас может гореть только один цвет. Это существенное ограничение.

По поводу корректности. Я даже ждал этот вопрос. У меня таймер - вложенный автомат, а потому не нужно контролировать его завершение.

О процедуре. Она приведена в книге С.Баранова "Синтез микропрограммных автоматов". Знать ее очень полезно. Процедура эта не "помогает" писать, а помогать приводить одну модель к другой. Я беру Вашу - блок-схему и получаю свою - автомат. Она объясняет/доказывает, что Ваша программа это по сути тот же автомат и наоборот.

Так что все нормально. Имя свою модель я очень просто создаю управление светофором. В этом случае я не изобретаю таблицу, не создаю программу перебора ее строк. Т.е. ситуация только проще, а не сложнее. Более того автомат имеет плюшки, которых нет у таблицы и программе к ней.

У Вас может гореть только один цвет. Это существенное ограничение.

Кто вам это сказал? Нет у меня таких ограничений! Все три цвета у меня задаются одновременно одним 3-х битным числом, скажем:

1 это красный

2 это желтый

4 это зеленый

соответственно:

3(три) это красный + желтый,

7 это красный + желтый + зеленый, например, и так далее.

Таймер в этом случае надо использовать аппаратный, может вы мне расскажете как правильно использовать аппаратный таймер? Как вам в этом автоматы помогают?

Если так - другое дело. Как-то не врубился сразу. Так что беру свои слова (про один цвет) обратно.

По поводу таймера. Совсем нет проблем. Здесь используется вложенный автомат. Можно и параллельный. Все эти задержки используются в моих примерах на Git. В базовом автоматном классе (LFsaAppl) это методы FCreateDelay и FCreateParDelay.

Sign up to leave a comment.

Articles