Задачи для начинающих
Знакомый в Уни, начал подкидывать задачки. Возможно будет интересно и тем кто хочет научится программированию. Выкладывайте свои ответы - обсудим.
Вначале задача в том виде, как рассказали по телефону. Я ее протестировал на "кошках" - решают без каких либо проблем, в общем виде.
1. Есть террариум в котором нужно поддерживать постоянную заданную температуру, для этого есть функции "ВключитьНагрев", "ОтключитьНагрев".
Требуется вначале построить Flussdiagram, а потом уже прогу на питоне.
Для начала попробуйте просто описать алгоритм используя конструкции "Делай ..." и "Если ... То... Иначе..."
Специально написал немного меньше чем надо. Допишите сами чего еще не достаёт для постновки задачи.
Выкладывайте свои ответы - обсудим.
А если не будут обсуждать, а будут смеятся над ответом, или пойдут ироничные или саркастические шутки?
Смотря какой террариум. Если он большой, то я предпологаю что в террариуме должно находится несколько датчиков температуры, а так-же несколько подогревательных элементов, допустим по бокам, и посередине. Ведь в квартире иногда бывают 2 или 3 обогревателя, но в константу MAX_COUNT_SENSORS можно просто установить значение 1, тогда будет от одного датчика проверяться. И если это проект для ардуино, то датчики будут возвращать скорей всего числа с плавоющей точкой, что-то вроде около нуля, а range в Python отказывается иметь дело с float, берёт только целые числа. Причём датчики ардуино, будут давать погрешность, калибровка датчиков (термометров) это тот ещё геморрой. А MicroPython какой-нибудь урезаный, там нет прям таких крутых библиотек как в нормальном Python 3.x
Требуется вначале построить Flussdiagram, а потом уже прогу на питоне.
Ох, а мне вот проще наоборот.
"Делай ..." и "Если ... То... Иначе..."
А мне больше нравится использовать ...in range...
if avg_temp in range(MIN, MED): ... elif avg_temp in range(MED, MAX): ... elif avg_temp > MAX: ... else: ...
Начну с кода, а завтра попробую Flussdiagram нарисовать.
import random import sys #Константы-------------- MIN_TEMP = 0 #Минимальная температура MED_TEMP = 5 #Средняя температура MAX_TEMP = 10 #Максимальная температура STEP = 1 #Шаг MAX_COUNT_SENSORS = 5 #Максимальное количество сенсоров #Функци----------------- #Поиск среднего значения def avg(items): return sum(items) / len(items) #Делаем теплее def make_warm(i, idx): #Инкрементация массива idx индекса i, на один шаг, с шагом STEP i[idx] += STEP #Делаем холоднее def make_cold(i, idx): #Декрементация массива idx индекс i, на один шаг, с шагом STEP i[idx] -= STEP #Остужаем всё def make_cold_all(i): #Декрементация всех элеметнов массива i, с шагом STEP for x in i: i[i.index(x)] -= STEP #Сброс def restart_all(mv, i): #Устанавливаем для каждого элемента массива i, значение mv for x in i: i[i.index(x)] = mv #Начало----------------- #Инициализация переменных temp = [] # Массив со значением от датчиков index = 0 # Индекс avg_temp = 0 # Средняя температура cmd = '' # Команда, Y-дальше мониторить/A-выключить подогрев/N-выход times = 0 # Сколько раз убавлять температуру #Инициализация #temp = [1, 3, 4, 5, 10] #Главная программа------ try: #Рандомно генерируем температуру for i in range(MAX_COUNT_SENSORS): temp.append(random.randint(MIN_TEMP, MAX_TEMP)) while True: #Получаем среднее значение avg_temp = avg(temp) if avg_temp != None: avg_temp = round(avg(temp)) #Выдаём все значения температуры for i in temp: print(i) #Перенос на новую строку print('') #Среднее значение print(avg_temp) #Если среднее значение находится между минимальной и средней температуры, то: if avg_temp in range(MIN_TEMP, MED_TEMP): #Холодно print('Холодно, включаю подогреватель') #Получаем индекс массива минимальной температуры index = temp.index(min(temp)) #Подогреваем make_warm(temp, index) #Если среднее значение находится между средней и максимальной температуры, то elif avg_temp in range(MED_TEMP, MAX_TEMP): print('Нормальная температура, отключаю подогреватель') #Понижаем температуру make_cold_all(temp) #Если температура выше максимальной температуры, то elif avg_temp >= MAX_TEMP: print('Жарко, отключаю подогреватель') #Понижаем температуру index = temp.index(max(temp)) make_cold(temp, index) #Иначе ошибка else: print('Ошибка, датчики температуры сбрасываются на минимальную температуру') #Сбрасывем температуру, до минимального значения restart_all(MIN_TEMP, temp) #Спрашиваем, что делать дальше, Y-дальше, A-выключить подогрев, N-нет cmd = input('Дальше (Y-да/A-выключить подогрев/N-нет)?').upper() #Если нажали на клавишу N, то завершаем программу if cmd == 'N': break #Если нажали на клавишу A, то отключаем подогрев elif cmd == 'A': try: #Пытаемся выключить на n-раз times = int(input('На сколько выключить?')) except Exception as err: print('Ошибка ', err) else: #остужаем n-раз for _ in range(0, times): make_cold_all(temp) except Exception as err: print('Ошибка ', err)
В данной ситуации, т.е. в этом алгоритме выше MED_TEMP не поднимается, поэтому в данном алгоритме, т.е. строка elif avg_temp in range(MED, MAX): бесполезна.
если не будут обсуждать, а будут смеятся над ответом, или пойдут ироничные или саркастические шутки?
ну я надеюсь, что не будут. Все же тема обучение и начинающие.
Хотя иногда бывает действительно сложно удержаться.
А мне больше нравится использовать
В институте как и на работе - делаешь не так как нравится, а так как хотят.
Код пока не смотрел, слишком много. Там должно быть весьма немного. И пожалуйста, длинные простыни в приложение.
Смотря какой террариум
Это нужно узнавать ДО начала работы. Но в принципе не интересует, так как уже есть функции включить подогрев и выключить.
И если это проект для ардуино
Для данного этапа подобные мелочи не интересуют в принципе. Это всё на потом когда будет понимание проблем.
Ну и Вы вроде не такой уж и начинающий
или пойдут ироничные или саркастические шутки?
-----
Так обязательно пойдут.
Бо, это не то что сказано, а то как воспринято.
Просто научись извлекать из этого пользу.
А мне больше нравится использовать ...in range...
-----
А мне - когда код выполняет обработку данных.
калибровка датчиков (термометров) это тот ещё геморрой.
-----
Угу... а представь себе, что помимо просто калибровки еще надо учитывать нелинейность самого датчика...
И что датчиков не 1-2, а пара сотен на каждом блоке, а блоков может быть... много.
И вот когда ты нарисуешь свой ин-рандже на каждый датчик придет дядя и обязательно сломает этот датчик и его надо будет заменять...
А ты уже и забыл что, где и как у тебя соспагетчено...
НП.
Если взять из жизни... можно составить примерный алгоритм, допустим если тело человека ниже 32 градусов, то можно сказать это мертвец, если же выше 41, то тоже мертвец, т.к. белки начинают сварачивается. Если выше 38 дают таблетки, а если ниже 32, то будет скорей всего какая-нибудь диагностика. значения констант MIN_TEMP, MED_TEMP, и MAX_TEMP зависят от того, смотря кто в террариуме живёт. Я думаю что в промежутки MIN_TEMP и MED_TEMP нужно включать обогрев, а если выше MED_TEMP отключать. калибровка датчиков это геморрой, а значения температуры от датчиков скорей всего будет очень маленьким 0.000...
Не-а. Так нельзя. При учебных задачах надо исходить из того, что всё работает идеально, если не оговорено иначе. А то любую задачу можно своими выдумками усложнить до бесконечности.
А что если в датчике ошибка, а что ессли обогреватель вкоючается только если кго последовательно три раза включить и два раза выключить, а что если нагреватель расположен под потолком, а датчик на полу, а что если в террариуме дырка и как не нагревай, температура будет падать, а что если террариум стоит на улице при -50...
Вот структограмма, рисовал её этой программой https://www.struktograf.de/, температура сначало повышается до 37, потом понижается до 34, и так туда сюда прыгает в диапазоне 34..37 градусов...:
Правда сначало накалякал код на vb6, потом превратил в структограмму, завтра на Python переделаю...:
Private temp As Integer Private cmd As Integer Private c As Long Private Const MIN_TEMP = 34 Private Const MAX_TEMP = 38 Private Sub Form_Load() i = 0 cmd = 0 c = Me.BackColor Me.Timer1.Enabled = True Me.Timer1.Interval = 100 End Sub Private Sub Timer1_Timer() Me.Caption = i If cmd = 0 Then i = i + 1 If i > MAX_TEMP Then Me.BackColor = vbRed cmd = 1 End If ElseIf cmd = 1 Then i = i - 1 If i < MIN_TEMP Then Me.BackColor = c cmd = 0 End If End If End Sub
При учебных задачах надо исходить из того...
-----
...чему требуется научить.
АлехНек пока не сформулировал какая будет цель обучения.
Можно предположить - не программа регулирования температуры в террариуме - это только средство.
А что если...
-----
Корректным ответом будет машина состояний.
Полная. Или дополненная фиктивным состоянием до полной.
Но построение оной в качестве "задачи для начинающих" в плане обучения программированию (не конкретному языку) не есть правильный подход - нет базы на которую можно положить имплементацию указанной машины.
К сожалению, приходится не только хвалить но и ругать.
Замечательный пример, как НЕ нужно писать программы.
Вот перлы, которые ну никак не предполагались при описании задачи
Рандомно генерируем температуру Получаем среднее значение Получаем индекс массива минимальной температуры Иначе ошибка Спрашиваем, что делать дальше, Y-дальше, A-выключить подогрев, N-нет
Ну не нужно из пушки палить по воробьям
тоже задачки кидать
Хорошее решение, только номер не забудьте им дать. И отвечающий тоже должен номер задачи написать к чему ответ.
Ну и проверять нужно будет решения с комментариями, что правильно и что неправильно.
Я правда, для первого раза, небольшие заковырки специально делаю. Но уже думаю и так видно чем задача из реальной жизни может отличаться от учебной.
Ну а что можно сделать в форуме в одной ветке?
-----
Вообще-то, много чего.
Например, можно запостить полного Страуструпа и свои комментарии к каждой его сентенции.
немного показать, что такое программирование и с чем его едят
-----
Опять таки - данное не может быть целью так как является средством.
Ну и как средство оно зависит от того к кому применяется.
Мне вот насколько будет полезно? Угу...
Аналогично будет для тех, кто уже понимает самый базис. Ну может маленькая практика в плюсе.
А для тех кто не понимает - для них тоже бесполезно - им надо объяснять что такое Если...то...иначе... и зачем оно надо, и как из него построить заданное.
Кстати, мне тут пришла в голову мысль - самый лучший задачник по программированию - поваренная книга. У нее один недостаток - на выходе хоть что-то, но будет...
Немножко чему то научится.
-----
Месяца три надо постить описание элементов языка и давать задачи, которые подогнаны под то, чтобы решение без использования описанного элемента было много сложнее, чем с ним, и при этом переход от постановки задачи к необходимости использования элемента не должен быть явным.
При этом нужно дополнительно контролировать усвоенность и применение элементов изученных ранее.
Тогда можно чему то научить.
Ну и дополнительно: откуда взялась максимальная, минимальная температура и какие то команды?
Допустим минимальная температура 20, максимальная 35. Датчик в реальном времени измеряет температуру, а дальше программа обращается к шине данных, там из аналога переводится в цифровое значение, и программа получает значение ввиде каких-то чисел. Если температура 18, то включается подогрев, как достигает в террариуме значение 35, подогрев отключается. А cmd = 0 включает подогрев и мериет температуру, cmd = 1 отключает подогрев, но продолжает дальше мерить температуру, и снижает температуру. Покуда это симулятор, мы симулируем датчик температуры, и подогрев. Если бы это был бы не симулятор, то вместо cmd мы бы назвали бы heater, и он принимал бы булевое значение, если бы температура была бы ниже минимума, то программа бы устанавлива heater = true, и дальше мерила бы температуру. Всё просто:
//Константы МАКСИМЛЬНАЯ_ТЕМПЕРАТУРА = 35 МИНИМАЛЬНАЯ_ТЕМПЕРАТУРА = 18 //Инициализация текущая_температура = 0 обогреватель = выкл // Цикл циклить пока True: текущая_температура = получить_текущую_температуру() запуск_обогревателя(обогреватель) если текущая_температура > МАКСИМЛЬНАЯ_ТЕМПЕРАТУРА то: обогреватель = выкл. если текущая_температура < МИНИМАЛЬНАЯ_ТЕМПЕРАТУРА то: обогреватель = вкл.
А если несколько датчиков температуры и несколько подогревов, то можно вынести это в функцию... или можно даже использовать мистер Фред. В данном алгоритме попахивает многозадачностью, я бы в данном проекте попытался бы использовать бы FreeRTOS это легковесная многозадачная ОС реального времени для IoT.
P.S.:С кодом на Python-е получилась каша, потому-что мне в лом было заниматься заниматься с мистерм Фредом и с таймерами, по мне так изврат когда в консольном приложение используют потоки или таймеры.
Для начала попробуйте просто описать алгоритм используя конструкции "Делай ..." и "Если ... То... Иначе
наверное перед тем, как что-то программировать, правильно было бы почитать про PID контроллер, хотя бы в википедии. Там и теория есть, и свойства решения, и как это можно имплементировать. Кстати, в arduino под это есть аж целая PID Library.
Знакомый в Уни, начал подкидывать задачки.
а я бы добавил задачки от другого профессора, которые он публикует на bwinf.de - там выбор побольше будет, а если взять второй тур и все предыдущие годы, то на несколько лет можно чадо по самое здрасте загрузить, да и самому порадоваться за красиво поставленные задачи.
Может быть я что-то не так понял (и уж точно я не знаю питон :) ), но мне кажется, что ты пытаешься решить задачу "в лоб" :)
Я понимаю, что задача настолько просто сформулирована, что "в лоб" решить ее гораздо проще ;)
Но все таки мне кажется, что тут нужно сделать 2 класса:
1) Контроллер градуcника
2) Контроллер обогревателя
Контроллер градусника должен посылать сообщения контроллеру обогревателя.
Таким образом логика контроллера обогревателя становится максимально примитивной и, что важно, тестируемой:
public interface ITermometerController { event EventHandler<TemperatureEventArgs> Temperature; } public class TemperatureEventArgs : EventArgs { TemperatureArgs (int value) { Value = value; } public int Value {get; private set; } } public interface IHeaterController { void HeaterOn (); void HeaterOff (); } public class HeaterController : IHeaterController { public HeaterController (ITermometerController termometer) { termometer.Temperature += termometer_Handler; } public void HeaterOn() { ... } public void HeaterOff() { ... } public void termometer_Handler(object sender, TemperatureArgs e) { if (e.Value > highThreshhold) HeaterOff(); else if (e.Value < lowThreshhold) HeaterOn(); } }
Вот и весь код :)
нужно сделать 2 класса
-----
нужно делать 5 классов - градусник, нагреватель, два контроллера и террариум.
типы оборудования - градусники и нагреватели - могут меняться и потому адаптируются контроллерами.
террариум - ну он по задаче есть - должен присутствовать и агрегировать контроллеры.
это и будет решение в лоб.
НО! это не будет решением начинающего...
нужно делать 5 классов - градусник, нагреватель, два контроллера и террариум.
А еще можно сделать по классу на каждый отдельный орган чувств каждого обитателя террариума.
Поставленная в 1-ом посте задача сводится к "написать котроллер обогревателя". Все остальное - вода.
НО! это не будет решением начинающего...
Это направление, в котором начинающий должен двигаться, если он хочет чему-то научиться.
нужно делать 5 классов - градусник, нагреватель, два контроллера и террариум.
В реальности нужен только один класс, который реагирует на событие. Событие - изменение температуры. Событие приходит от термометра, но на самом деле это не важно - удав может по желанию включать и выключать обогреватель, подавая нужное событие, например имитируя градусник. Градусник не должен пренадлежать обогревателю - лёзе куплюнг. Мне нравится решение программиста, хотя я не понимаю этот синтаксис
Поставленная в 1-ом посте задача сводится к "написать котроллер обогревателя"
-----
Тогда вполне годится сааамый первый вариант...
В постановке задачи определены три сущности - террариум, нагреватель и термометр(?, не явно).
террариум, по определению, должен агрегиривать нагреватель и термометр.
изолируем фактические нагреватель и термометр соответствующими контроллерами.
Вот она - 5-ка.
Можно - усложнить (или упростить сопровождение) введя фабрики для двух сущностей, как оно обычно и бывает на практике.
в котором начинающий должен двигаться
-----
Ну должен. У него, правда, пока еще не уложилось Если...То...Иначе.
Там 2 класса, один из которых не имеет функционала.
-----
А должно быть минимум 3.
Пусть два из них - нагреватель и термометр - абстрактные.
При этом нагреватель не должен знать об термометре, а термометр - об нагревателе.
Вообще не должны. Потому как в террариуме они никак напрямую не взаимодействуют.
Террариум, кстати, тоже не должен управлять процессом - его задача - получить инстансы нагревателя и термометра, создать контроллер на базе полученных инстансов и запустить его в работу.
И, кстати, у тебя в решении есть существенная ошибка.
Она заключается в том, что ты принял как данное термин - нагреватель.
В большинстве случаев это будет корректно.
Но не всегда - террариум, по определению, является системой с контролируемой температурой.
Так что вполне может иметь место ситуация когда надо охлаждать - следовательно - надо переделывать контроллер.
Тогда вполне годится сааамый первый вариант...
Не подходит. Там термометр опрашивается в цикле.
В постановке задачи определены три сущности - террариум, нагреватель и термометр(?, не явно).террариум, по определению, должен агрегиривать нагреватель и термометр.
Аквариум, терариум или жилая комната - в данной задаче это не имеет значения. Это просто описательная информация. Также как в задаче "Ученица 1-ого класса деревенской школы построила себе в лесу шалаш и спрятала там 10 монеток. При этом в своей копилке дома у нее было 16 монеток. Сколько всего монеток было у школьницы?" полно описательной информации, которая ничего не дает. Это просто контекст, который не играет никакой роли в решении.
изолируем фактические нагреватель и термометр соответствующими контроллерами.
Именно это я и сделал. При этом код контроллера термометра никого не
интересует, поэтму я ограничился только кодом контроллера нагревателя.
При этом нагреватель не должен знать об термометре, а термометр - об нагревателе.Вообще не должны. Потому как в террариуме они никак напрямую не взаимодействуют.
Ну это уже holly war на тему "толстых" и "тонких" контроллеров :)
В большинстве случаев это будет корректно.
А если прочитать условие задачи, то это будет корректно и для данной задачи :)
Событие приходит от термометра
-----
А кто сказал, что Термометр в состоянии делать нотификацию?
Может или не может - неизвестно - потому термометр и оборачивается в контроллер термометра.
Нагреватель - аналогично.
удав может
-----
Может.
Для корректно имплементированного кода это не должно вызывать переписывания кода.
И вместо удава там может быть какой-нибудь песец или пингвиn...
Не подходит. Там термометр опрашивается в цикле.
-----
Ну и что? Ну опрашивается, ну в цикле. Заявленному требованию - удовлетворяет - значит годится.
Ну это уже holly war на тему "толстых" и "тонких" контроллеров :)
-----
И тем не менее - если делать правильно - значит делать правильно.
А если прочитать условие задачи
-----
Читаем:
нужно поддерживать постоянную заданную температуру
Об том что функции управляют именно нагревателем - это уже твое восприятие того как они поименованы., но из условия задачи именно нагреватель в качестве устройства не следует.
Ну и что? Ну опрашивается, ну в цикле. Заявленному требованию - удовлетворяет - значит годится.
Где я говорил, что это решение не годится? Я сказал, что это решение "в лоб". Ну или если бы писали на ANSI C :)
И тем не менее - если делать правильно - значит делать правильно.
Толстые и тонкие контроллеры - это не вопрос привильно или нет. Спорить тут не имеет смысла.
Об том что функции управляют именно нагревателем - это уже твое восприятие того как они поименованы., но из условия задачи именно нагреватель в качестве устройства не следует.
Это потому что ты прочитал только половину условия:
нужно поддерживать постоянную заданную температуру, для этого есть функции "ВключитьНагрев", "ОтключитьНагрев".
Почему ты проигнорировал то, что после запятой - большой вопрос.
А кто сказал, что Термометр в состоянии делать нотификацию?
Это самое красивие решение. Поскольку реальные приборы не названы и задача учебная, нужно привести красивое теоретическое решение. Контроллер действительно может долбить термометр регулярно, опрашивая температуру и принимая решение после каждого опроса. Но это не красиво.
Более того, а кто сказал, что обогреватель вообще автоматически может реагировать на изменение температуры? И ВДРУГ, решение Программиста полностью функционирует без переписывания, если в качестве эвента выступает дворник, считывающий температуру и инициирующий события.
Вот Flussdiagramm:
Очень похоже, забыли только сказать чем рисовали. Немного неаккуратно и не совсем соответствует DIN 66001
https://de.wikipedia.org/wiki/Programmablaufplan
- yEd Graph Editor – kostenloser Diagrammeditor, mit dem Datenflussdiagramme gezeichnet werden können
- Orinoco – kostenloses Tool zur Modellierung und Simulation von Datenflussdiagrammen
Где я говорил, что это решение не годится?
-----
Ну а зачем писать что-то если удовлетворяющее решение уже есть?
Это потому что ты прочитал только половину условия
-----
Я прочитал как раз то что нужно и прочитал правильно.
Если тебе не нравятся пингвины с песцами - пусть будет какая-нибудь редкая ящерка из средней полосы, которая размножается только в ограниченных по температуре условиях. А террариум разместим поближе к экватору.
Почему ты проигнорировал то, что после запятой
-----
Во второй половине указаны идентификаторы управляющих функций, но нигде не сказано что они управляют именно нагревательным элементом. Вывод об том что подразумевается именно нагревательный элемент ты сделал исходя из названия функции - это чисто твое умозрительное заключение. По факту корректирующий температуру элемент может быть любым, но управляемым двумя указанными методами.
перед тем, как что-то программировать, правильно было бы почитать про PID контроллер,
Зачем это знать начинающему?
Для решения задачи не нужно знать абсолютно ничего. Даже какой то язык программирования. И будет ли работать даже написанной программа на реальном контроллере, тоже совершенно не важно.
Для первого этапа достаточно описать всё хотя бы своими словами. Я удивляюсь почему до сих пор никто ничего не написал из тех кто хочет учится. Ведь именно для и них всё и затеял.
а я бы добавил задачки от другого профессора
Добавляйте. Только я бы в этой теме сделал ограничение: Кто добавляет задачи, тот и ментор для них.
Если же есть задачи, но нет желания или знаний для их сопровождения, то лучше добавлять в новой теме. В которой будут только задачи.
Но это не красиво.
-----
Это вполне красиво - на то он и контроллер, чтобы изолировать сущностный элемент.
Контроллер действительно может долбить термометр регулярно
-----
Как он будет делать - не важно. Важно что благодаря прокладке-контроллеру управление не будет зависеть от типа и возможностей Термометра.
если в качестве эвента выступает дворник
-----
Так ведь без разницы.
Разница появится когда будет требоваться учитывать показания термометра, действия дворника и мнение питона.
требуется учитывать инерционность тепловых процессов.
Это вы придумали
в качестве "управляющего воздействия" выберем две величины: как надолго включить нагреватель , и какую после выключения сделать паузу.
Это вы придумали
инициализировать "регулятор": некая сущность, которая будет имплементировать управление, вычисляя "управляющее воздействие" (напомню, это - две величины: время включенного состояния и пауза после). 0. запросить у регулятора управляющее воздействие
1. выполнить управляющее воздействие2. перейти к 0.
Это вообще с программированием ничего общего не имеет.
постановка задачи.
Ну вот, наконец то, то с чего и нужно начинать. Вначале нужно понять что же действительно хочет пользователь.
А не фантазировать: поддержание температуры в террариуме в заданных пределах (tmin, tmax), требуется учитывать инерционность тепловых процессов и т.п.
Я специально привел вначале самое простое описание - обычно с этого и начинают говорить что надо.
И задача программиста выбить все нужные знания у пользователя.
Что у нас есть на сегодня:
- Температура желательная
- Температура измеренная
- Внешняя функция включить нагреватель.
- Внешняя функция выключить нагреватель.
Что нам еще не хватает?
Хотя бы то, как представлена температура - как строка или как число. Для диаграмм и описания это не имеет смысла, а вот для конкретной программы нужно уже знать.
И тут мы подходим к типам данных.
Базовых не так уж и много
символ - 'A', 'B'
строка из символов - "asdfg"
целый тип - 0,1,2,3, -10
вещественный тип: 0.12345, -3.14
логический тип: Да, Нет.
В каждом языке существуют свои особенности определения и использования данных. В том числе и способ их представления в машинной форме. Но этих вопросов мы пока касаться не будем.
Пока ограничимся тем, что температура представлена вещественным числом и для ее ввода нужно просто вызвать внешние функции.
Хотя бы то, как представлена температура - как строка или как число.
Это не играет никакой роли в процессе составление алгоритма. Потому что определения пороговых значений для температуры это отдельная задача. Представьте, что градусник говорит на французском. То есть информация передается акустически. Ну и нафига усложнять теоретическую задачу дле начинающих.
написал достаточный алгоритм, который постоянно мониторит температуру и реарирует. Программист написал изящную реализацию, которая реагирует на события. Обе реализации достаточно абстрактны, что бы поднимать дополнительные модули для рассширения функтиональности. Не надо перегружать прогу подробностями, которые могут ВДРУГ понадобится.
Пока ограничимся тем, что температура представлена вещественным числом
-----
Ограничься - целым. Если нужна точность - задай единицу измерения 0.1, 0.01, 0.001 градуса.
Для вещественных тебе придется объяснять представление в виде порядок и мантиса с усечением/округлением - именно то чего ты пока касаться не хочешь.
Это не играет никакой роли в процессе составление алгоритма.
Вообще то играет, потому как 2+2 может быть и 22 и 9 не обязательно меньше 10
По крайней мере, если на входе строка, нужно показать ее преобразование в число.
Можно было и опустить, но мен хочется показать немного большее, чем просто обычная задача.
По крайней мере, уже видно, что раз для такой простой задачи, столько можно чего придумать, то что же будет для более сложной.
Зачем?
-----
Затем, что есть два вещественных числа - 22.3 и... 22.3... и при этом одно из них меньше другого.
Чтобы объяснить этот момент - придется углубляться в детали представления, а это на уровне Если...То...Иначе - лишнее.
По-этому есть смысл перейти к целым значениям 223 и 223 единицы по 0.1 градуса - это будет понятно и вполне однозначно.
Можно перейти и к 2231 и 2233 - по 0.01 градуса - тут уже будет видна причина неравенства 22.3 и 22.3.
я пользователя уже пытал и узнал что он действительно хочет
-----
У тебя есть проблема из 223 нарисовать для пользователя "22.3С"?
Вынеси в отдельную подзадачу и пусть ее реализовывают...
А внутри все должно быть так как должно быть - не надо преобразовывать в вещественное полученное дискретное. Его вообще не надо трогать - надо работать с тем что получено, однократно перегоняя заданные критерии к йeтому виду.
К тому же с точки зрения обучения есть еще один момент.
Нужно чтобы юниор учился мыслить абстрактно.
С этой позиции 223 которое более абстрактное значение много предпочтительнее 22.3 которое есть конкретная температура.
Еще раз скажу - сформулируй цель которую пытаешься достичь данным упражнением.
Вообще то играет, потому как 2+2 может быть и 22 и 9 не обязательно меньше 10
По крайней мере, если на входе строка, нужно показать ее преобразование в число.
Не в этом дело. Программист мог класс термометра полностью расписать. Вплоть до краски корпуса. Учитесь абстрагироваться. В градуснике вообще температуры может не быть, а как на термостате, 2 положения, одно для "слишком горячо" и другое для "слишком холодно". Аналоговые движки без единиц измерения.
Имхо не надо придумывать детали к учебной задаче. Эта задача для учебы на программиста, а не на следователя, который клиентам иголки под пальцы загоняет и информацию выпытывает. Имхо.
Красивое решение во первых простое. Во вторых масштабируемое. В третьих есть вещи основные и второстепенные. Например блок обработки температуры и принятия решения можно вынести. Тогда без разницы, какую инфу присылает термометр, блок обработки переводит ее в событие.
Я спрашивал, где это в задании?Я спрашивал, где это в задании?
Задание толком не написано, решил действовать сам, и сам всё делать (придумывать концепцию, до имплементации кода). Ну вот чтобы кота за хвост не тянуть, решил перейти из теории в практику... Значит, сделал как написано было в "учебнике", для начинающего электронщика, точнее это https://images-na.ssl-images-amazon.com/images/I/61xObTMZJ...:
Собрал как написано было в книжке, на шину посадил термистор и резистор, но забыл откалибровать, т.е. покрутить переменный резистор (слева):
В итоге показывает неправильно температуру.
Показывает -26°C, хотя в квартире как минимум +25°C градусов есть.
Когда закрываю рукой, хотя она тёплая +36°C, программа почему-то показывает -40°C.
Вот код измерения температуры с формулой:
Private Sub Timer2_Timer() . ' Die Timer2-Routine zwei wurde am Ende wie folgt erweitert ' um den NTC-Widerstand und die Temperatur zu ermitteln Dim U_mess_1000 As Single Dim R_NTC As Single ' OP hat zweifache Verstärkung! U_mess_1000 = (il × 2.5 / Val(Me.lb_2_5_Volt.Text)) / 2 ' Widerstand nach Masse = 1000 Ohm, Spannung daran ist U_mess_1000 ' U_mess_1000/1000 = U_NTC/R_NTC ' U_NTC = 5 Volt -U_mess_1000 ' R_NTC = U_NTC/U_mess_1000 × 10000 = ' R_NTC = (5 V-U_mess_1000) /U_mess_1000 × 1000 R_NTC = 1000 × (5 –U_mess_1000) / U_mess_1000 ' Anzeige des NTC Widerstands in kOhm Me.lb_R_NTC.Caption = Format(R_NTC / 1000, "0.0") & " K" ' Werte aus Tabelle B Wert und R25 Wert ' und in Temperatur umrechnen Me.lb_temp.Caption = _ Format(1 / (Log(R_NTC / 4472) / 3977 + 1 / 298) –273, "0") & "°C" CloseHandle: If FT_Close(lngHandle) <> FT_OK Then LoggerList.AddItem "Fehler bei Aufruf: FT_Close" Exit Sub Else End If . End Sub
Очень похоже, забыли только сказать чем рисовали. Немного неаккуратно и не совсем соответствует DIN 66001
Dia см. http://dia-installer.de/index.html.de, ею в коледже заставляли рисовать.
Задание толком не написано,
Специально, между прочим. Разделил на две части. Одна, так как сказали по телефону.
И не надо никакой практики.
Я уж не знаю сколько можно просить не делать длинные сообщения, раздражает ооочень сильно, скроллить разный мусор.
Диа была моей любимой программой раньше. Теперь потихоньку перехожу на yed.
Вот думаю отчего не пишут начинающие, может действительно непонятно
Гляньте здесь: следование и ветвление
Ну вот например, сюда все постить:
Blogger, Tumblr, Livejournal
Диа была моей любимой программой раньше. Теперь потихоньку перехожу на yed.
У меня есть Visio 2000 Enterprise, Visio 2002. А так-же есть Visio 2003 которая входит вместе с Visual Studio 2003 Enterprise Edition. Dia нравится больше чем Visio. Ok потом попробую Yed.
Вот думаю отчего не пишут начинающие, может действительно непонятно
Просто нет толком постановки задачи, да и начинающие скорей всего учат что-нибудь попроще. А с термометром там будет геморрой см. https://youtu.be/BCdCmPXgyYM?t=244, он ведь не в градусах значений возвращает, а там какое-то непонятное число, нужно термистер калибровать, это такой-же геморрой как столик у 3D принтера выравнивать...
С айти стало хуже, компьютеры дорогие, нужен хороший интернет, надо знать иностранный язык. В универах и интситутах больше математикой загружают.
непонятно почему при этом жалуешься
Ну да если напишу какие то волшебные слова, сразу очередь выстроится.
Вот для проверки одной идеи - можете мне в личку скинуть решение, я его анонимно выставлю.
Также интересно будет узнать отчего нет желания участвовать, хотя было валом вопросов как стать программистом и чем они там занимаются.
Просто нет толком постановки задачи,
Так и нужно узнать что именно не хватает.
Именно в данной постановке мне ее решили буквально сразу. Причем человек ни в технике , ни в программировании не разбирается.
А когда я показал оригинальное задание - сказали что не понимают.
Детали реализации, могут вполне отличатся, но основной алгоритм остается без изменений.
А с термометром там будет геморрой
Это когда нужно будет на работе такое делать, чтобы правильно работало.
А сейчас всё просто - вызывает функцию, получаем температуру.
Задача то ведь совершенно элементарная вместо 2 действий (ЕСЛИ выполнятся условие ТО действие 1 ИНАЧЕ действие 2) нужно сделать 3.
Это всё до чего нужно додуматься.
Так и нужно узнать что именно не хватает.
Я алгоритм сделал, см. выше. Мы мерием температуру внутри террариума (по логике внизу будет холодней, а вверху теплей), и при определённом промежутке, при котором холодно, и нужно включать нагреватель, и нужно правильно распределять тепло, и промежуток зависит от того, какое животное находится в террариуме. А хороший алгоритм зависит от наблюдений, а там ищете причину-следствия. Как минимум нужно знать на практике что такое конвекция - https://ru.wikipedia.org/wiki/Конв�%..., алгоритм нужно разрабатывать наблюдая террариум допустим спомощью инфракрасной камеры. По мне так только млекопитающим нужна определённая температура, иначе простуда, а гомойотермные животные при низкой темпераре могут просто впасть в спячку, я видел как муха в квартире упала из-за низкой температуры.
Приведу пример насчёт наблюдений: Дома есть мобильный кондиционер на колёсиках, когда мне летом или весной жарко, я его выкатываю, на нём можно задать минимальную температуру, при которой кондиционер будет включаться, как в квартире стало теплее минимальной температуры, так кондиционер автоматически включается, допустим я ставлю +18°C, а в квартире допустим +25°C, через 2 часа он выключается, т.к. думает что +18°C, смотрю на термометр который находится на расстояние в 2 метра, он мне показывает не +18°C, а что-то в районе +22°C. Т.е. радиус всего +18°C ~1 м. Через какое-то время квартира нагревается, мне уже жарко, а кондиционер думает что ещё +18°C.
Ну так еще лучше, кидай всё на страницу а ссылку сюда.
Зачем? Для 3х пользователей только для создания и модерации сообщений, а для всех остальных только для чтения.
НП.
Я сейчас занят, и играюсь в Java, делаю игру таракание бега, козе понятно что s=v*t, но тараканы могут то тормозить или назад возвращаться, там уже в помощь интегралы...
Я алгоритм сделал, см. выше
Если этот, то это совсем не то
https://foren.germany.ru/showmessage.pl?Number=37557463&Bo...
и нужно правильно распределять тепло
Ну сколько можно говорить, что подобные вещи нас абсолютно не интересуют
Валом было других вопросов - Кто научит быть программистом?
Читать и править чужой код. Обычно помогает, когда новичков бросают на устранение багов. Сначала новичок мужественно прокручивает метод в 10000 строк для поиска нужной строки, пока не начинает плеваться . Потом правит и видит, как прога разваливается. Потом пару раз правит архитектурно правильный код и видит, как в 2 клика нужный код находится, код, который к теме напрямую не относится, не видно и не слышно, изменения закапсулированы в классе, при изменении требований просто меняется класс и все защищено юниттестами. И внезапно приходит озарение.
Поэтому для новичка имхо очень важна группа, где он может видеть чужой код и получать звиздюли за свой.
Нужно идти все же дальше. Может потом кто-то еще захочет почитать.
Из того что мы знаем, нам в итоге нужно пойти по трём путям:
- ничего не делать
- включить нагрев
- выключить нагрев
Проблема, как это закинуть в ветвление у которого только два пути?
Довольно просто, нужно сделать два ветвления. Значить у нас должно быть и два условия.
На первый взгляд начальное условие просится само собой - если температуры равны, то ничего не делать.
Затем нужно проверить, что у нас с текущей (измеренной) температурой, если она меньше заданной то нужно включить нагреватель иначе выключить.
Теперь осталось вспомнить, что мы получаем температуры в виде вещественных чисел. Вроде какая разница целое или вещественное при сравнении? А она есть и следует пока просто поверить на слово и запомнить, что не следует проверять в лоб - А равно Б, если одно из чисел вещественное. Во многих случая, данную рекомендацию или не знают или игнорируют. И всё работает. Однако до некоторого времени, пока не звонит/пишет заказчик и говорит, что у него программа вдруг стала выдавать неверные результаты.
Поэтому правильное сравнение выглядит немного странно |А-Б| < x, где | | означают абсолютное значение, < обозначает меньше, а х - это допуск или точность. Например, если нас интересует расстояние между городами и мы получили два значения, будет ли нас интересовать равны ли они с точностью до метра или нет? А вот когда хотим заказать новую дверь, скорее всего измерим дверной проем с точностью до миллиметра.
В итоге у нас получается следующее описание:
Прочитать измеренную температуру (Tist) Прочитать/ввести желательную температуру (Tsoll) ЕСЛИ |Tist - Tsoll| < Tolerance ТО 1. ничего не делать ИНАЧЕ ЕСЛИ Tist < Tsoll ТО 2. включить нагреватель ИНАЧЕ 3. выключить нагреватель
Вот оригинальная задача
Jede Minute wird auf dem Raspberry mit CRON ein Python-Programm gestartet, das wie folgt abläuft:
Zunächst wird die Soll-Temperatur von einem Internet-Webservice gelesen und in der Variablen Tsoll gespeichert.
Dann wird von einem angeschlossenen Sensor die aktuelle Temperatur im Terrarium ausgelesen und in der Variablen Tist gespeichert. Wenn nun Tist<Tsoll-0,5°C, also zu kühl, ist, wird die Heizung eingeschaltet.
Dazu wird ein Unterprogramm mit Namen HeizEIN aufgerufen. Wenn es zu warm ist mit Tist>Tsoll+0,5°C, wird die Heizung mit Aufruf des Unterprogramms HeizAUS ausgeschaltet.
Damit ist das Python Programm am Ende.
В диаграмме некоторые изменения, но основа осталась неизменной
Кто хочет может добавить код на питоне.
Читать и править чужой код.
-----
Эээ...
Не совсем понятно кто это должен делать...
Ибо в практике желающих быть наученными быть программистами подразумевается кто-то кто прочитает и поправит, после чего клиент будет наученным быть программистом.
очень важна группа
-----
Один из таких новичков... имея, кстати, 5 баллов в профильном дипломе, звонил профессору и просил проконсультировать по очень сложному вопросу - как убрать из формы поле... не убирая поле из формы... Или другими словами - как поменять висибле с труе на фалсе....
И внезапно приходит озарение.
-----
Есть люди которые будут пытаться...
И есть люди которые будут смотреть как пытаются другие...
подразумевается кто-то кто прочитает и поправит
PullRequests. Обязательны для всех, для новичков это не формальность. То есть ВСЕГДА при правильной организации социалистического труда на код перед вливанием в основной репозиторий кто то должен взглянуть.
звонил профессору и просил проконсультировать
Надеюсь ночью? Самые лучшие советы рождаются ночью после внезапного звонка.😁👍
при правильной организации социалистического труда
-----
При правильной организации нуб может сидеть, смотреть и... становится прогером.
Какие тебе ПуллРекуестс? Там же надо кнопарики тыкать и стресс получится если тыкнуть не туда...
Неее, стресс - не нужен, нужно - чтобы научили быть программистом...
Надеюсь ночью?
-----
Не помню.
Помню, что после этого мне сказали - не трать больше времени...
Ну в начале не было задачи, вы хотели чтобы мы на кофейной гуще гадали, я долго думал про Tsoll и Tist... А нужно было так Tsoll Tist в математике именно так, или хотя-бы t_soll, t_ist
Вчера я оптимизировал код, но уже было поздно.... Делал я в PowerPoint-е.
НП.
В Универе у нас было меньше программирования, больше теории, т.е. решали какие-нибудь lim, всякие производные брали, программировали на Turbo Pascal толи версии 5, толи версии 7. В колледже меньше теории, а больше практики, и в сторону СУБД.
Ну в начале не было задачи, вы хотели чтобы мы на кофейной гуще гадали
Довольно странная отговорка, я ведь вроде ясно показать какое решение может быть в первом случае, там совершенно нечего было гадать.
Ну и после всех объяснений диаграмма получилось к совсем другой задаче.
Хотите играть дальше? Мне уже следующую задачку подкинули.
я долго думал про Tsoll и Tist
Отчего? Что тут неясно?
https://foren.germany.ru/showmessage.pl?Number=37568068&Bo...
Прочитать измеренную температуру (Tist) Прочитать/ввести желательную температуру (Tsoll)
2. Есть следующая таблица
Кто попробует добавлять и удалять данные, поймет насколько неудобно. А уж делать на этой основе программу, совсем ужос.
Требуется сделать нормальную структуру базы.
По многочисленным заявкам трудящихся:
"Имеется предприятие по продаже кофе. Оно продает несколько разных сортов кофе. Каждый сорт стоит нетто + накладные расходы(брутто). Имеются клиенты, которые покупают это кофе. Нужно наладить учет продаж и хранение информации в базе данных"
koder (C)
Требуется сделать нормальную структуру базы.
-----
Какой базы?
Таблица - уже задана - надо писать корректный бин и смотреть чем его класть/изымать из заданной таблицы...
Или у тебя "детская задачка" на нормализацию?
Ну тогда надо объяснить что такое нормальная форма базы, почему используется... и почему нарушается.
Какой базы?
а разве это имеет значение? Вот диаграмма выше для какого языка программирование нарисована?
Таблица - уже задана
И ты бы сразу по этой таблице сбацал что-то на оракле, например?
Или у тебя "детская задачка"
А что тут только с 18+ тема?
Если идти академическим путём, то всё уже описано до нас, искать нужное тоже надо учится.
https://info-comp.ru/database-normalization
https://otus.ru/nest/post/1812/
Но если хочешь можешь описать, как сделать что то приличное.
И ты бы сразу по этой таблице сбацал что-то на оракле, например?
-----
Разумеется.
Правда только для версии 11+ - ниже там Ентити не пашет...
Пойми - если не Я проектирую базу - мне пофиг какая она будет.
А в данном случае - Я - не проектирую т.к. таблица уже задана.
то всё уже описано до нас, искать нужное тоже надо учится
-----
Разумеется.
Вот только если цель обучение - надо и ставить задачу для обучения - ознакомится с описанным и применить к данному.
А вот так с напрыгу - как раз то что Я написал и будет...
если не Я проектирую базу - мне пофиг какая она будет
А мне не пофиг, какой смысл, делать то, что нужно выбросить сразу в помойку.
надо и ставить задачу для обучения
Ну так напиши как надо. Я исходил как бы из реальной жизни. Вот к тебе пришел чел. показал экзель и сказал - хочу базу к этому.
А мне не пофиг,
-----
Хи-хи... а мне пофиг что тебе не пофиг.
Бо, по факту, таблица - задана.
Какая ни есть - она уже определена.
какой смысл, делать то, что нужно выбросить сразу в помойку.
-----
Никакого.
Потому нефиг переделывать то, что после переделки пойдет в помойку.
Исключение - практическая учебная задача (ПУЧ).
Но для ПУЧ должно быть четко определено какую часть какой теории данная практика должна закрепить и теория должна быть доступна до начала работы над ПУЧ.
Ну так напиши как надо.
-----
Это - долго... и не нужно.
Достаточно указать какую часть теории надо изучить и использовать или дать ссылки на теорию.
показал экзель и сказал - хочу базу
-----
Ну и?
Вот - КАК ЕСТЬ - так и вколачиваешь в сервер.
Потому как пришелец не сказал, а ты - не добавил, в какой нормальной форме он это хочет...
а юниор, в принципе, не имеет понятия об том что есть какие-то нормальные формы и пока не ознакомится с теорией ему фиолетово на нормализации которые ты от него ожидаешь... просто не поймет об чем речь...
А уж делать на этой основе программу, совсем ужос.
Ужос. Делать программу на основе таблицы. Программа- это средство для обработки информации. И использует базу данных для хранения этой самой информации. Каждая программа имеет архитектуру, продиктованную задачами и организация хранения должна соответствовать этпй архитектуре. Вы же получили склад и думаете, какой бизнес можно замутить с этим складом. Начинать нужно с проги. И под нее органозовывать БД. Имхо
Что касается нормализации баз данных это алгоритм. Просто берешь по учебнику и выполняешь предписанные шаги.
а юниор, в принципе, не имеет понятия об том что есть какие-то нормальные формы и пока не ознакомится с теорией ему
Юниор теорию знать ДОЛЖЕН. Иначе это не юниор, а ученик. Юниор это работник с отсутствием опытa полностью закончивший обучение. И нормализация баз данных это базовые знания. Они обязательны.
Скорее наоборот, когда юниор полезет уже готовую и рабочую базу нормализовать, потому что выглядит она точно как в примере, ему обьяснят, что это исторически сложились и руками трогать то, что работает, нельзя.
А вот это опыт и с ТАКИМ опытом работник считается мидлом
Юниор теорию знать ДОЛЖЕН. Иначе это не юниор, а ученик. Юниор это работник с отсутствием опытa полностью закончивший обучение. И нормализация баз данных это базовые знания. Они обязательны.
Мна... Точно? А слабо сейчас, никуда не глядя, сказать чем, скажем 4NF отличается от 3-й? Единственный встретившийся мне "юниор", который мог отбарабанить эти определения, как программист был... ну... метров на пять под плинтусом.
Ну так напиши как надо. Я исходил как бы из реальной жизни. Вот к тебе пришел чел. показал экзель и сказал - хочу базу к этому.
Про нормализацию другие расскажут. У меня внезапный взгляд с другой стороны: я бы поинтересовался где у этого чела письменные согласия клиентов на обработку и хранение их персональных данных (имя) :) И всегда ли Claus это тот же самый Claus.
A. Ну для реляционной СУБД тут два варианта:
1)Создать таблицу с 3-мя полями, ID - первичный ключ, FIeldName - название поля, Value - значение:
ID | FieldName | Value
типа:
1 | LaufendeNummer | 1
1 | Datum | 01.02.2021
1 | Kundenname | Peter
1 | AnzahlKafee1 | 2
1 | Netto | 5,00
1 | Brutto | 5,20
2 | Datum | 01.02.2021
2 | Kundenname | Claus
2 | AnzahlKaffee2 | 1
2 | Netto | 3.50
2 | Brutto | 5.20
2)Сделать классы, сериализовать и запихать объекты в БД. Не знаю как в других языках сериализуется, допустим в PHP одним оператором, допустим:
class Tabelle {
public $Datum;
public $Kundenname;
public $AnzahlKaffe1;
public $AnzahlKaffe2;
public $AnzahlKaffe3;
public $Netto;
public $Brutto;
public function __consctructor()
{
....
}
}
Дальше создаёте объект
$record1 = new Tabelle();
$record1.Datum = '01.02.2021';
А дальше сериализуете и записываете в СУБД:
см. https://www.php.net/manual/ru/function.serialize.php
$ser_object = serialize($record1);
В C# тоже есть https://docs.microsoft.com/ru-ru/dotnet/api/system.runtime...
B. Для NoSQL вообще проблемы нет, в MongoDB хранятся в формате типа JSON, только BSON. Хотя есть агрегация см. https://docs.mongodb.com/manual/aggregation/, я бы в Insert см. https://docs.mongodb.com/manual/reference/method/db.collec... всё сразу что надо запихал бы. Пишите так:
use DatabaseTabelle1
db.tabelle1.insert({"LaufendeNummer":"1", "Datum":"01.02.2021", "Kundenname":"Peter", "AnzahlKaffe1":"2", "Netto":"5.00", "Brutto":"5.20"})
db.tabelle1.insert({"LaufendeNummer":"2", "Datum":"01.02.2021", "Kundenname":"Claus", "AnzahlKaffe2":"2", "Netto":"3.50", "Brutto":"3.70"})
C. Можно сделать всё это ввиде объектов и спомощью LINQ.
P.S.:Но вообще есть ещё вариант, но о нём я скажу вечером. В кратце нужно создать таблицу AnzahlKaffee, в которой будут поля: LaufendeNummer - вторичный ключ, Kategorie - (1, 2 или 3), и Anzahl - число..., получитсячто-то типа такого:
1|1|2
2|2|1
3|3|1
Основная таблица:
LaufendeNummer|Datum|KundenName|Netto|Brutto
1|01.02.2021|Peter|5.00|5.20
2|01.02.2021|Claus|3.50|3.70
3|01.02.2021|Wolfgang|2.50|2.70
Вторая таблица:
LaufendeNummer|Kategorie|Anzahl
1|1|2
2|2|1
3|3|1
Но лучше ещё так:
Основная таблица:
LaufendeNummer|Datum|KundenID|Netto|Brutto
2|01.02.2021|1|5.00|5.20
5|05.02.2021|1|7.00|7.40
Kunde:
KundenID|Name
1|Claus
Юниор это работник с отсутствием опытa полностью закончивший обучение.
-----
Это в тебе говорит остаток (пост)советского обучения.
Ибо по официальной статистике МинОбразования США 18% выпускников школ элементарно - читать, писать и считать - неграмотны.
Скорее наоборот
-----
Что будет на рабочем месте - пусть будет на рабочем месте - там много что будет не так.
В топике же говорится про задачи для начинающих. Т.е. для тех, у кого если и есть какая-то теория в голове то с практикой она никак не связана. Потому нужно не просто давать понятную себе постановку задачи, а сопровождать оную ссылкой на теорию.
Помимо этого еще надо четко понимать какие цели ставятся перед ПУЧ.
И эти цели - не нормализация никому не нужной таблицы, а то чего требуется добиться от обучаемого.
В данном случае - должен осознать и явить понимание того что такое "нормальная форма" и уметь обосновать применение 3-й, а не 5-й.
Будут ли ошибки, будет ли рабочий код - не суть важно.
Важно - чтобы осознал формы и был готов к следующему шагу - осознанию возможностей и ограничений связанных с конкретной формой.
Ужос. Делать программу на основе таблицы.
-----
А куда ты денешься?
Есть какой-нибудь комплекс - базы и куча софта. Большой - у меня было 2 ГБ спагетти-сорцов.
Ты либо пишешь на тех базаx что есть, либо переписываешь все 2 ГБ спагетти.
Ибо там совершено непонятно где именно вылезет небольшое изменение в базе.
А слабо сейчас, никуда не глядя, сказать чем, скажем 4NF отличается от 3-й
А я не юниор
Вообще то когда я действительно пришел первый раз на первую фирму, я как раз этот самый 4-й уровень и пытался впендюрить
На самом деле я не нормализую таблицы и не считаю, что делать это надо по памяти. Придется делать - подниму доки и сделаю..Более того. Если в проге нормально определены энтити в персистентном слое, то ничего вообще нормализовать не надо - база данных является отражением этох сущностей и может быть построена только одним образом - правильно. Поэтому в первую очередь классы сущностей, а потом база данных.
У меня внезапный взгляд с другой стороны: я бы поинтересовался где у этого чела письменные согласия клиентов на обработку и хранение их персональных данных (имя) :) И всегда ли Claus это тот же самый Claus.
Фигасе. Какой то не программистский взгляд. На самом деле именам в таблице потребления кофе делать нечего, но это совсем не вопрос защиты данных
1) Customer (customer_id, name)
2) Article (article_id, name, price_netto, vat)3) Order (order_id, datetime)4) OrderDetails (order_id(FK), customer_id (FK), article_id(FK), quantity)
НП
Тут напрашивается 3 класса и зависимости между ними. и, о чудо, мы действительно имеем место для сохранения Customer'a, Article и Order'a. Последняя таблица техническая для зависимостей.
И заметь, MrSanders написал "заказ только с одним клиентом связан".
Мы оперируем обьектами реального мира, которые отражены в классах и зависимости тоже реальные между обьектами. А таблицы только позволяют нам технически эти зависимости сохранять.
Но для ПУЧ должно быть четко определено какую часть какой теории данная практика должна закрепить и теория должна быть доступна до начала работы над ПУЧ.У нас тобой разные точки зрения на процесс обучения.
Я вообще не собирался затрагивать вначале теорию нормализации баз данных, потому как непонятно - проверено
Вначале нужно просто поиграться с тем что есть, попробовать добавлять и удалять данные, тогда сразу будут ясны проблемы.
продиктованную задачами
Задачи как бы и описаны данной таблицей. Больше у заказчика ничего нет.
Просто берешь по учебнику и выполняешь предписанные шаги
не работает, результат просто смешной получается. Нет понятия, что такое вообще база данных и таблицы, грубо говоря.
я бы поинтересовался где у этого чела письменные согласия клиентов на обработку и хранение их персональных данных (имя)
Не подходит под DS-GVO Оказывается даже для рекламы разрешено использовать "имя, фамилию, почтовый адрес, год рождения." без всякого согласия. Как раз получил рекламу на дом и занялся "расследованием".
И всегда ли Claus это тот же самый Claus
хорошо, что обратили внимание. Это был один из подводных камней о которых хорошо бы споткнутся.
Задачи как бы и описаны данной таблицей. Больше у заказчика ничего нет.
Заказчика убить. Он принес программисту готовое неправильное решение не написав, что это такое? Нет, ну реально, сделайте непонятно что из хрен знает чего? И это учебная задача?
Такую задачу может решить человек с опытом. Но на таких задачах нельзя ни учится ни учить. Это реальность из вселенной мурра
не работает, результат просто смешной получается.
У меня работало. Я действительно давно именно с таким заданием не сталкивался(ну просто это абсолютно устаревший стиль программирования), но когда то действительно в учебнике была учебная задача и пошаговый алгоритм позволял ее нормализовать
Заказчика убить.
Ну тогда даже и пулемётов не напасёшься. Как то мне еще не попадался заказчик который бы предоставил идеальное ТЗ.
У заказчика есть проблема, которую он пытался решить, вот с этой проблемой он и пришел к программисту.
Но на таких задачах нельзя ни учится ни учить
Ну покажите мне хоть кто то "правильную задачу" и как вы бы на ней учили?
пошаговый алгоритм позволял ее нормализовать
Алгоритм мона?
Может просто им (студентам) книги тупые дали? Я не знаю, мне показали только решение.
Мне вот кажется, что достаточно будет и 3х таблиц.
Достаточно и одной. Правильно 3 для обьектов и технические таблицы для связей, которые зависят от определенных связей. Эти связи и Программист и MrSanders вычисляли из исходной таблицы. Отсутствие поставленной задачи привело к разночтению и появлению бага. Была бы задача с описанием ситуации - было бы нагляднее
Пример. Программисты имеют 3 паузы , пьют в них кофе и в конце дня получают зарплату. 01.02.2021 Петер в первую паузу выпил 2 чашки, а потом не пил и получил зарплату нетто-брутто. Я понимаю, что в данном конкретном случае это атягивание совы на глобус, но без задания можно много нафантазировать и напрограммировать.
Как то мне еще не попадался заказчик который бы предоставил идеальное ТЗ.
Да причем здесь идеальный? Он у вас еще и немой и только одна рука, из которой на обрывке бумаги торчит таблица. Просто муму какое-то
Ну покажите мне хоть кто то "правильную задачу" и как вы бы на ней учили?
Имеется предприятие по продаже кофе. Оно продает несколько разных сортов кофе. Каждый сорт стоит нетто + накладные расходы(брутто). Имеются клиенты, которые покупают это кофе. Нужно наладить учет продаж и хранение информации в базе данных. imho
Поэтому в первую очередь классы сущностей, а потом база данных.
-----
В Ентити Фрамеворк реализованы два подхода - коде фирст и датабасе фирст.
Основной вопрос - кто больше взаимодействует с клиентом - базовик или прогер.
По мне - с клиентом взаимодействует базовик - ему нужно построить "правильную" базу и эта "правильная" база может существенно отличаться от того как она будет представлена прогеру.
Прогер же может лишь определить классы сущностей и молится на то что под них будет создана "правильная" база. Но его надежды - пусты - никакой сущностный класс не определит триггер, который будет синхронизировать текущую и стороннюю базы.
потому как непонятно - проверено
-----
Именно так.
Потому как это не делается с наскока - надо долго и аккуратно приучать к изучению тербазиса и ставить задачи таким образом чтобы разультат был достижим при понимании теории.
Мало того - нельзя делать - непонятно, еще раз непонятно и снова непонятно - результат такого подхода вполне предсказуем - пошло нафиг это ИТ...
Вначале нужно просто поиграться с тем что есть, попробовать добавлять и удалять данные, тогда сразу будут ясны проблемы.
-----
Да нет никаких проблем - есть таблица и в нее надо писать/читать данные.
Какие есть - такие и писать и в том виде в каком даст клиент.
А то, что потом отчет будет построить сложно - это тебе сейчас понятно, а юниору - нефига не понятно
- он та далеко не думает - у него огромная проблема - сформировать скл-инсерт для вставки в таблицу...
У нас тобой разные точки зрения на процесс обучения.
-----
Обучившиеся у меня успешно работают по специальности... сменив несколько поколений систем разработки.
ответ - изучить соответствующую часть теории.
ну не нужна пока никакая теория
Первое, что сразу видно, откуда брать цену на сорта кофе? И сортов несколько.
Значит нам нужна еще таблица по сортам кофе с ценами.
Есть еще клиенты, значить нужна таблица с клиентами. Ну и еще что то для связи всего воедино.
Вот теперь можно идти и читать как делать таблицы и как их связывать.
Ну так это всё из таблицы и видно
-----
Из нее ничего не "видно".
Из нее следует, что какая-то информация представлена в виде таблицы.
При этом не сказано, что можно добавлять строки и нельзя добавлять колонки.
Что именно представлено - не определено, ожидается оценка на основании (отсутствующегo) практического опыта.
Чтобы понять что именно не так - возьми ту же таблицу, но на китайском (иероглифами, именно так ее видит нуб) и поясни что там к чему.
Основной вопрос - кто больше взаимодействует с клиентом - базовик или прогер.
Какова цель процесса?Допустим базовик вылез вперед. В результате получаем какие то таблицы. Начинаем лепить код, пытаясь всунуть между описанием процесса клиенты и той хренью, которую налепил базовик. И потом ищем костыли, как сделать вот так, но но этак.
Есть стандартные решения для многих бизнес-процесов. Стандартные - это значит и проверенные на практике на стабильность, масштабируемость и легкость в сопровождении. И это значит, что проггер с первого взгляда узнает и понимает имплементацию. И есть решения "я это зделал, но не завидую тем, кто будет после меня разбираться с этим". Так вот, загоняя программиста между клиентом и базовиком мы вынуждаем его выкручиваться, лепя на коленке костыли. Итог немного предсказуем. Имхо.
ему нужно построить "правильную" базу
Я запущу на автомате построение базы и за 10 сек. получу готовую "правильную" базу из персистентного слоя. По готовым классам. Базовик месяц будет лепить таблицы и потом я еще полгода буду пытаться организовать сохранение в эти таблицы. И получится хрень.
и молится на то что под них будет создана "правильная" база.
Теперь я понимаю, Мурр, откуда твои вопросы про чудо чудное, которое делает диво дивное и в природе не существует. Окропление святой водой заменяет юниттесты
QНу так это всё из таблицы и видно
что видно? Что у программиста зарплата 7.00 нетто и 7.40 брутто? Я своих продактменеджеров за такие таблицы гоняю. Приказ, который может быть неправильно понят, будет неправильно понят.
откуда брать цену на сорта кофе
Найди в таблице слово сорт. Там количество чешек выпитого кофе. Найди в таблице слово цена. Там зарплата дегустатора кофе.
И если интерпретация сорта проданного кофе подразумевает зависимость количество-цена, то интерпретация дегустатор такой зависимости не имеет. Нетто и брутто привязаны к самому дегустатору. Упс.
Первое, что сразу видно, откуда брать цену на сорта кофе?
-----
Цена это куда?
Кофе это как?
Кому отослать - сорта?
Через что брать?
Все что "видно" - это только через твой личный опыт, через твою оценку содержания и, возможно, через какую-то дополнительную информацию от заказчика, которой ты не поделился.
У нуба ничего этого нет. Он смотрит на какие-то буквы, какие-то цифры, организованные в разреженную табличную форму и просто не понимает ни что с этим надо делать, ни что ты от него ожидаешь...
В той стране откуда Я сбег после переворота была мода на написание учебников - советские им сильно не подошли.
Писали много, писали разное.
Вот в учебник математики попала задачка:
У Пети 4 яблока,
У Маши 2 груши.
РЕШИ.
Но там хоть понятна цель - уничтожить образование как таковое.
Цель была достигнута - выпускают инженеров с опциональным знанием арифметики.
Причем, если мне не изменяет память, требования устного счета в пределах 10 заявлено для поступления в подготовительную группу в детском саду... потом 12 лет в школе...
Поэтому в первую очередь классы сущностей, а потом база данных.
-----
загоняя программиста между клиентом и базовиком мы вынуждаем его выкручиваться, лепя на коленке костыли
???
и за 10 сек. получу
-----
Ну давай попробуем.
Задача - прежняя - определить триггер, который при вставке выполнит некоторые действия в другой базе.
Ну или еще удобнее - вести лог (без информирования клиентa) записей просмотренных конкретной группой пользователей.
Если этого мало - Я найду еще кучу задач, каждая из которых выйдет за рамки простого хранения данных, подразумеваемого при использовании парадигмы коде фирст.
Не подходит под DS-GVO
Исчо как. Имя клиента это личная информация. Откуда его может узнать кофейня? Только если его сообщит клиент. (рекламщики могут валить на публичные источники вроде телефонной книги и "неперсонализированные" письма). Если кофейня собирается сохранять имя, она должна предупредить клиента и сохранить данное им согласие. А то будет больно.
она мне всё рассказала, что там написано
-----
Она у тебя слишком хорошо тебя знает... знает что ты можешь предоставить и что тебе надо сказать.
Но она у тебя не умеет читать задачу по-прогерски - т.е. интерпретируя неправильно все что может быть интерпретировано не правильно.
Как решать, да не знает.
-----
Ожидаемо.
Бо, требуется определить ряд понятий из области баз данных:
поле,
таблица,
запись,
первичный ключ,
ссылочный ключ,
реляция
и т.д. и т.п...
Потом нужно дать СКЛ и дать поошибаться на несоответствии типов, на нуллах, на отсутствующих ключах.
Тогда будет базис на который можно пытаться положить нормализацую.
Но вот если раз рядом есть студент, то отчего бы не
-----
Ну почему бы не поделится?
Поделюсь, если буду видеть, что пойдет на пользу...
Но пока Я такого не наблюдаю.
Наблюдаю - потребителя, который говорит - Дай!
А - Дай - уехал в Китай и сказал - никому не давай.
К тому же моя помощь может поломать какой-то учебный процесс - Я не в курсе чему и по какой методике обучают. Могу, конечно, определить дыры и постараться их заткнуть, но, возможно, просто забегу вперед и заткнув дыркi не дам набрать ожидаемого опыта.
Не так все просто в обучении.
не умеет читать задачу по-прогерски
ну так студент это по определению еще не умеет
Тогда будет базис на который можно пытаться положить нормализацию.
странно, вроде кто то очень знакомый, мне недавно тут писал, что начинать надо было именно с нормализации, дать ссылку - пусть почитают теорию.
дать ссылку - пусть почитают теорию
-----
Ну ты же сам сказал - не готовы, не могут.
Пришлось указать что нужно положить в базис чтобы были готовы и могли.
ну так студент это по определению еще не умеет
-----
Ну так учи.
Я в себе читателя года три убивал...
Я всё понял
В таблице указаны космонавты, которые должны
Во. А я между прочим третий день отлавливаю продактменеджера, которому в задании все было ясно, он так и написал- и соответственно дополнить. Теперь будем выпытывать, что такое соответственно и чем дополнить
требуется определить ряд понятий
А чего их определять, иди в академию и изучай туториалы
https://htmlacademy.ru/tutorial/php/databases
Узнаешь наконец что база данных - это программа, которая позволяет хранить и обрабатывать информацию в структурированном виде.
-----
Пример того как нельзя туторить:
https://docs.microsoft.com/ru-ru/office/troubleshoot/acces...
Задача - прежняя - определить триггер,
Задача- при починке машины использовать ключ на 17. Понимаешь, ты путаешь задачу и решение. Ты подбирает задачу под гаячный ключ, потому что он у тебя есть. И тебе очень хочется доказать, что не зря😁
Я найду еще кучу задач, каждая из которых выйдет за рамки простого хранения данных,
Без сомнения. Но все это исключения из правил и вовсе не материал для обучения юниоров. Каждое исключение это пакт с дьяволом. Потому что именно ты сожалел о тех, кто должен это все понять, когда тебя не будет. 😁
Я программист. Ну почти
-----
Хммм... техник-кодировщик - сойдет...
-----
Действительно - не твоя головная боль.
Я запущу на автомате построение базы и за 10 сек. получу готовую "правильную" базу из персистентного слоя.
-----
Но получишь ты, к сожалению, сурогат базы, пригодный для весьма ограниченного круга задач.
Я бы понял твою упертость, если бы у тебя был хоть какой-то механизм манипуляции всеми аспектами скл-сервера на базе твоих бинов, но, увы, там ооочень ограниченные возможности.
Но получишь ты, к сожалению, сурогат базы, пригодный для весьма ограниченного круга задач.
Ну начали письками меряться. Мой "суррогат" является стандартом для хранения данных. Твоя поделка на коленке будет глючить и в твое отсутствие ее выкинут нахрен. Потому что никто не понимает, как это чудо работает и где какие триггеры заныканы.
ВСЕ, что не стояло в техзадании это действительно не моя головная боль. Вот сейчас рефакторингом выкидываем нафиг из кода какие то непонятные поделки, которые предыдущие программисты налепили "на всякий случай". Потрачено дофига времени, куча мусора в коде, а ЭТО так никогда использовано не было. И теперь нужно еще больше времени, что бы понять, это действительно продуктивный код под конкретное задание или поделки скучающих самоделкиных.
всеми аспектами скл-сервера на базе твоих бинов
Чеееем? Надеюсь термин "аспект" ты применил в литературном стиле, а "скл-" это не сильно обидное ругательство
И мне не нужно ничем манипулировать. Ты опять отталкиваешься от инструментария. А не от задачи. Вместо автоматической сварки ты используешь гвозди и радуешься, что можешь вбивать их гуда хочешь и как хочешь. И главное для тебя сам процесс вбивания.
ВСЕ, что не стояло в техзадании это действительно не моя головная боль.
-----
Ну в тех.задание тебе создание триггера вписали - в этом проблемы нет.
А вот инструментария для его создания у тебя нет. И это - головная боль.
Потому что никто не понимает
-----
Интересно девки пляшут...
Кто-то разрабатывал СУБД, делал возможность в определенной ситуации использовать функционал написанный прогером, а тут пришел Кодер и говорит - то, что написано, никто не понимает...
Я, как человек доверчивый, поверил бы, но...
...мешает то, что в группу тех кто поленился освоить триггеры Я не попал.
Это Я еще не стал оценивать Жабу с точки зрения одной буржуазной лженауки...
А не от задачи.
-----
В соседней ветке лежит вопрос по тому какая база поддерживает вполне применяемую на практике, но не укладывающуюся в рамки традиционных реляционных баз, задачку.
Спляши, плс, от задачки...
И задачка - не единственная, которая не укладывается...
А вот инструментария для его создания у тебя нет. И это - головная боль.
Упс, Сколько времени займет добавление триггера в готовую базу?
делал возможность в определенной ситуации
Именно так. Разумеется есть специфичные задачи. Но это исключение из правил и редкий случай. А в стандартной ситуации (типичное сохранение данных в базу) нужно использовать стандартные средства. А когда начинаются "определенные ситуации" на уровне базы начинается жопа при отлове багов. Ибо ВДРУГ сохранение начинает "в определенных ситуациях" работать не стандартно.
Есть еще один минус. Такие нестандартные костыли сложно покрывать юниттестами. Доступ к базам данных как правило тестируются набазах "в памяти". H2 например. В них очень сложно воспроизвести весь этот зоопарк с нестандартными решениями и триггерами.
В соседней ветке лежит вопрос по тому какая база поддерживает вполне применяемую на практике, но не укладывающуюся в рамки традиционных реляционных баз, задачку.
Типичный случай, когда решили делать через жопу. Подготовили решение не имея понятия о инструментарии. Проблема не в задаче, которая может быть решена по разному. Проблема в уже готовом решении, которое не имеет практической реализации и с которым как раз ты муздохался. Поэтому и муздохался, что решение нестандартное, нужны костыли, нужно что-то этакое, чудо чудное.Задача как раз укладывается. Не укладывается ваше решение этой задачи.
Покажи свое решение
Ну надо вначале, хоть как то пояснить как к нему прийти. И без дополнительных уточнений уже не обойтись.
Первое, что решили - это вынести кофе с ценой в отдельную таблицу. Нужно еще решить как будем связывать таблицы между собой, решаем через дополнительное цифровое поле, значения в котором будут уникальны. Значения этого поля будут создаваться автоматически и после создания не имеют права изменится.
Дальше нужно будет решить, что делать с количеством отдельных заказов. Так как их не предполагается иметь больше трёх решаем иметь для каждого заказа отдельную строку. Если бы кофе приходило на склад десятками или сотнями, то нужно было создать колонку "количество".
Осталась еще одна проблема, которую сразу можно и не заметить - изменение цены на кофе с течением времени. Решаем пока эту проблему игнорировать, иначе нужно добавлять дополнительные поля.
В итоге получилось следующее:
Ну очевидно, что твое решение не позволяет казывать несколько чашек кофе.
Посмотри на картинку:
Тут есть возможность включить в заказ не только заказать несколько чашек одного сорта кофе, но можно еще заказать все 3 сорта кофе одновременно.
Так что твое решение не покрывает заданную тобой таблицу.
Вот только удаление данных из таблицы "сортов кофе" лучше запретить.
Чой-та? Разрешаем удалять если не используется. ON DELETE RESTRICT
А ещё тут спряталась гадкая штука... А что мы будем делать когда цену кофе поменять надо будет? Если старые счета ссылаются на запись, и не хранят цену сами, то они внезапно изменятся. И окажется что клаус 5-го числа не 7.40 заплатил, а 8.60.
Чой-та? Разрешаем удалять если не используется.
Ну и как это всё сейчас объяснить? - ON DELETE RESTRICT и прочее...
А ещё тут спряталась гадкая штука...
Осталась еще одна проблема, которую сразу можно и не заметить - изменение цены на кофе с течением времени. Решаем пока эту проблему игнорировать
Ну и как это всё сейчас объяснить? - ON DELETE RESTRICT и прочее..
Ну так же как и "почему нельзя удалять". Но да, согласен, проще сказать что запретим удаление, чтобы не сломать табличку.
Решаем пока эту проблему игнорировать
Ой. Невнимательно читал.
Упс, Сколько времени займет добавление триггера в готовую базу?
-----
Так ведь при твоем подходе - до бесконечности - у тебя просто нет такой возможности.
А в стандартной ситуации
-----
А у нас точно стандартная ситуация?
А если не стандартная, то сразу появится возможность создать триггер в базе?
Проблема не в задаче
-----
Ну значит нет никакой проблемы получить решение!!!
Тебе скинуть бины которые подойдут для задачи или сам набросаешь?
Потом в 10 секунд сбросишь в базу... и у меня пропадет головная боль по этому моменту.
Не укладывается ваше решение этой задачи.
-----
Предложи другое.
Задача простая: тематический каталог, группировка какой-то информации по каким-то темам, добавление, получение, разделение и т.п.
Все - тривиально. Все - понятно. Все - описано.
Вот только ни одной толковой имплементации пока не нашел.
Бухгалтер не будет рад такому решению
Уж до кого нам нет дела, так это точно до бухгалтера
Нету тама бухгалтера, есть только официант.
Зато хорошо видно, сколько может быть проблем для казалось бы простой задачи.
Это всё к тому, что могут дать курсы. В лучшем случае это:
https://siblec.ru/informatika-i-vychislitelnaya-tekhnika/b...
А всё остальное нужно уже думать/изучать самому. Хотя многие проблемы будут видны только с опытом.
По крайней мере, те кто собирается сменить профессию, могут получить небольшое представление что их ожидает.
Если старые счета ссылаются на запись, и не хранят цену сами, то они внезапно изменятся. И окажется что клаус 5-го числа не 7.40 заплатил, а 8.60.
Неудобно и не всегда возможно. Я покупаю кофе. Выбираю товар из списка. А откуда возьмётся цена? При каждой покупке с бумажки вручную забивать? На самом деле это можно сделать 2-мя способами. Кофе имеет цену. И покупка имеет стоимость, которую она получает от кофе в момент покупки. Тогда при изменении стоимости кофе стоимость покупки не меняется. Или при изменении цены на кофе просто закладывать новый товар.
Или при изменении цены
-----
В таблицу Цены вносится запись об новой цене. "Старые цены" - никогда не изменяются и не удаляются.
Кстати - цена действует от установленной даты до... установленной даты. Ну так в тех.задании определили "периодичность" изменения цены. Т.е. при установке новой цены нужно внести изменения в запись об предыдущей цене - до... установленной даты - поменять.
Как менять будешь? Транзакцией с двумя-тремя запросами или повесишь триггер на табличку? Если вдруг триггер - то как ты его туда по твоей методике повесишь?
В таблицу Цены вносится запись об новой цене.
Пока такой таблицы не было. Но да. Так лучше. Если нет партий товара с фиксированной ценой.
Как менять будешь?
Никак. Есть класс "кофе". Если подгрузка цены автоматическая, то при создании обьекта класса он получит цену по алгоритму(последнюю или по дате или по дню недели или прямым пользовательским выбором из списка итд). При создании обьекта класса "закупка" этот обьект тоже получит ссылку на обьект класса "цена". То есть цена есть и у кофе и у закупки. При изменении цены у кофе предыдущие закупки свои цены не меняют - привязка не через товар, а прямая.
И эта операция это логика на уровне программы. База данных просто хранит обьекты и обеспечивает целостность информации, не давая, например,
удалить задействованные цены.
Никак.
-----
Никак - не пойдет.
По условию - на каждый момент времени имеется одна цена.
Поэтому при изменении цены требуются две операции:
- добавить запись с новой ценой и периодом применения
и
- изменить верхний предел применения в старой цене.
Вопрос лишь в том каким инструментом это делать.
и обеспечивает целостность информации
-----
Вот и обеспечивай - у тебя не явный констрайнт на недопустимость двух цен в одном периоде.
Можно, конечно, считать каждый раз, но это куда проблемнее триггера на таблице.
добавить запись с новой ценой и периодом применения
Маска программы для импорта или внесения новой цены. Это никаким образом не влияет на существующие классы. И на сохраненные объекты.
изменить верхний предел применения в старой цене.
Не надо. В смысле не обязательно. Прога просто выберет нужную цену согласно алгоритма. Через маску управления ценами можно действительно отключать цены, которые нельзя больше использовать. И можно иметь несколько цен р при заключении операции продажи выбирать.
у тебя не явный констрайнт на недопустимость двух цен в одном периоде.
А с чего это они недопустимы? Кто сказал, что не может быть несколько цен на один товар в одном периоде? При фиксированной наценки и нераспроданных остатках остатки можно продавать и по низкой старой цене. И неявных констрейнтов не бывает. У меня абсолютно жёсткая зависимость продажа- цена. И вообще нет зависимости товар-цена на уровне базы, прога подбирает цену товара по алгоритму, например в пятницу скидки.
И можно иметь несколько цен
-----
Это не меняет ситуацию.
выберет нужную цену согласно алгоритма
-----
Какова "цена" работы "алгоритма"?
Кто сказал, что не может быть несколько цен на один товар в одном периоде?
-----
Я сказал. Упростил для понимания.
Хочешь несколько - дополнительный ключ в таблицу и... снова пункт 1. - триггер или код в аппe...
А вот на то, что с твоей структурой данных нельзя получить таблицу из задания
Что конкретно нельзя получить?
Всё что там есть - это то, что определённый клиент имеет несколько заказов в определенный день.
То что они должны быть в группе никого не волнует, а если заволнует легко решается введением дополнительной информации. Для данного случае это усложнение совершенно нецелесообразно.
Какова "цена" работы "алгоритма"?
Сколько стоит подгрузить 3 записи из базы данных и дать бухгалтеру список для принятия решения? Сколько стоит загрузить ПОСЛЕДНЮЮ внесенную запись?
Хочешь несколько - дополнительный ключ в таблицу и... снова пункт 1. - триггер
Да причем здесь триггер? Триггер реагирует на событие и манипулирует записями в базе данных. Здесь нормальное управление записями. Производится из проги. Нафига здесь триггер, когда мы просто из нормальной маски программы закладываем новую цену?
Сколько стоит загрузить ПОСЛЕДНЮЮ внесенную запись?
-----
Неправильная постановка вопроса.
Правильная - Сколько стоит загрузить запись об цене на конкретную дату?
Ответ - зависит от организации хранения, в худшем случае - количество сканов таблицы по количеству записей.
Производится из проги.
-----
Можно. Но будет - дороже.
когда мы просто
-----
Да-да... в общем - напиши два решения - твое, а потом - с триггером.
Потом сравни чего и сколько там есть.
Правильная - Сколько стоит загрузить запись об цене на конкретную дату?
Ответ - зависит от организации хранения, в худшем случае - количество сканов таблицы по количеству записей.
Записи сначала фильтруются по товару. Это индексируемое поле. Потом остаётся столько записей, сколько было изменения цен на товар. Сколько это может быть? Пара? Пара сотен?
Можно. Но будет - дороже.
По другому нельзя. Товар нельзя привязывать к цене по констрейту. Во первых теряется возможность выбрать цену. Во вторых ты вводишь в манипулирование данными логику, лежащую за пределами программы. Это делать категорически нельзя. Завтра вылезет баг, программист поставит на уши весь код и не найдет место, где цена присваиваиваеься товару. Сегодня одна, а завтра вдруг другая. И никто не видит, как втихоря данные подменяет триггер. Это отвратительный стиль программирования .
Сколько это может быть?
-----
Много.
У нас, на небольшом производстве, объем базы превышал 20 гиг...
И, кстати, была проблема с расписанием смен - точно такая же, как с ценами и ценниками...
Сегодня одна, а завтра вдруг другая.
-----
Именно так оно и работает.
Вчера была одна, на сегодня задана другая, а с завтра и до следующего изменения - определена третья.
И никто не видит, как втихоря данные подменяет триггер.
-----
А кто должен видеть?
Ты же говорил - база должна оставаться в порядке. Вот триггер об этом и позаботился.
То, что кодер не знает и не понимает, что база, по природе, слегка более сложное образование чем то, что создается сбросом бинов за 10 секунд - понятно и можно считать - нормально.
А вот то, что он
роет код и не смотрит в доки где прописано "заполняется триггером" и не догадывается посмотреть базу - ну так что с него взять - пусть лепит что умеет.
Это отвратительный стиль программирования.
-----
Отвратительный стиль программирования - использование техников-кодировщиков на месте инженеров-программистов.
Грамотное использование имеющихся инструментов - вполне нормальное явление.
У нас, на небольшом производстве, объем базы превышал 20 гиг.
Мурр, ну ты понимаешь разницу между базой данных и списком цен к одному товару? Ну меняй их 2 раза в день, 10 лет - 10000 записей. Найти последнюю это смешная задача.
вот то, что он роет код и не смотрит в доки где прописано "заполняется триггером" и не
Ты никогда не правил баги? У меня их десятки в день и я разумеется посмотрю в доках. Если в коде не найду. Только в хорошем коде я найду проблему сразу. Класс ентити персистентного слоя или клас репозитори.. Не через полчаса, а вот просто открою соответствующий класс и СРАЗУ увижу проблему. Пока ты в не то что доках хоть что нибудь найдешь, а просто доки найдешь.А скорее всего не найдешь. Куча задокументировано мусора это тем не менее куча. Чем больше слепленных на коленке хреней, тем больше доку. Я слышал, у тебя часто тупая молодежь не справляется? Наверно не успевает доки дочитать? 😁
использование техников-кодировщиков на месте инженеров-программистов.
😁
между базой данных и списком цен
-----
Все необходимое имеется в исходной таблице.
Только вот из нее просят сделать нормальную базу...
Только в хорошем коде я найду проблему сразу.
-----
Поверь - в хорошем коде, т.е. в коде который базируется на теории которую ты не изучил, ты будешь искать баг до второго пришествия... при том что в коде его не будет, а ошибка будет иметь место.
Чем больше слепленных на коленке
-----
База, сброшенная из персистентного слоя как раз относится к разряду слепленных на коленке.
Ее единственное преимущество - можно использовать кодеров не имеющих знаний по базам данных.
у тебя часто тупая молодежь не справляется?
-----
Не часто, а регулярно. Их просто недоучивают под мои задачи.
Именно поэтому Я редко рекомендую кому-то в возрасте начинать вползать в ИТ - изучать - много, будут сидеть на равных с туповатыми недоучками.
невозможность заказать больше одной чашки за один раз
Ну это тоже твоя интерпретация
Гораздо проще "нажать заказ" два раза, чем от открывать заказ, добавлять продукт, закрывать заказ. В любом случае это повлечет некую дополнительную информацию, которая для данной задачи совершенно лишняя. Мы ведь хотим только показать, как сделать из большой "неправильной" таблицы одну "правильную" в смысле понятия нормализации базы данных. То что при этом могут возникнуть определенные проблемы, пока скажем так - не интересует.
После окончания 1го этапа можно сделать ревью и там уже решать, что делать дальше.
А пока я просто позвонил заказчику и он мне подтвердил, что это ему действительно не нужно, как и 1я колонка с номерами. Но если вместо только даты будет и время он не возражает.
Так что в итоге получилось следующее
Еще правда забыли подискутировать отчего названия на немецком, а не на английском, отчего KundeId, а не kunde_id, названия таблиц в множественном, а не в единственном числе и пр.
Поверь - в хорошем коде, т.е. в коде который базируется на теории которую ты не изучил
Такого кода не существует. Мы ж говорим о нормальной фирме, не о партизанском отряде? Это значит, что самодеятельноe введение новых технологий категорически запрещено, а введение сопровождается ОБЯЗАТЕЛьНЫМ обучением команды. Упс
База, сброшенная из персистентного слоя как раз относится к разряду слепленных на коленке.
Мурр, тебя начинает нести. В чем смысл обругивать стандартные классические библиотеки, перенесшие сотни релизов и протестованные миллионами програмистов?
Не часто, а регулярно. Их просто недоучивают под мои задачи.
Честно, это показатель. Когда люди регулярно недопонимают какие-то задачи, я бы серьезно задумался, а виноваты ли в этом люди. Или все-таки задачи.
Я еще не видел человека, который не смог бы разобраться с построением стандартного веб-приложения на спринге. Простого, надежного, стабильного и быстрого.
Получилось хорошо.
Но ты заметил. что от таблицы плясать невозможно - получается неоднозначный результат. Причем на уровне базы данных все варианты были технически правильные. Пришлось "звонить" клиент.
А вот если бы мы начинали c задания, такой проблемы бы не возникло. В этом смысле новичков лучше учить от задания моделировать бызы данных или классы. В этом случае ошибка будет сразу видна - не будет разговора о интерпретациях.
А вот если бы мы начинали c задания, такой проблемы бы не возникло.
Сколько помню было заданий, как начинаешь делать/задумываться - всегда возникают вопросы.
Так что ставить вопросы - этому как бы тоже надо научится.
Задания выставлялись точно в таком виде как я их получал, но и даже додуматься, что кому то придёт в голову паковать чашки кофе в ящики и отправлять их единым заказом я бы не смог, соответственно никогда бы об этом не написал.
А вот рассказать дальше, что делать - это пожалуй нужно.
Итак, то что мы получили выглядит гораздо лучше исходного варианта, но где же тут база данных?
Можно, конечно продолжить все в эксель, но это явно не наш путь.
Для "нормальной" реляционной базы данных, типа - MySQL, Ms SQL Server, Oracle, PostgreSQL, SQLite и пр. нам понадобится создать базу данных, создать таблицы и наполнить их какими либо данными.
Процесс для новичка довольно сложный и описать его в двух словах никак не получится. Главное что нам нужно сейчас знать - то что мы сделали это только начало. Мы всего лишь определились с таблицами и какие данные туда будем записывать.
Для создания описания базы данных, так называемой ER-модели, нам нужно определить немного больше. Требуется еще определить типы данных в столбцах - будут ли там целые числа, вещественные числа, строки или что другое. Так же требуется определить может ли значение отсутствовать - быть нулевым. Например имя клиента или сорта кофе никак не может отсутствовать - это будет ошибкой. (Не будем рассматривать ситуацию, когда в эти поля просто записывают пустую строку)
Также нам надо будет определить индексы для таблиц и как таблицы соединяются между собой.
Проще всего сделать модель базы данных в специальной программе, как например
https://www.devart.com/entitydeveloper/
И разрешить ей создать базу данных на основе модели.
Программа бесплатная, если у вас меньше 10 таблиц. Для большего количества нужно уже иметь что-то платное от этой фирмы (например dotConnect for SQLite)
В этом случае модель может выглядеть следующим образом
Стрелочки показывают так называемые отношения (relation), а надписи 1 *, говорят о том что одна запись из таблицы клиентов, может повторятся много раз в таблице заказов.
Данная программа может также создавать программный код описывающий базу данных.
сопровождается ОБЯЗАТЕЛьНЫМ обучением команды.
-----
А что КОМАНДА делала в униках?
В чем смысл
-----
Не знаю.
Есть - рутина - пишешь стандарт и будь доволен.
Есть - разработка - пишешь что-то что соответствует какой-то теории и что написать без понимания теории невозможно.
По твоему вопросу - что делали такие же миллионы базовиков когда кодеры создавали базы доступным им способом?
Я еще не видел
-----
Посмотри на Кота. Посмотрел? Теперь ты видел того кто не разобрался в реализацией одного веб-приложения.
Где-то пару лет назад искал готовый форум реализованный на шарпе. Форум - нашел, работать - заставил. Как реализовано - не понял.
Просто не хватило времени на изучение того что использовалось.
А что КОМАНДА делала в униках?
Базы данных учила. А тут бац и хайбернет подогнали. А тут бац и спринг джипиэй родился. В нормальной фирме создается ударная группа, которая пробует прикрутить новую технологию к проекту. Потом, по результатам, либо вся фирма переходит после обучения либо никто. И да, на фирмах регулярные (блин, чуть не написал "шулюнги" ) семинары для всех. У нас внутренние один час в неделю.
По твоему вопросу - что делали такие же миллионы базовиков когда кодеры создавали базы доступным им способом?
Я не понял вопрос. Я много лет сам писал модели баз данных. И лепил приложения к этим базам. Потом попал в команду, где показали, как можно делать по другому. Проще, быстрее и надежнее. Начинать не от базы данных, а от модели классов, которая описывает сущности программы. Результат получается похожий. Но не совсем.
С сущностями на уровне классов проще моделировать. Берем покупателя. Никому и в голову не придет покупателю добавить цену. То есть сущность сразу на этапе моделирования интуитивно понятна. Есть товар. И есть закупка. Мы не скидываем все в кучу и не делим потом "а это поле куда?", нормализуя таблицы. Мы просто описываем процесс закупки.
Теперь ты видел того кто не разобрался в реализацией одного веб-приложения.
В контексте дисскуссии я бы так откыто этим тезисом не размахивал. Но я промолчу
Базы данных учила.
-----
И таки никто так и не дошел до триггеров?
Странно... меня вот не учили, а откуда-то оно у меня есть...
семинары для всех.
-----
Хорошо. Но не заменяет...
С сущностями на уровне классов проще моделировать.
-----
Блин...
В Ентити реализованы ДВА подхода.
Хочешь - лепишь код и по коду сбрасываешь базу.
Хочешь - лепишь базу и по ней строишь код.
При сбросе базы из кода одни ограничения, при лепке кода из базы - другие.
Но! При лепке кода из базы ограничений меньше.
То есть сущность сразу на этапе моделирования интуитивно понятна.
-----
Тебе что-то мешает реализовать сущность в виде таблицы?
Бин и его дефолтное пустое расширение лепятся и поддерживаются автоматом.
В контексте дисскуссии
-----
Именно в контексте - недоизучал, не хватило времени... недоучка в той области.
И таки никто так и не дошел до триггеров?
Смотри, пример из жизни. нужно зайти в комнату, пропылесосить, помыть полы, уйти из комнаты. У тебя это выглядит так. Работник заходит в дом и его замечает триггер. Пока работник поднимается по лестнице, триггер лезет в окно , пылесосит и убегает опять через окно. Работник заходит, опа, уже пропылесошено, осталось помыть полы. И все, блжет, работает. До тех пор, пока что то не изменили. И ВДРУГ стало непропылесошено. Кто, где когда пылесосил никто не знает, чртов триггер лазил через окно и его теперь никто не найдет.
Любой дурак может повесить триггер в конкретной базе данных. Нужен доступ и мануал. Но еще раз, триггеры - это последнее средство для стандартных мероприятий. Это внутренние дела базы данных, можно организовать логгирование, но никогда CRUD - операции
Хочешь - лепишь базу и по ней строишь код.
Но! При лепке кода из базы ограничений меньше.
Потому что лепка у тебя самодельная. Если база сделана не под энтити, то черта с два ты их туда нормально засунешь. А это значит костыли в коде. А это значит херня.
Тебе что-то мешает реализовать сущность в виде таблицы?
Ничего. Кроме того, что сначала ты неделю программируешь базу данных. А потом я неделю набиваю по базе руками классы. А наоборот я набиваю классы(или строю УМЛ-диаграммы) и за 10 минут получаю готовую базу. Неделя экономии.
Любой дурак может повесить триггер в конкретной базе данных. Нужен доступ и мануал. Но еще раз, триггеры - это последнее средство для стандартных мероприятий. Это внутренние дела базы данных, можно организовать логгирование, но никогда CRUD - операции
В общем случае - нет. БД может использоваться как "связь" межу приложениями. Хоть это и не очень хорошо. И тогда триггер это самое простое и адекватное средство.
В примере с кофе - представьте что у нас одна база со счетами и бухгалтерией - таблицей, в которую записано сколько кофе каждого сорта продали, к которой лезут два приложения - официант и бухгалтер. Официанта интересуют только счета. Бухгалтера - только продажи. Кто из них должен лезть в чужие ентити? Бухгалтер в счета официанта или официант в бухотчетность? А почему бы через триггер в базе не увеличить счётчик проданного кофе?
Если база сделана не под энтити, то черта с два ты их туда нормально засунешь.
Хибернейтом - геморройно. Что скорее говорит о качестве хибернейта. Ручками - без проблем.
А наоборот я набиваю классы(или строю УМЛ-диаграммы) и за 10 минут получаю готовую базу. Неделя экономии.
Ага. А потом три недели пытаемся оптимизировать запрос, для которого я пишу sql, отрабатывающий за 3 секунды, а хибернейт щелкает 3 часа если не вываливается с OutOfMemory. Получается проще 2 недели на базу и "ручной" доступ к ней потратить.
Надо сказать что я года с 2010 пытаюсь где только можно избегать хибернейта. Ну не работает такое общее решение в сложных приложениях. Его конфигурация становится чуть ли не самой сложной частью, которая ещё и с каждым bugfix-ом норовит сломаться. И в конце-концов всё равно пишем в самых критичных местах не hql а sql запросы. Ну и нафига тогда всё городить?
Но не всегда получается... Вот сейчас опять - нужна пакетная обработка порядка 10 миллионов записей. И всё написанное на хибернейте радостно хрюкает больше суток. Это уже знатоки хибернейта убили больше месяца на оптимизацию. Делаем триггер и вьюшку - опа, отрабатывает за 30 минут. Тоже плохо - часть бизнес-логики пришлось в бд пихать. Но уж лучше так.
В примере с кофе - представьте что у нас одна база со счетами и бухгалтерией - таблицей, в которую записано сколько кофе каждого сорта продали, к которой лезут два приложения - официант и бухгалтер.
Не могу. Представь, что что у тебя есть малознакомый человек. И тебе нужно отдать деньги. Вместо того, что бы просто отдать, ты заводишь с ним общий счет. Общий!!!! Это категорически неправильно. Каждое приложение должно быть изолировано и общаться с другими только через интерфейсы. И трижды должно быть изолировано хранилище данных.
Хибернейтом - геморройно. Что скорее говорит о качестве хибернейта. Ручками - без проблем.
Нет. Хайбернет это только стандарт де факто. Если можно без проблем стандартно, то нестандартно - это коствль. Ф топку
Ага. А потом три недели пытаемся оптимизировать запрос, для которого я пишу sql, отрабатывающий за 3 секунды, а хибернейт щелкает 3 часа если не вываливается с OutOfMemory.
Это говорит о качестве модели. И о умении пользоваться персистентным слоем.
тоже плохо - часть бизнес-логики пришлось в бд пихать.
Смотри. Это плохо. Это ты написал. Это значит что это либо действительно исключительная ситуация, которая встречается не каждый день. либо что то плохо сархитектурено. И нужны костыли.
Я понимаю, что когда корабль тонет, нужно использовать то, что есть. И цеплятся за доски. Или если по другому НИКАК нельзя, то можно то, что нельзя. Но в нормальной стандартной проге нужно (имхо) использовать только стандартные решения. И неважно, что нестандартные быстрее, если скорость не критична. Легкость сопровождения важнее. Имхо
если скорость не критична
В этом то и заключается проблема. Когда речь идет о миллионах записей, будешь делать, что угодно лишь бы запросы выполнялись быстрее.
Помнится были и триггеры и stored procedure и materialized view.
Обращаем внимание на постскриптум
нужно зайти в комнату, пропылесосить, помыть полы, уйти из комнаты.
-----
нужно зайти в комнату, помыть полы, уйти из комнаты?
никто не знает
-----
Ты всего лишь пытаешься утверждать, что поскольку у тебя (и коллег) нет инструмента для определения триггера при написании бина, то... никто не знает и на этом основании оно вредно.
Потому что лепка у тебя самодельная.
-----
Какая разница какая она у меня?
Ентити - стандарт для .Нет и там ДВА варианта.
Кроме того, что сначала ты неделю программируешь базу данных.
-----
Ээээ???
Вообще-то, это на уровне подготовительной группы детского садика.
Если мне удобно - а иногда мне удобнее конвертировать документацию в скрипты - делаю скрипты. Да - руками, да - долго. Но обычно все же быстрее чем даже построение УМЛ.
Если мне не удобны скрипты - пользую любой редактор с визуальным представлением - хоть ЭМ, хоть Деварт, хоть... Аксесс...
А потом я неделю набиваю по базе руками классы.
-----
Ну это твое дело - хочешь руками - делай руками.
А вообще-то встроенный генератор кода есть. И если код не устраивает - можно и шаблоны подредактировать - пока код будет соответствовать требованиям, а там довольно вариативно, Ентити - никаких проблем не будет.
А наоборот я набиваю классы(или строю УМЛ-диаграммы) и за 10 минут получаю готовую базу.
-----
Ну и как ты туда триггер запихиваешь?
Попробую так.
Задачка из топика.
База - полностью, т.е. в 5-ю форму, нормализованная.
Что ты будешь делать чтобы собрать исходную таблицу?
Будешь утверждать что не надо 5-ю форму?
Или попросишь несколько вьюшек слепить?
А инструмент для вьюшек у тебя есть?
А если вьюшек не хватит и процедура потребуется?
Упсс - опять уперлись в инструменt...
Знакомый в Уни, начал подкидывать задачки.
как бы ни казалась примитивной работа пешеходного светофора, но реализация не так проста. конечно специальные языки ее упрощают.
Алгоритм может быть таким:
-1- включить зелёный машинам, пешеходам красный
-2- если пешеход нажал кнопку, и машинам зелёный горел уже достаточно долго
- включить машинам желтый
- чуть подождать
- включить машинам красный
- чуть подождать
- включить пешеходам зелёный
- выдержать достаточно времени для хождения пешеходов
- включить пешеходам красный, а машинам желтый
- чуть подождать
- включить машинам зеленый
- перейти к -2-
........
R,Y,G - лампочки светофора машинам
R2,G2 - лампочки светофора пешеходам
Алгоритм может быть таким
-----
Не может.
В алгоритмах УПРАВЛЕНИЯ вообще не может быть никакой прописанной логики. Тем более логики, в которой принимаемое решение зависит от того какой кусок кода выполнялся на предыдущем шаге.
В таких алгоритмах выделяется то что называется "текущее состояние" и на его базе строится обычный цифровой автомат. В автомате, как положено, применяется противогоночное кодирование.
Только тогда это работает.
А не соблюдение этого правила ведет к куче проблем, часть из которых - с трупаками... например см. столкновение поездов в Риге после замены стандартной АБС на модернягу написанную местными студентами.
Даже в том что ты написал нет одного важного элемента - ты не проверяешь включенный сигнал на фактическую работоспособность. А лампочки, как общеизвестно, имеют свойство регулярно перегорать...
В алгоритмах УПРАВЛЕНИЯ вообще не может быть никакой прописанной логики. Тем более логики, в которой принимаемое решение зависит от того какой кусок кода выполнялся на предыдущем шаге. В таких алгоритмах выделяется то что называется "текущее состояние" и на его базе строится обычный цифровой автомат.так ведь текущее состояние автомата определяется как раз логикой предыдущего состояния.
Кстати на картинке изображен именно цифровой автомат (State Maschine). Точнее два.
А лампочки, как общеизвестно, имеют свойство регулярно перегорать...задача упрощена и не требует никак обрабатывать эту ситуацию.
на картинке изображен именно цифровой автомат
-----
Увы, но нет...
Просто потому что после выполнения очередного шага автомат должен перейти из состояния А в состояние Б и находится в положении которое было до начала перехода из А в Б, за исключением измененного "текущего состояния".
Функция перехода должна изменить (атомарная операция) текущее состояние.
Код автомата должен никак не зависеть от того из какого и в какое состояние автомат переключается. Вообще никак.
Как следствие - код автомата никак не должен зависеть от конфигурации перекрестка и выбранного режима работы светофоров - автомат будет один и тот же.
Следствие 2 - приличная реализация автомата должна включать обработку ошибок. Например - выход из строя памяти в которой хранится "текущее состояние" или код автомата...
не требует никак обрабатывать эту
ситуацию
-----
В Риге тоже не обрабатывали - два поезда столкнулись и появилась куча трупов...
П.С. Что данное решение не для осваивающих иф-елсе-тхен - Я вполне понимаю.
В Риге тоже не обрабатывали - два поезда столкнулись и появилась куча трупов...Рига не причем. Это пример простенькой задачки без учета сложностей реальности.
Что данное решение не для осваивающих иф-елсе-тхен - Я вполне понимаю.на то они и спец языки, чтобы изображать логику более наглядно в графическом виде.
росто потому что после выполнения очередного шага автомат должен перейти из состояния А в состояние Б и находится в положении которое было до начала перехода из А в Б, за исключением измененного "текущего состояния". Функция перехода должна изменить (атомарная операция) текущее состояние.всё это соблюдено в диаграмме выше.
Код автомата должен никак не зависеть от того из какого и в какое состояние автомат переключается.а это не понимаю. Ибо именно код автомата определяет из какого состояния и в какое и при каких условиях автомат переключается. Т.е. активация очередного состояния является следствием предыдущего и условия перехода.
Диаграмма выше вообще очень проста (ввиду упрощенной задачи), ибо нет ни одного состояния из которого было бы возможным перейти не в одно, а в одно из несколько возможных состояний.
конечно специальные языки ее упрощают
Для этого нужно знать эти специальные языки и упрощение тоже еще вопрос.
Но перед алгоритмом нужно хоть немного описать задачу.
Похоже у нас есть два светофора стоящих на пешеходном переходе: один для машин, другой для пешеходов. Имеется еще кнопка запроса перехода.
Два светофора должны работать в противофазе в стандартном режиме и в режиме запроса перехода. Еще нужно будет определить различные времена, как минимум время горения красного, зеленого, желтого цвета и задержку переключения машинного и пешеходного светофоров. Нужно еще определится с алгоритмом запроса пешехода на переход.
Для этого нужно знать эти специальные языки и упрощение тоже еще вопрос.конечно надо знать и выбрать (если есть выбор) тот из них, на котором программа будет выглядеть понятней и легче модифицироваться, если приспичит.
Этот что на картинке подобен стандартному SFC.
https://ftp.owen.ru/CoDeSys3/98_Books/plcopen_sfc_v10_ru.p...
Именно на таком и следует программировать, если задача является последовательностью (во времени) шагов.
На текстовом языке, а ля C# или стандартном ST (а также на графических стандартных FBD, LD) этот алгоритм будет выглядеть гораздо менее привлекательным.
Но перед алгоритмом нужно хоть немного описать задачу. Похоже у нас есть два светофора стоящих на пешеходном переходе: один для машин, другой для пешеходов. Имеется еще кнопка запроса перехода. Два светофора должны работать в противофазе в стандартном режиме и в режиме запроса перехода. Еще нужно будет определить различные времена, как минимум время горения красного, зеленого, желтого цвета и задержку переключения машинного и пешеходного светофоров. Нужно еще определится с алгоритмом запроса пешехода на переход.Всё именно так и есть. А времена там на картинке жестко забиты (от балды правда). Например, @T > 5000 означает время активности шага сверху более 5000 милисекунд.
Нужно еще определится с алгоритмом запроса пешехода на переход.
Пока машины ездят достаточно одного нажатия на кнопку, и сразу или через паузу (если зелёный машинам светил слишком мало) отреагировать на это нажатие. Очередное нажатие будет воспринято только когда пешеходам опять красный будет, а пока пешеходам зелёный, то нажатия кнопки - в игнор.
https://m.habr.com/ru/post/254885/
Если выходной сигнал цифрового автомата зависит лишь от текущего состояния, то такой автомат называется автоматом Мура
😁
подкидывать задачки.
Вот реальная задача управления светом в подвале школы (как то товарищ попросил запрограммировать с его слов)
- есть кнопка.
- начальное состояние - выключить свет (если включен).
- при нажатии кнопки включить свет.
- если кнопка нажата коротко, то свет сам потом выключается через некоторое время. (далее начальное состояние)
- если кнопка нажата больше секунды (но меньше 10ти), то свет сам не выключится, а выключится повторным нажатием кнопки. (далее начальное состояние)
- если кнопку нажать очень долго (более 10 секунд), то свет моргает один раз (т.е. тухнет на 1 секунду и опять включается) и устанавливается некий сигнал (зачем нужен не знаю).
- после этого короткие нажатия кнопки игнорируются, а при долгом нажатии (10секунд), свет моргает 5 раз и тухнет, а некий сигнал сбрасывается через некоторое время начиная с начала 5тикратного моргания. (далее начальное состояние).
...
Кроме того есть аварийный сигнал.
Если он пришел, свет включается, некий сигнал выключается, а вышеприведённый алгоритм отключается не зависимо от текущего его шага.
Когда аварийный сигнал уйдёт, то алгоритм стартует с начального состояния.
всё это соблюдено в диаграмме выше.
----
Увы-увы, но нету там этого.
Например, у тебя там НЕТ возможности переключить все светофоры перекрестка в "Мигающий Желтый".
А когда ты это попытаешься добавить - у тебя появится довольно неприятное усложнение логики.
Если допустить, что светофор дается произвольный - например один трех лампочный, другой - пяти, все снова усложнится.
А усложнения недолжно быть - функция автомата не поменялась - автомат должен управлять включением/выключением ламп светофора. И только.
Ибо именно код автомата определяет из какого состояния и в какое и при каких условиях автомат переключается.
-----
Это на самом деле - просто.
С - состояние
У - управляющее воздействие
Тогда автомат А определяется как
С = А(С,У).
Если У - пустое - нет кнопок или удаленного управления - будет С = А(С) или С = А(С,нулл)
А автомат переключается в любом случае - даже в том, когда С(до) тождественно равно С(после)
ввиду упрощенной задачи), ибо нет
-----
Ты просто частью отбросил, частью замаскировал места где должны быть поверки условий.
Но в сколь-нибудь реальном управлении так работать не будет. Нее - воткнуть - можно, но будут проблемы.
Грубо говоря - в реальной системе ты должен взять текущее С (например состояние ламп включено/выключено/перегорела плюс "режим работы") и текущее У (например, кнопки, таймер, ошибки) рассчитать новое С. На каждом шаге т.е. изменении состояния ламп - все пересчитываешь из лампы+ и все У... Дрючить "кодом автомата" какую-то одну лампу/кнопку/таймер - нельзя.
Тогда - будет работать.
Т.е. активация очередного состояния является следствием предыдущего и условия перехода.
-----
Тут ты упускаешь что после смены состояния (переключения ламп) автомат должен находится в позиции "готовность к очередному изменению состояния" и что это всегда одна и та же позиция.
если задача является последовательностью (во времени) шагов
-----
Именно по этому и будут проблемы - не должно быть никакой "последовательности" - из текущего состояния и управляющих воздействий должно быть вычислено новое состояние. После получения состояния все находится на исходной для нового пересчета.
Попробуй - тебе понравится.
не должно быть никакой "последовательности"без последовательности никак не обойтись, ибо активность шагов таки последовательно меняется.
Но для надёжности, (что значит признания программиста, что он не в состоянии полностью осознать чего пишет) можно код каждого шага оставить пустым (т.е. ничего не делать), но в конце кода программы жестко присвоить значения всем выходам на основании номера текущего шага. Тогда гарантируется строгая функциональная зависимость каждого выхода от текущего шага.
Это конечно надёжней, но менее эффективно, т.к. приходится каждый раз выполнять код присваивания может 100-ни выходам, даже когда ничего не менялось. А если выходы - стринги например, по килобайту длины, то тут уже явно могут быть заметны проблемы с производительностью.
ввиду упрощенной задачи), ибо нет ----- Ты просто частью отбросил, частью замаскировал...опиши, если интересно, все входы и выходы, состояния, условия переходов, а я удовольствием покажу какой будет программа на этом языке.
Вот реальная задача управления светом в подвале школы
Где вы всю эту фигню берете?
Даже понять не захотелось, что именно требуется.
Это не задачи для начинающих, потому как даже обычный светофор требует знание понятия "задержка".
Кроме того, не следует сразу с размещением задачи давать и какое либо готовое решение. Ну и также, не показав как решать предыдущую задачу, давать сразу следующую.
Где вы всю эту фигню берете?эта фигня реально работает в школе и именно такой затребована. Там много подобной фигни. Управление жалюзями, например, вытяжкой в кухне.
Это не задачи для начинающих, потому как даже обычный светофор требует знание понятия "задержка".когда начинающий освоит решать задачки которые никуда не годятся, и станет гуру в этом, он останется начинающим для реальных задач, применимых в управлении.
Я дал задачки для начинающих реальных задач. В которых кстати понятие "задержка" отсутствует принципиально. Ну или вернее она не значит "спать" как Sleep(), а значит "не время что-то делать дальше", т.е. поток никогда не блокируется.
Если знать разные языки тогда уже можно оценить на каком языке задача решается проще и понятнее.
Это скорее удел специализированных одиночек.
На работе обычно есть направление и есть один или несколько языков которые можно использовать.
Ну и проще и понятнее тоже не критерий. Допустим, мне проще и понятнее написать что то на С++.
Но если мне для эксель нужно что сделать или на веб страничке, что то выпендриться, то С++ мне ну никак тут не поможет.
Это что то типа как кашу размазывать по тарелке, вроде и много, а как копнешь то почти ничего.
когда начинающий освоит решать задачки которые никуда не годятся, и станет гуру в этом
Дело то не в задачах, а какую цель для обучения они преследуют.
Начинающему нужно вначале разобраться с основными конструкциями: ветвлением и циклом, когда это усвоится можно идти дальше.
для реальных задач, применимых в управлении
Это именно задачи для управления чего то, больше они ни на что и не годятся.
Ну или вернее она не значит "спать" как Sleep(),
Это уже всё ваша интерпретация. Я, как начинающий, не имею никакого понятия, каким образом мне можно какое то действие сделать на 3 секунды позже. Да и не нужно мне это сейчас знать
А уж что такое потоки и что их еще и можно блокировать я вообще и
близко не слышал
Это уже всё ваша интерпретация. Я, как начинающий, не имею никакого понятия, каким образом мне можно какое то действие сделать на 3 секунды позже. Да и не нужно мне это сейчас знать смущ А уж что такое потоки и что их еще и можно блокировать я вообще и близко не слышалЗадачка вначале темы была именно управления температурой кажется. Вот и я привел задачки по управлению.
Чтобы решать управленческие задачки (которые работают обычно в контроллерах с входными и выходными датчиками) нужно другое мышление, чем если к примеру алгоритмы сортировки писать, или чего нибудь для десктопа.
Управленческая задача
- не имеет права ждать зависнув в Sleep, Эвенте, критической секции (в этих языках этих возможностей даже и нету)
- по нормальному, не имеет права делать даже долгий вычислительный цикл
- задача периодически с заданным интервалом получает управление и она должна сделать минимум действий и сразу вернуть управление.
- никаких потоков тоже нет
- ничего вызываться из библиотек, что может подвесить программу нельзя.
- например Socket можно пользовать только в NonBlocked (если не ошибаюсь в названии) режиме, так другой режим зависает в ожидании данных.
......
Лучше это учитывать сразу, ибо придется переучиваться, если надо будет реальную задачку написать.
без последовательности никак не обойтись,
-----
Обойтись.
Та последовательность, об которой ты говоришь, не имеет никакого отношения к управляющему автомату - она лишь следствие его работы.
ибо активность шагов таки последовательно меняется.
-----
Это тебе кажется. Реализуешь автомат в точном соответствии с теорией - в автомате ее не будет.
могут быть заметны проблемы
-----
Это вопрос реализации переходной функции - к реализации самого автомата имеет почти никакое отношение.
Тогда гарантируется строгая функциональная зависимость каждого выхода от текущего шага.
-----
Т.е. ты сам понимаешь что создаешь большой геморой, который в сколь-нибудь сложной конфигурации - более одного светофора, "желтый" светофор, "зеленая волна" - у тебя издержки управления вырастут настолько, что будет нужен быстрый процессор и куча прогеров...
если интересно
-----
Лениво.
я удовольствием покажу какой будет программа
-----
А смысл?
Выше описывал для Кодера переработку парсера для Сишных выражений - там именно программа которую ты можешь показать была заменена автоматом - 60Кб кода => 15 строк + таблица на 60 строк. И эти 15 строк никак не будут меняться какой бы набор унарных и бинарных операций для языка не придумали.
Кстати, автомат для светофора, включающий любые возможные схемы переключения, будет примерно того же объема.
Лучше это учитывать сразу
Это вообще не нужно даже и знать поначалу, а тем более учитывать. Тут бы понять, что такое алгоритм и как его едятъ
Вот и я привел задачки по управлению.
Разное бывает управление....
Всё что требовалось в первой задаче, это додуматься как из одного ветвления сделать два.
А в светофоре нужно не только поочередно открывать движении пешеходам и машинам, но и еще в определенном порядке переключать 6 лампочек. И еще как то длительность учитывать. И это не принимая во внимание кнопку "хочу перейти улицу".
Пример: Управление жалюзями.
Входы:
- кнопка вверх
- кнопка вниз
- сигнал непогоды
Выходы:
- мотор вверх
- мотор вниз
- датчик крайне верхнего положения
- датчик крайне нижнего положения
Требование:
- при нажатии одной из кнопок включить соответствующий мотор
- мотор выключить при отжатии кнопки, если она была нажата менее 3х секунд, иначе отжатие - в игнор
- мотор выключить при срабатывании датчика крайнего положения или нажатия любой из кнопок
- перед включением мотора проверить датчик (может включать и не надо)
- при срабатывании датчика непогоды жалюзи поднять вверх игнорируя кнопки
.е. ты сам понимаешь что создаешь большой геморой, который в сколь-нибудь сложной конфигурации - более одного светофора, "желтый" светофор, "зеленая волна" - у тебя издержки управления вырастут настолько, что будет нужен быстрый процессор и куча прогеров...наоборот, если писать на SFC (или том что на картинках) любой из шагов делает минимум действий и не грузит процессор.
И как раз чем сложнее задача, тем оправданее использование SFC, а вместо цифрового автомата.
на каком языке задача решается проще и понятнее
Вообще то вместо каких то непонятных квадратиков со стрелочками, мне гораздо понятнее следующее
ЦИКЛ ДО бесконечности Разрешить движение машин на х секунд Разрешить движение пешеходов на y секунд КОНЕЦ ЦИКЛА
И как раз чем сложнее задача, тем оправданнее использование SFC
Это что то типа такого: Чем меньше знаешь в программировании тем оправданнее использовать Visual Basic.
Если мне надо будет программить какое то железо, то я лучше возьму С. Уж хотя бы точно знаешь что получишь
Вообще то вместо каких то непонятных квадратиков со стрелочками, мне гораздо понятнее следующее ЦИКЛ ДО бесконечности Разрешить движение машин на х секунд Разрешить движение пешеходов на y секунд КОНЕЦ ЦИКЛА
пусть это понятней, но это неприемлимо.
Такого в задаче управления писать нельзя.
Если мне надо будет программить какое то железо, то я лучше возьму С. Уж хотя бы точно знаешь что получишьню, ню...
те принципы что я изложил, и тот язык что на картинке привел, позволяют работать сотням программ управления сразу в одном контроллере. А если писать на С, ну одну, две осилишь, а дальше - кирдык.
И как раз чем сложнее задача, тем оправданее использование SFC, а вместо цифрового автомата.
-----
Это можно обсуждать после изучения того, что продуцирует СФЦ.
Смотреть - не буду - мне проще сделать автомат, который гарантирует работоспособность системы управления.
Остальное - надо смотреть.
позволяют работать сотням программ управления сразу в одном контроллере
Вообще то нам обычно нужна была одна программа, дай бы бог ёё там разместить
Большое преимущество данного языка, не нужно объяснять, что такое "спагетти код" - всё сразу и так видно
Если мне надо будет программить какое то железо, то я лучше возьму С.я когда то, еще будучи студентом, весьма хорошо освоил язык Ассемблер, и писал игрушки для самодельных компьютеров Специалист и Синклер (ZXSpectrum). На кафедре тоже для Синклера написал управление сигнализацией, в паре с коллегой который оборудование разработал.
Так вот тогда мне казалось что я могу всё, и язык С и в руки брать не хотел даже для ознакомления.
Но позже ебстественно понял что С может быть поудобнее, а потом и С++ оценил.
ольшое преимущество данного языка, не нужно объяснять, что такое "спагетти код" - всё сразу и так виднопредлагаю написать на С управление светоформ или светом. И тогда мы сравним какой из кодов званию спагети более соответствует.
Такого в задаче управления писать нельзя. Хорошо хоть мои знакомые "железнячники" этого не знаютне знают потому как узкоспециализированные задачи пишут.
Если был они управление роботом к примеру что машины клепает написать попробовали, и так чтобы алгоритм мобильно менять можно было, то оценили бы специальные языки программирования. Ибо они для этого заточены.
вот к примеру в приаттаченом файле во что генерируется упраление светофором если генерировать в СиШарп
----
странно текстовый файл приаттачить не удаётся, потому привожу его содержимое.
.......
// input
public bool Button; // кнопка пешехода
// output
public bool R, Y, G; //светофор для машин
public bool R2, G2; // светофор для пешеходов
//local
public bool BB;
public int Branch1 = 1;
public int Branch1_Prev;
public int Branch1_T;
public bool Branch1_Pulse = true;
public int Branch2 = 1;
............................
if (Branch1_Pulse)
{
_ _ Branch1_Prev = Branch1;
_ _ Branch1_T = Environment.TickCount;
}
switch (Branch1)
{
_ _ case 1: /*S1*/
_ _ {
_ _ _ _ /*машины едут, пешеходы стоят*/
_ _ _ _ R = Y =_ G2 = false;
_ _ _ _ G = R2 = true;
_ _ _ _ /*пешеход нажал кнопку*/
_ _ _ _ if (BB)
_ _ _ _ {
_ _ _ _ _ _ /*прошло ли достатоно времени для потока машин*/
_ _ _ _ _ _ if ((Environment.TickCount - Branch1_T) > 5000)
_ _ _ _ _ _ {
_ _ _ _ _ _ _ _ Branch1 = 2;
_ _ _ _ _ _ }
_ _ _ _ }
_ _ }
_ _ break;
_ _ case 2:
_ _ {
_ _ _ _ /*машинам желтый*/
_ _ _ _ Y = true; G = false;
_ _ _ _ /*выдержать желтый*/
_ _ _ _ if ((Environment.TickCount - Branch1_T) > 2000)
_ _ _ _ {
_ _ _ _ _ _ Branch1 = 3;
_ _ _ _ }
_ _ }
_ _ break;
_ _ case 3:
_ _ {
_ _ _ _ /*машины стоят*/
_ _ _ _ Y = false; R = true;
_ _ _ _ /*люди идут*/
_ _ _ _ R2 = false; G2 = true;
_ _ _ _ /*пусть люди походят*/
_ _ _ _ if ((Environment.TickCount - Branch1_T) > 5000)
_ _ _ _ {
_ _ _ _ _ _ Branch1 = 4;
_ _ _ _ }
_ _ }
_ _ break;
_ _ case 4:
_ _ {
_ _ _ _ /*люди стоят*/
_ _ _ _ R2 = true; G2 = false;
_ _ _ _ /*игнорировать нажатия кнопки пока люди ходили*/
_ _ _ _ BB = false;
_ _ _ _ /*машинам желтый*/
_ _ _ _ Y = true; R = false;
_ _ _ _ /*коротенькая пауза*/
_ _ _ _ if ((Environment.TickCount - Branch1_T) > 1000)
_ _ _ _ {
_ _ _ _ _ _ Branch1 = 1; /*S1*/
_ _ _ _ }
_ _ }
_ _ break;
}
Branch1_Pulse = Branch1 != Branch1_Prev;
switch (Branch2)
{
_ _ case 1: /*S1*/
_ _ {
_ _ _ _ /*пешеход нажал кнопку*/
_ _ _ _ if (Button )
_ _ _ _ {
_ _ _ _ _ _ Branch2 = 2;
_ _ _ _ }
_ _ }
_ _ break;
_ _ case 2:
_ _ {
_ _ _ _ /*пешеход отжал кнопку*/
_ _ _ _ if (!(Button ))
_ _ _ _ {
_ _ _ _ _ _ /*запомнить это нажатие*/
_ _ _ _ _ _ BB = true;
_ _ _ _ _ _ Branch2 = 1; /*S1*/
_ _ _ _ }
_ _ }
_ _ break;
}
Значит код потрясающий говорите, до спагетти как до неба? И сотня светофоров получается нажатием одной кнопы?я говорю то что сказал уже, а всякий тупой стёб без малейшей аргументации мне не интерестен.
Заявляется (исходно) что описывается автомат, а решение предлагается в виде говнокода... Синтезировали бы обычный автомат - все было бы приемлемо.ну ясно что всё что не автомат, то говнокод. Я бы глянул на этот говноавтомат на досуге, да боюсь такое и показать стыдно.
а всякий тупой стёб без малейшей аргументации мне не интересен.
Ожидалось, что аргументы додумаются
Тогда конкретно, самый минимум:
- Как Вы относитесь к глобальный переменным?
- Как Вы относитесь к case 1,2,3,х ? Насколько "понимабельно"
- Как мне сделать два/три/х светофоров исключительно через кодогенератор?
- Это ничего, что код не рабочий? Сколько интересно понадобится времени "новому программисту", что бы это понять чисто смотря в код?
Как Вы относитесь к глобальный переменным? Как Вы относитесь к case 1,2,3,х ? Насколько "понимабельно" Как мне сделать два/три/х светофоров исключительно через кодогенератор? Это ничего, что код не рабочий? Сколько интересно понадобится времени "новому программисту", что бы это понять чисто смотря в код?
ответьте сперва на мои вопросы, а потом я отвечу на Ваши если еще понадобится.
- Вы считаете что нужно понимать именно результат компиляции, а не исходный код?
- если да, то это относится только к сгенерированному в C# для исполнения в симуляторе, или же и к сгенерированному в машинный код какого либо конкретного процессора, для выполнения на реальном контроллере?
- вы часто оцениваете код глядя на его шестнадцатeричный дамп ?
- вы знаете чем в памяти контроллера отличаются ячейки где хранятся переменные, объявленные в исходниках как публичные от ячеек с объявленными как приватные , и какие из них лучше?
жно. только обернуть в класс. и дёргать его.но чтобы ниже приведенное получить надо поработать
Прости конечно, но это самое ужасное режение из всех возможных.
Его минусы:
1) оно не масштабируемое.
2) оно сложно тестируемо.
Предлагаю подойти к решению задачи с другой стороны:
1) надо признать, что мы тут говорим о состояниях, а не о каких-то алгоритмах. Состояний у светофора не так много:
+----+----------------+---------------+----------------+------------------+------------------+ | Nr | машины Красный | машины Желтый | машины Зеленый | пешеходы Красный | пешеходы Зеленый | +----+----------------+---------------+----------------+------------------+------------------+ | 1 | 1 | 0 | 0 | 0 | 1 | | 2 | 1 | 0 | 0 | 1 | 0 | | 3 | 0 | 1 | 0 | 1 | 0 | | 4 | 0 | 0 | 1 | 1 | 0 | +----+----------------+---------------+----------------+------------------+------------------+
Если я какое-то состояние упустил, то его можно добавить :)
Итак, делаем интерфейс описывающий состояния светофора:
public enum CarLight { Red, Yellow, Green } public enum PedestrianLight { Red, Green } public interface ITrafficLight { CarLight CarLight { get; } PedestrianLight PedestrianLight { get; } } public class TrafficLight : ITrafficLight { public CarLight CarLight { get; set: } public PedestrianLight PedestrianLight { get; set; } }
2) Вспоминаем, что у нас есть кнопка и описываем ее интерфейсом:
public interface ITrafficLightButton { bool IsPressed { get; } void Reset (); }
3) Теперь можем описать состояния:
public interface ITrafficLightState { ITrafficLight TrafficLight { get; } void Wait (); } public class TrafficLightState : ITrafficLightState { private int _delay; public ITrafficLight TrafficLight { get; private set; } public <span class="redactor-invisible-space"></span>TrafficLightState (ITrafficLight trafficLight, int delay) { // тут проверить параметры TrafficLight = trafficLight; _delay = delay; } public virtual void Wait () { Thread.Sleep (_delay); } } public class TrafficLightWaitForPedestrianState : TrafficLightState { private ITrafficLightButton _button; public TrafficLightWaitForPedestrian (ITrafficLightButton button, ITrafficLight trafficLight, int delay) : base (trafficLight, delay) { if (button == null) throw new ArgumentNullException ("button must be initialized");<span class="redactor-invisible-space"></span> _button = button; } public override void Wait () { while (_button.IsPressed == false) Thread.Sleep (1000); base.Wait (); } } public class TrafficLightResetButtonState : TrafficLightState { private ITrafficLightButton _button; public TrafficLightWaitForPedestrian (ITrafficLightButton button, ITrafficLight trafficLight, int delay) : base (trafficLight, delay) { if (button == null) throw new ArgumentNullException ("button must be initialized");<span class="redactor-invisible-space"></span> _button = button; } public override void Wait () { _button.Reset (); base.Wait (); } }
4) Теперь нам нужен зацикленный контейнер:
public class CircularList<T> : IEnumerable<T>, IEnumerator<T> { private List<T> _list = new List<T>(); ... public void Add (T item) { _list.Add(item); } ... #region имплементация IEnumerable<T> ... #endregion #region имплементация IEnumerator<T> ... #endregion }
5) Ну и теперь самое интересное - код светофора:
В конструкторе светофора инициализуруем состояния:
ITrafficLightButton button = new TrafficLightButton(); CircularList<ITrafficLightState> states = new CircularList<ITrafficLightState>(); states.Add (new TrafficLightWaitForPedestrianState(button, new TrafficLight() { CarLight = CarLight.Green, PedestrianLight = PedestrianLight.Red }, 5000 ); states.Add (new TrafficLightState(new TrafficLight() { CarLight = CarLight.Yellow, PedestrianLight = PedestrianLight.Red }, 3000 ); states.Add (new TrafficLightState(new TrafficLight() { CarLight = CarLight.Red, PedestrianLight = PedestrianLight.Red }, 2000 ); states.Add (new TrafficLightResetButtonState(button, new TrafficLight() { CarLight = CarLight.Red, PedestrianLight = PedestrianLight.Green}, 15000 ); states.Add (new TrafficLightState(new TrafficLight() { CarLight = CarLight.Red, PedestrianLight = PedestrianLight.Red }, 1000 );
А вот и так этот светофор работает:
foreach (ITrafficLightState trafficLightState in states) { TurnTrafficLights(trafficLightState.TrafficLight); trafficLightState.Wait (); }
Вот собственно говоря и все :)
ответьте сперва на мои вопросы, а потом я отвечу на Ваши
Вообще то даже детишки дома этого себе не позволяют.
Значит придётся опускать планку до визуальных программистов, которым даже сложно найти ошибку в своей программе
нужно понимать именно результат компиляции, а не исходный код
В связи с отсутствием понимания исходного кода приходится довольствоваться тем что есть.
если да
тут нужен nullable boolean, но его у вас скорее всего нет.
Вообще то, насколько я знаю визуальные языки программирования не занимаются компилированием написанного. Это обычные кодогенераторы, которые могут вызывать компилятор соответствующего языка.
вы часто оцениваете код глядя на его шестнадцатeричный дамп
Исходя из того что это кодогенератор можно оценить модель лежащую в его основе.
вы знаете чем в памяти контроллера отличаются ячейки
Как то совершенно не волнует где будет исполнятся моя прога, как и то что там насували эти затейники в Сименс или Куку.
Интересен прежде всего код. А всё что вижу - это есть одна баальшая функция.
соответственно хотелось бы иметь что попроще.
А проще некуда. Да, в ответе многа букаффф. Но есть 2 вещи.
1. это состояние. Мы не меняем желтый на красный. Мы меняем состояние на состояние. Можно в тестовом примере выкинуть пешеходный светофор. Можно выкинуть кнопку. Но принцип останется
2. Это описание реальных обьектов классами. Что бы выкинуть пешеходный светофор, не нужно вылавливать его из огромного метода. Достаточно удалить или замочить класс. И само описание состояния соответствует реальным обьектам - в каждом классе инкапсулировано ровно то, что нужно.
Кроме того есть интересные вещи типа масштабируемости. Можно добавлять или удалять обьекты. Имхо на таком коде нужно учить новичков - что бы привыкали думать обьектами.
P.S.
респект Программисту. Я не пишу на С-шарп, но код абсолютно понятен и легко читаем.
хотелось бы иметь что попроще.
Что может быть проще, чем один бесконечный цикл? :) Ни ветвлений, ни каких-то алгоритмов.
Из "сложного" тут только циклический контейнер. Но, если человек не знает как работает foreach, то его можно заменить на простой бесконечный цикл:
List<ITrafficLightState> _list = new List<ITrafficLightState>(); .... int index = 0; while(true) { ITrafficLightState state = _list[index]; TurnTrafficLights(trafficLightState.TrafficLight); trafficLightState.Wait (); index = index + 1; index = index % _list.Count; }
Местное глюкало вчера сожрало ответ, а сегодня откуда-то нашло.
- Вы находите приведённый в файле код хорошим или плохим?
-----
Ничего если Я отвечу?
В файле лежит генерированный говнокод. Он не может быть хорошим или плохим в том плане в каком программисты считают код хорошим или плохим. Оценивать его можно только с точки зрения реализации автомата описанного СФЦ. С этой точки зрения это именно говнокод...
Вы считаете что нужно понимать именно результат компиляции, а не исходный код?
-----
Понимать нужно весь процесс и в деталях.
Т.е. надо понимать язык описания, синтезируемый автомат и иметь возможность модифицировать как описание, так и продуцированный код.
или же и к сгенерированному в машинный код
-----
Часто крайне желательно понимать не только машинный код, но и то как его выполняет процессор.
Данное понимание позволит избежать хотя бы синтеза гигабайтов кода подобного приведенному.
Местное глюкало вчера сожрало ответ, а сегодня откуда-то нашло.
Если ты не нажимаешь кнопку "отправить", то пост не публикуется. Но если ты попробуешь в этой же ветке что нибудь написать, то неотправленный пост будет представлен для редактирования. По крайней мере у меня так.
-----
Ты начал - правильно.
Даже привел таблицу состояний.
Что требовалось сделать - построить... автомат, который берет одно состояние как текущее и возвращает каким должно быть следующее. Можно по состоянию ламп, можно - по номерам состояний - это не важно, лишь бы различались. Существенно - без привязки к самому светофору.
Светофор - не определяет каким оно должно быть новое состояние - он только отображает установленное.
Т.е. у тебя будет один автомат и любое количество любых светофоров - код автомата останется без изменений.
Murr хочет сказать, что интерфейс ITrafficLightState должен быть таким:
public interface ITrafficLightState { ITrafficLight TrafficLight { get; } void Wait (); ITrafficLightState Next { get; } }
и тогда работа светофора будет такой:
ITrafficLightState trafficLightState = startState; do { TurnTrafficLights(trafficLightState.TrafficLight); trafficLightState.Wait (); trafficLightState = trafficLightState.Next; } while (trafficLightState != null);
Но в данном случае, я не вижу необходимости в таком подходе.
ITraficLight traficLight = TTraficLightFactory.Crete("MyTraficLight"); TButton button = traficLight.Button; TTraficLightController controller = new TTraficLightController("MyTraficLight"); ITrafficLightState state = controller.Init(); foreach (;true;) { trafficLight.Set(state); state = controller.Next(state,{button,timmer}); // S = F(S,U) // Wait (); // не нужно - state будет управлять через отсутствие изменений }
Напишешь? ;)
-----
Опять - лениво.
Бо, всем понятно что там будет - табличка: текущее состояние, управляющие сигналы, новое состояние.
Ищется совпадение первых двух и возвращается третье. Все по теории.
Табличку - проверяем отдельным инструментом (не руками/головой) на отсутствие потерянных и подвисших строк и дополняем автомат если нужно.
controller.Next
Теоретически да. Внешний контроллер.
Но в данном конкретном УЧЕБНОМ случае это неважно, в роле контроллера выступает обычный цикл. Главное - состояния переключаются и переключение вынесено из светофора.imho
P.S. Ааа, Программист уже написал....
Бо, всем понятно что там будет - табличка: текущее состояние, управляющие сигналы, новое состояние.
Ищется совпадение первых двух и возвращается третье. Все по теории.
Ага, вот только что-то мне подсказывает, что у тебя там будет говно код в стиле
switch (blah-blah) { case 1: break; case 2: break;
}
роль контроллера исполняет зацикленный лист
-----
У тебя "зацикленный лист" завязан на конкретную реализацию светофора и последовательность сигналов.
Изменится светофор - надо переделывать КОД, а машина состояний в контроллере никак не завязана на светофоры.
И не важно какой конфигурации перекресток - Я поленился переименовать ТТрафикЛигхт в ТРоадКросс... ну да, лентяй, каюсь...
Ну следующее состояние должно определяться через контроллер (у меня в примере это зацикленные лист), либо состояние само должно определить следующее состояние (это особенно полезно, если из текущего состояния можно перейти в одно из нескольких состояний, т.е. если есть ветвления)
что у тебя там будет говно код в стиле
-----
Нее, Я это привык делать трехколоночной табличкой.
Ну или двухколоночной если управляющих сигналов нет...
Верификацию же надо делать - 100 элементов во входящем состоянии, 20-30 управляющих, 100 в выходящем состоянии и от 20 до 5000 строк - мне его руками проверять ой как лениво...
А кейсовый говнокод иногда в мок могу сунуть - там без валидации сойдет...
Прости конечно, но это самое ужасное режение из всех возможных.прощаю конечно, ведь ты не учавствовал в беседе, поэтому не должен понимать о чем шла речь.
А вот с АлехНек и Мурр у меня была беседа в стиле Гладышева с Иваном Чонкиным, когда он объяснял ему почему у коня пальцев нет.
- Вот ты вчерась насчет лошади спрашивал.
- Насчет какой лошади? - не понял Иван.
- Ну вообще, почему, мол, она человеком не стала.
- А-а, - Иван вспомнил, что в самом деле вчера был какой-то такой разговор.
- Так вот, - с гордостью сообщил Гладышев. - Я понял, почему лошадь не становится человеком. Она не становится человеком, потому что у ней пальцев нет.
- Эка, удивил, - сказал Чонкин. - Это я с малых лет знаю, что у лошади нет пальцев.
- Да я тебе не о том. Я говорю не то, что у ней нет пальцев, а то, что она не становится человеком, потому что у нее нет пальцев.
- А я тебе говорю - это всем известно, что у лошади нет пальцев.
Тут они заспорили, как часто люди спорят между собой, доказывая один одно, а другой другое,...
Предлагаю подойти к решению задачи с другой стороны:хорошее решение, да только не подходящее для стандартных систем программирования контроллеров.
Ибо в этих языках:
- нету Sleep (поэтому надо следовать совету Мурр, и вынести Next из класса)
- нету интерфейсов
- класс имеет только одну функцию у которой есть доступ к входным, выходным и локальным данным класса. В локальных данных могут быть инстанциированны другие классы, единственную функцию которых можно вызвать, предварительно записав необходимое в их входные данные, и считав выходные после вызова их единственной функции.
- альтернатива CASEу только IF-ELSE. Никаких Action<>, которые можно было бы засунуть в таблицу, нету.
- рекурсии невозможны
Состояний у светофора не так много:таблица состояний это конечно хорошо.
Еще лучше таблица переходов (что предлагал Мурр), где для каждого состояния указаны условия переходов в другие состояния.
А еще лучше таблица переходов изображенная в виде графа.
А это ни что иное, как язык SFC из упомянутого стандарта.
Там сразу рисуешь такой граф.
...........
Единственный язык из стандарта, который по структуре подобен СиШарпу, это ST. И если соблюдать ограничения, то написанную программу на СиШарпе можно, слегка подправляя текст, преобразовать в ST и наоборот.
Что может быть проще, чем один бесконечный цикл?
У нас получается два варианта:
- Задача не для начинающих.
- Задача для начинающих. В таком случае должны быть использованы только те элементы которые им известны. Классы и интерфейсы к этому не относятся, к сожалению.
Кстати, после тестирования выявлено, что приведенный код абсолютно нерабочий. А после возможного исправления, работает не так, как ожидалось.
Pedestrian Red, Auto Green, delay 5s Pedestrian Red, Auto Yellow, delay 3s Pedestrian Red, Auto Red, delay 2s Pedestrian Green, Auto Red, delay 15s Pedestrian Red, Auto Red, delay 1s Pedestrian Red, Auto Green, delay 5s Pedestrian Red, Auto Yellow, delay 3.015s Pedestrian Red, Auto Red, delay 2s Pedestrian Green, Auto Red, delay 15s ...
Также очень бы хотелось увидеть реализацию класса TrafficLightButton для консольной проги под виндой, без каких либо извращений.
Для теста было использовано просто без нажатия кнопки.
internal class TrafficLightButton : ITrafficLightButton { private bool _isPressed = false; public bool IsPressed { get { return _isPressed; } } public void Reset() { } }
А кейсовый говнокод иногда

поддержку совместимости с существующими программами конечно надо оставить, но с обязательным предупреждением, без возможности его отключения: "говнокод".
Кто за?
Кстати, после тестирования выявлено, что приведенный код абсолютно нерабочий. А после возможного исправления, работает не так, как ожидалосьэто только теоретически таблиц достаточно.
Если задача попадётся чуть сложнее, то программист, который плевался ранее глядя на графы, сам начнёт рисовать их на бумаге и потом списывать результат в таблицы.
И если это ему часто придется делать, то и брезгливость к графам как рукой снимет.
который плевался ранее глядя на графы, сам начнёт рисовать их на бумаге
Многое зависит от решаемых задач. Тот же робот просто вынужден переходить из одного состояния в другое.
И когда программируешь исключительно роботов, начинаешь и мыслить по другому и инструменты нужны другие.
А когда, просто одна задачка попадется ее можно решить по разному. И рисунки могут вообще не понадобится.
проблема не в операторе, а в его использовании. Это как типа нож. Можно и так и так использовать.это верно, как и то, что Clean Code Development - как пиво: вещь хорошая, но можно и заболеть, а может и мозги отключить вообще, так, что кроме него ни о чем и думать не сможешь.

У нас получается два варианта
-----
У нас получается:
- одна учебная задача
- множество, в зависимости от квалификации прогера, решений
Классы и интерфейсы к этому не относятся
-----
Ну так определяйся с тем что они знают и что могут/должны пользовать.
А то - начали со средины - непонятно знают ли они переменные, выражения, операторы и т.п...
Классы и интерфейсы к этому не относятся, к сожалению.
Неверно. Этим нужно заниматься с самого начала. На обьектно-ориентированных языках нужно сразу писать обьектно-ориентировано иначе человек просто не станет переучиваться, привыкнув думать отдельными методами.
но можно и заболеть
Обычно заболевают те у кого иммунитет слабый
ССД еще никому не мешал, но в программировании роботов действительно абсолютно бесполезная вещь.
Насколько помню и у Сименса и у Кука свои собственные системы для программирования, с другими просто не сталкивался, но подозреваю что тоже самое.
У нас получается:- одна учебная задача
Это если смотреть абстрактно, а свете топика вроде однозначно - задачи для начинающих которые с программированием раньше не сталкивались.
Конечно, ничто не мешает нам поиграться и предложить самые разные решения - тоже интересно.
Ну так определяйся с тем что они знают
А ты что забыл как сам на 4-х лапах ходил и что знал при этом
Судя по тестовому объекту - знаний практически нет
Этим нужно заниматься с самого начала.
Я вообще то не сторонник бросания людей сразу в море что бы научить их плавать. Кто выплывет - молодец, а кто не выплывет тот нам и даром не нужен.
Похоже у моего знакомого сторонники данной теории.
После первой задачи, сразу контрольная на дизайн паттерны, а потом что то с SOLID будет
Этим нужно заниматься с самого начала.
-----
Эээ... это в тебе говорит засилье буржуазной методологии.
Я, кстати, встречал подготовленных по этой методике - без всяких проблем выстраивают охрененные иерархии интерфейсов и абстрактных классов. А дальше начинается проблема - уложить алгоритм в операторы никак не получается...
Правда в том, что надо поймать момент когда операторы уже освоены и алгоритм реализуется без особых проблем и тогда вводить классы, затем - виртуальные функции, следом - абстрактные классы и наконец - интерфейсы. Причем именно в таком порядке.
привыкнув думать отдельными методами
-----
Это как раз работа преподавателя - оценивать достигнутое и не позволять застаиваться в нем.
человек просто не станет переучиваться
-----
Опять 25...
ВУЗ на то и ВУЗ чтобы научить эффективно (само)обучаться.
Если этого нет - называй его ПТУ или ТЕХНИКУМ.
а свете топика вроде однозначно - задачи для начинающих которые с программированием раньше не сталкивались
-----
Для них не существует возможности получить хоть какое-нибудь решение - требуется базис - переменные, выражения, операторы-выражения, оператор-иф. Без этого - никак.
Найди какую-нибудь советскую книжку в названии которой есть словосочетание "дидактические материалы" и ознакомься в плане - исходные требования к обучаемому, тема и методика обучения, ожидаемый результат. Оно там дается на КАЖДОЕ занятие/тему. Это- минимум. Если поковыряешь кого-нибудь из закончивших пед-ВУЗ - они тебе еще накидают методик оценки/мотивации/стимулирования и прочей их премудрости...
задачи для начинающих которые с программированием раньше не сталкивались.
Есть несколько способов учить разговаривать на иностранном языке.
Один - заучить слова, потом заставить говорить как нибудь, потом пытаться корректировать построение предложений. Это классика, так учат взрослых эммигрантов и в итоге получается "моя твоя не понимай". Но работает, эти люди могут как то комунницировать.
И есть способ заучивания готовых конструкций. Разговорных паттернов. Так учат детей.
Поэтому ИМХО при обучении програмированию на обьектно-ориентированных языках сразу необходимо использовать и застaвлять использовать все ООП-конструкции. Многие будут потом использоваться интуитивно.
Промежуточный код тоже можно представить в удобоваримом виде. Ну чутка подучить теорию и сделать в соответствии с нею. Там не сложно, но получится много более понятно... для понимающих тер.базис.как именно удобоварительнее? где глянуть?
............
хотя возможно это и не понадобится. Приведенная генерация в СиШарп сделана только для симуляции, чтоб можно было отладить алогоритм без контоллера прямо на десктопе. А в контроллере зачастую и дотнэта нету.
как именно удобоварительнее?
-----
Так же как со светофором - контроллер - отдельно, функционалистика - отдельно.
Функционалистика, кстати, сильно упростится.
На одной из предыдущих работ шеф требовал... сначала от китаянки - сделай... и она лепила как могла - вместо автомата - код с флажками... потом - от меня - поправь/переделай... но пока не переписал как надо - починить было невозможно... а когда переписал - все пошло легко и быстро... но само переписывание заняло кучу времени...
Так что делать надо правильно - не "помня, что есть теория", а в соответствии с теорией - получится и просто, и красиво...
И есть способ заучивания готовых конструкций
Ну попугая тоже можно научить разговорной речи данным способом.
И пока, как я вижу на примере студента, получается именно так. Никакого понимания нет и в помине, да и не может быть.
Я не представляю, как можно начинающему понять где есть что и зачем.
тебе еще накидают методик оценки/мотивации/стимулирования
Зачем? Этот аспект мне интересен меньше всего. А уж на форуме почти бессмыслен.
Меня больше интересует, как можно получить решение понятное начинающим, которое не будет "страшным".
Для светофора с кнопочкой такого пока не нахожу Без кнопочки еще как то можно.
Но опять таки, размещать всё в одном классе совершенно не хочется, так что хотя бы один простой класс добавить нужно.
В этом случае всё управление лампочками будет там. Это позволит убрать хотя бы ошибки переключения, когда горят красный и зелёный одновременно. И уж точно гарантировать что при включенном зеленом для авто не будет зеленого для пешеходов.
В этом случае приходим к довольно простой главной функции
private static void Main(string[] args) { CombinedTrafficLight trafficLight = new CombinedTrafficLight(); InitTraceState(); while (true) { trafficLight.DisableAutoTraffic(); trafficLight.EnablePedestrianTraffic(); Delay(RedLightTimeMs); TraceState(trafficLight); trafficLight.EnableLightSwitch(); trafficLight.DisablePedestrianTraffic(); Delay(YellowLightTimeMs); TraceState(trafficLight); trafficLight.EnableAutoTraffic(); Delay(GreenLightTimeMs); TraceState(trafficLight); trafficLight.EnableLightSwitch(); Delay(YellowLightTimeMs); TraceState(trafficLight); } }
результат получается таким
+------+-----+-----+ |Pdestr|Auto |Delay| | R G |R Y G| [s] | |------+-----+-----| | * |* |3.094| | * | * |1.015| | * | *|4.000| | * | * |1.016| | * |* |3.000| | * | * |1.016| | * | *|4.015| | * | * |1.016| | * |* |3.000|
Так же как со светофором - контроллер - отдельно, функционалистика - отдельно.
ну вот ниже я переделал на автомат. Все лампочки светофора записываются каждый раз на основании текущего шага ветки В1.
Но мне лично больше нравится предыдущая версия (где машина состояний, но не автомат).
Зачем? Этот аспект мне интересен меньше всего.
-----
Затем, чтобы понимать что надо дать, как надо дать и что надо требовать чтобы удостоверится что до обучаемого "дошло" (цель обучения достигнута)...
А пока не "дошло" - следующий шаг бессмыслен - максимум - заучит наизусть что есть что и что забудет на следующий день, а навыка "сложить из того что есть" - не появится.
В случае задачи со светофором, по не озвученным тобою требованиям, требовалось сформулировать ДВА "если" или обеспечить ТРИ ветви выполнения кода.
Данное решение удовлетворит тебя (хотя мне лично непонятно почему), но не будет решением задачи по светофору.
как можно получить решение понятное начинающим
-----
Мне вообще не понятно как можно говорить об каком-то "понятном решении" не зная базиса который есть у того кто должен понять.
По условию у тебя начинающий, без предварительных знаний в программировании.
В моем понимании - есть три группы таковых:
- детсадовцы (без возможности понимать какие-то формализмы)
- школьники (с возможностью понимать формализмы)
- возрастные взрослые (закончившие школу до ИТ эры)
Группу - старшешкольники и молодые взрослые - опустил - т.к. у них есть предварительные знания в объеме школьного курса.
Для каждой группы все будет по-разному.
Для самой младшей группы тебе придется сделать физические предметы представляющие собой части решения и обучать и складывать в решение под мантру поясняющую что именно делается. Дней за 10-15 сложишь и будет моргать светофор. На самостоятельное повторение или модификацию - не рассчитывай - они на это еще не способны.
приходим к довольно простой главной функции
-----
Да? А они в школе функции проходили? Хотя бы на уровне определения функции как отображение из многих в одно соответствие?
И уж точно гарантировать
-----
Задекларируй как задачу что тебе надо написать условия проверки горения лампочек используя оператор-иф - если знают необходимый минимум - могут написать.
Модифицируй задачу - в полученном светофоре зажигать нужный набор лампочек по внешней команде.
Модифицируй задачу еще раз - написать контроллер светофора - что-то что будет сообщать что должно гореть...
А цикл, тем более - бесконечный цикл в который запихано ВСЕ - им еще долго изучать...
читать жабий байт-код.
Не в этом дело. Все в одну простыню. В проге есть модули. Например состояния. Их надо изолировать. Тогда тот же кейс будет оперировать не кусками километрового кода, а объектами или на худой конец вызовами методов. То же с именами переменных.
Я не представляю, как можно начинающему понять где есть что и зачем.
А может не надо так? Может можно на конкретных примерах? Вот взять код Программиста и показать инкапсуляцию. Взять два класса зверь и собака и показать абстракцию и наследование? Агрегирование на примере колес автомобиля?
Не в этом дело. Все в одну простыню.Тут такой случай, что пока сам не испробуешь - не поймешь.
Уверяю всех неверующих: тупейшая простыня switch-casе - это самая понятная и удобная реализация машины состояний.
Ибо даже при отсутствии графического редактора, глядя на эту простыню case за case-ом, и имея в руках карандаш над бумагой, диаграмма безошибочно оказывается на ней.
Что и наоборот верно: нарисованная диаграмма однозначно ложится в swith case-ы.
А до того пока я это понял, я изобретал исполнялки машины состояний, входом которым служил массив описывающий состояния, и переходы в другие с Func<> в качестве условий, с Action<> в качестве действий.
Но когда приходит время применить это на реальной задаче, то обязательно найдется неудобный моментик, в котором вся эта жесткость определений связывает тебе руки, а при switch-case-ах они свободны.
Тогда тот же кейс будет оперировать не кусками километрового кода, а объектами или на худой конец вызовами методов.не знаю где там можно увидеть кусок километрового кода, ибо там именно кода нигде и 5 строк не превышает.
Но конечно можно все действия оформить в методы, а все условия - в функции. Но это как раз - маразм.
Это стоит делать только если код действительно большой - для наглядности.
Но надо еще учитывать что любые вызовы методов/функций - это накладные раходы, которые вполне могут оказывать существенное влияние, если программа работает на дохлом контроллере с еле живым процессором.
Мне приходилось перерабатывать функциональные блоки для их ускорения из за жалоб заказчиков, путём примитивного убирания вложенных вызовов функций, т.е. делая из "правильного" кода - простыни.
Суха мой друг
теория одна...как Пушкин сказал.
не кусками километрового кода, а объектами
-----
А как ты предлагаешь это получить из диаграммы?
Составитель диаграммы вообще не имеет представления об классах и методах.
Это было раз. Второе - там не обязательно Шарп-код на выходе - могут быть какие-то блоки команд для оборудования...
когда вообще ни одного коммента от начинающих не было.
-----
А как они могут быть если не только они, но и те кто давно с тобой общаются, узнают об том что является приемлемым решением только тогда, когда ты предъявляешь свое решение?
Может книжку напишешь, по методике форумного обучения
-----
Это к студентам педов.
Но могу сразу сказать, что схема останется той же.
Задача не для начинающих.
Я не ставил задачу :) Если хочешь иметь решение для начинующих, то будь людезен сформулировать задачу соответствующим образом.
Задача для начинающих. В таком случае должны быть использованы только те элементы которые им известны. Классы и интерфейсы к этому не относятся, к сожалению.
Класс - это основополагающая контрукция в C#. Так что это первое, что должны изучить начинающие. А соответственно основные понятия ООП.
Кстати, после тестирования выявлено, что приведенный код абсолютно нерабочий. А после возможного исправления, работает не так, как ожидалось.
Нет ничего удивительного в каких-то мелких багах, особенно если учесть, что код я писал в браузере и даже не компилировал его :) Не понятно также что ты ожидал увидеть, последовательность состояний вроде правильная.
Также очень бы хотелось увидеть реализацию класса TrafficLightButton для консольной проги под виндой, без каких либо извращений.
Реализация класса TrafficLightButton кажется мне тривиальной - геттер IsPressed - запрашиет состояние напрямую у железки, а функция Reset - сбрасывает кнопку в состояние "не нажата". Тут есть зависимость от конкретного железа, так что показать код не могу.
то будь любезен сформулировать задачу соответствующим образом.
Ну тот же светофор, может поначалу без кнопочки. Главное, что бы понятно было как работает для начинающих.
Я вот еще не знаю какие требования к кнопочке. Самое простое, просто уменьшать горение зеленого сигнала машинкам на какое то время?
Не понятно также что ты ожидал увидеть
По крайней мере то, что мы видим на перекрестках: R Y G Y R
Но это не принципиально, можно подкрутить.
геттер IsPressed - запрашиет состояние напрямую у железки
То бишь на обычной винде работать принципиально не будет? Только с какой то железякой?
Запустить код так и не смог
Пока вопросу по тому что вижу:
- Чем отличается кнопка BB от Button?
- Какой смысл в определении нажатия и отжатия кнопки?
Ну и вопрос немного не связанный с примером. Отчего нельзя использовать осмысленные имена, а не B1,B2 и т.п. ?
Запустить код так и не смогэто попробуй
Чем отличается кнопка BB от Button?ВВ это не кнопка, а внутренняя переменная запоминающая нажатие Кнопки. Т.к. реакция на кнопку не всегда мгновенна: может машинам только только зеленый загорелся, поэтому пусть пешеходы ждут, но их нажатие уже запомнилось.
Какой смысл в определении нажатия и отжатия кнопки?на случай если кнопку нажали, но отжимать не хотят. Чтобы не циклилось там.
Отчего нельзя использовать осмысленные имена, а не B1,B2 и т.п. ?да можно конечно. B1 это сокращенно Branch1. Но можно обозвать "ВеткаСветофора", а если хочется поинформативнее то можно добавить имя любимой собаки и погоды на завтра.

У нас вроде эти времена давно прошли смущ Хотя оптимизация часто бывает и нужна. Мы просто с Вами живем в различных мирах и понять друг друга будет действительно сложно.да нет, понять не сложно. Любой, даже супер-пупер компьютер станет дохлым если подходящую задачку подкинуть.
Ну а у контроллеров зачастую процессоры слабенькие, поэтому там сильно не надо заморачиваться чтобы его перегрузить.
Понятно одним Ампелем вряд ли получится, но ежели там сотни подобных программ одновременно выполняются, и каждая каждые 5мс вызывается, то тут надо до мелочей о производительности думать.
......
Помню выпустили новую версию проги (которой контроллеры программируют) ну естественно старым кундам предлагать стали. А они тупо собрали тест и начали гонять фирмварэ библиотеки, и сказали а почему функциональные блоки тут работают от 2х до 5ти раз медленнее, чем в старой системе?!
Дык потому что молодые люди, летающие в облаках КлинКодаДеволопмена
их разработали! Кунды не могут ведь оценить всю красоту их исходников. Вот и пришлось красоту рушить и даже на вызовах функций экономить.
Хотя конечно эти блоки работали достаточно быстро, но раз медленнее старой версии - кунды уже беспокоятся, что у них ВотчДоги гавкать начнут.
второй вариант тоже не работает
Выдает енто и зависает
Auto Green True
Pedestrian Red True
Вот как проверяю
private static void Main(string[] args) { TrafficLight3 trafficLight = new TrafficLight3(); while (true) { trafficLight.RunStep(); } }
ну еще от базового класса наследуюсь и удаляю "светофоры"
второй вариант тоже не работает
все работает. чтото у тебя
Дык потому что молодые люди, летающие в облаках КлинКодаДеволопмена их разработали!
Проблему тут не в ССД. Да и в нашем мире обычно другие проблемы.
Вот буквально живой пример. Если прога, года рождения 2000 на С++. Размером сейчас больше 300 тыс. строк, классы попадаются под 10 тыс. строк с функциями длиной больше 1000 строк.
Как её править знают буквально пара человек, но и те боятся что то трогать, потому что фиг его знает как это аукнется.
Чтобы ее просто откомпилировать правильно понадобилось минимум пара часов, при помощи того кто разбирается. А просто самому нужно было бы пару дней разбираться.
Была бы грамотно написана, не было бы многих проблем.
что то у тебя
Может быть, но я в упор не понимаю, как можно перейти на шаг 2 не нажимая никаких кнопок
switch (B1) { /*машины едут, пешеходы стоят*/ case 1: /*S1*/ { /*пешеход нажал кнопку*/ if (BB) { /*прошло ли достатоно времени для потока машин*/ if (Environment.TickCount - B1_T > 5000) { /*машинам желтый*/ B1 = 2; /*S2*/ } }
каков алгоритм работы?
Задача то ваша была, я написал как понял
https://foren.germany.ru/showmessage.pl?Number=37617857&Bo...
а что такое "стандартный режим" ?
я подразумевал что машинам зелёный по умолчанию, и только если пешеход кнопку нажал, то на некоторое время машинам включается красный (ну и желтый конечно)
конечно можно бес проблем "зелёный по умолчанию" убрать и переключать как по кнопке, так и по таймеру. Но тогда странно будет, если пешеходов нету, а машинам красный.
а что такое "стандартный режим" ?
то что видим каждый день RYGYR
Но тогда странно будет, если пешеходов нету, а машинам красный.
У меня на перекрестке именно так и кнопа есть.
Я так предполагал, что если ничего не сказано против этого так оно и есть.
Но в итоге мы делали разные задачи, хорошо хоть выяснили наконец. В общем, стандартное общение с заказчиком
ну вот теперь машины будут ездить не более 10 секунд (от балды цифра), даже если пешеходов нету.
Всё равно как то странно получается, то красный и зелёный не горят, то 10 секунд на желтый.
+------+-----+-----+ |Pdestr|Auto |Delay| | R G |R Y G| [s] | |------+-----+-----| | * | *|0.047| | | * |10.016| | * |* |2.016| | * | * |5.015| | * | *|1.016| | | * |10.015| | * |* |2.016| | * | * |5.016|
да на скорую руку сделано. не проверено.
неужто самому трудно проверить и подправить?
вот это железно будет работать:
но задержки, надеюсь, сможешь нужные поставить?!
чтоб точнее времена совпадали, надо почаще дергать. раз 10 в секунду - ок.
погрешность будет одна десятая секунды.
..........
итого должно быть так, если нету пешегоходов
- зеленый 30 сек (пешеходам красный)
- желтый 2 сек
- красный 5 сек (пешеходам зеленый)
- желтый 1 сек (пешеходам красный)
- и сначала.
неужто самому трудно проверить и подправить?
Ну как бы это сказать....
Стиль работы в команде предполагает, что каждый участник выполняет свою работу правильно и до конца. Если за каждым всё тестировать и переделывать, то ...
Пока, что видны только недостатки языков визуального программирования в области отладки. Что даже достаточно опытный программист, не может сразу предоставить работоспособный код.
Пысы: мне в принципе хватило того, что бы добавить туды табличку для вывода результатов.
Что полезно железякам - не полезно винде
Увы, ничего не могу даже проверить. Лампочка зеленого для авто постоянно мерцает. Auto Green False Auto Green Trueэто чтото у тебя не так. тут уж я зуб даю. ибо у себя проверил.
выложи как ты там дергаешь. что то не так.
надо сделать экземпляр Ампеля и его Process дергать по таймеру (10 раз в сек например)
Пока, что видны только недостатки языков визуального программирования в области отладки. Что даже достаточно опытный программист, не может сразу предоставить работоспособный код.да если без отладки релиз делать, то и с текстовым языком проблемы будут тем более, чем с визуальным.
тут уж я зуб даю.
Считай повезло, что я не зубной врач
Мерцает абсолютно всё, судя по коду.
R = Y = G = false; if (B1_Pulse) ... /*машины едут, пешеходы стоят*/ case 1: /*S1*/ { G = true;
выложи как ты там дергаешь.
Уже всё выкладывал
Сейчас, правда немного по другому
private static void Main(string[] args) { TrafficLight5 trafficLight = new TrafficLight5(); InitTraceState(); while (true) { trafficLight.RunStep(); if (trafficLight.IsAnyChanges) { TraceState(trafficLight); } } }
Мерцает абсолютно всё, судя по коду.код правильный. выходы надо читать после вызова Process, а то что там внутри происходит это вызывателя не касается.
Поэтому переопределение выходов - это твоя ошибка.
Я же не сделал выходы виртуальными, а ты это в моем коде подправил.
......
пардон не верно сказал про "виртуальными".
но ты сменил переменные на свойства, и считаешь изменением каждую запись в свойство (пусть даже другого значения), а это неверно.
читать надо не то что происходит внутри Процесс, а то что есть после Процесс.
выходы надо читать после вызова Process
Тогда я не понимаю как работает этот контроллер
По идее должно быть так:
У меня есть цифровой выход, к нему подключена релюшка/тиристор. Установили "1" - реле включилось зажгло лампочку, установили 0 реле отключилось.
Выход "R" - цифровой выход к красному сигналу авто.
Что там и как крутится внутри волновать не должно.
Не могу я выходы сразу читать, надо городить еще что то чтобы "выбросить ненужное".
надо где то так:
private static void Main(string<> args)
{
Ampel trafficLight = new Ampel();
while (true)
{
trafficLight.Process();
// Trace outputs ...
Sleep(100);
}
}
и R,G,Y надо оставить переменными, а не свойствами.
Что там и как крутится внутри волновать не должно.правильно. Но ты поменял внутреннюю часть моего кода: изменил выходные переменные на свойства, и вставил туда свой код.
Это неправильно.
Ты можешь только читать выходы и больше ничего.
Ты можешь только читать выходы и больше ничего.
Ну я именно так и делаю. Я читаю, что пишется в шину цифровых выходов. Когда именно там изменяется сигнал во время функции или внутри нее, я не имею понятия. Не имеет права контроллер мерцать цифровым выходом.
Я просто проводками соединил шину с моей линейкой светодиодов.
Не имеет права контроллер мерцать цифровым выходом.он и не мерцает.
эти выходные переменные R,G,Y не являются лампочками, чтобы им мерцать при каждой записи.
значения этих переменных присваиваются реальным лампочкам (не в процессе работы, а) уже после вызова всех программ контроллера, т.е. после вызова Process.
не понял...
Ну вот старый код в желаемом исполнении. Есть разница с той табличкой что была ранее?
+------+-----+-----+ |Pdestr|Auto |Delay| | R G |R Y G| [s] | |------+-----+-----| | * | *|0.047| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.515| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | * | *|0.500| | | * |0.500| | | * |0.500| | | * |0.500| | | * |0.500| | | * |0.500| | | * |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500| | * |* |0.500|
Ну а на кой мне тогда симуляция на шарпе, если я не могу проверить реальное устройство?как это на кой?! прежде чем подключать реальное устройство, лучше проверить на шарпе. Но повторяю, ты не должен модифицировать мой код (по нормальному у тебя его даже не должно быть, а только DLL), ты можешь только им пользоваться, т.е. читать выходы и дергать Процесс.
функциональные блоки не работают напрямую с реальными устройствами.
юзер делает свою логику и потом, в системе программирования, связывает в таблице логические выходы с физическими лампочками.
А система работает так циклически:
- вызывает все программы (т.е. у каждой Process)
- перезаписывает выходы в реальное железо (что юзер в табличке указал)
вроде правильна табличка.
А если с этой сравнить? Видна разница?
+------+-----+-----+ |Pdestr|Auto |Delay| | R G |R Y G| [s] | |------+-----+-----| | * | *|0.031| | | * |10.016| | * |* |2.016| | * | * |5.015| | * | *|1.016| | | * |10.015| | * |* |2.016|
и эта вроде правильна по логике переключения лампочек. но чего там времена значат тебе виднее
........
пардон там с зеленым пешеходу похоже проблемы...в момент желтого у машин
Никогда еще не сталкивался с этим. Хотя может нам уже готовое давали.
логика отделена от физики.
производитель программ управления продаёт логику. а эту логику цепляют к разной физике, причем связываться с физикой может просто адресом на шине, а может и адресом по интернету - зависит от системы.
в твоем случае "физикой" является консоль. а у меня здесь - симулятор.
перед ampel.Process();
там стоило бы записать типа
ampel.Button = %IX100.33.10
вот эти % в настоящей системе задают адрес устройства чтения одного бита.
ну а у тебя надо может нажатие на кнопку клавиатуры туда записать.
тут чуть нагляднее и на клаву реагирует
в соответствии с диаграммой
машинам включится сразу желтый, если они уже ездили минимум 10 секунд.
иначе желтый включится когда они поездят хотя бы 10 сеунд (отсчет от включения зелёного).
еще когда машинам красный, кнопка игнорируется.
----
да еще на всяк случай: на диаграмме желтый горит 1 секунду, а в файле что у тебя что в прошлом посте послал - 2 секунды.
Хорошо что спросил, потому как у меня совсем другой.
"Кнопка работает, только когда красный машинам и просто уменьшает время его горения на какое-то время", но нет защиты от постоянных нажатий.
Потому как если нажал после красного, то смысла в этом нет - и так будет зеленый.
еще когда машинам красный, кнопка игнорируется.
вот это не доходит отчего
Но в принципе, у нас получается пока два кардинально разных подхода к решению: используя задержку после изменения состояния и измена состояния после отрезка времени.
У каждого есть свои достоинства и недостатки, особенно когда влезает еще и кнопочка. /Имея в виду исполнение программы под виндовс/
Под определенный алгоритм работы кнопки еще как то можно настроить систему, но вот интересно было бы сделать, что бы менять алгоритм работы кнопки достаточно просто не влезая в состояния.
тут я не понимаю чего там не доходит.еще когда машинам красный, кнопка игнорируется.вот это не доходит отчего
У меня логика такая: если машинам красный, то в это время людям зелёный. И людям следует дорогу переходить, а не на кнопку жать. Поэтому такие нажатия я считаю балавством и игнорирую.
Только если людям красный - только тогда кнопка воспринимается.
используя задержку после изменения состояниякак то неправильно звучит "задержка"...
У меня в алгоритме нет никаких задержек. Лучше сказать так: каждое состояние длится ограниченное время и они сменяют друг друга.
что бы менять алгоритм работы кнопки достаточно просто не влезая в состояния.скажи как кнопка должна работать и сделаем.
когда машинам красный, кнопка игнорируется.
А ты любишь выстрелить себе в колено :)
Можно ведь представить кнопку просто как триггер. Те если кнопка нажата, то через 10 секунд запускается смена состояний.
Предположим, что зелёный горит 10 секунд. На 8-й секунде к светофору подходит старушка и хочет сразу нажать кнопку. Зачем ей ждать 2 секунды пока не загорится красный?
Предположим, что зелёный горит 10 секунд. На 8-й секунде к светофору подходит старушка и хочет сразу нажать кнопку. Зачем ей ждать 2 секунды пока не загорится красный?если хочет пусть жмёт. Но какой смысл ей жать, если как раз сейчас ей горит зелёный. Ей идти надо.
Можно ведь представить кнопку просто как триггер. Те если кнопка нажата, то через 10 секунд запускается смена состояний.это плохо. например такая ситуация:
- загорелся зелёный для пешеходов
- подошел аболтус нажал на кнопку (запустил отсчет 10 сек) и перешел дорогу
- машинам уже зеленый, пешеходов нету, и тут прошли эти 10 сек.
нехорошо: никого из пешеходов нет, а машинам красный
Но какой смысл ей жать, если как раз сейчас ей горит зелёный. Ей идти надо.
Она вежливая бабушка и знает, что на переход дороги ей надо 9 секунд, те она гарантированно не успеет перейти дорогу на зелёный. Она знает правила, что ей должны дать возможность завершить переход, но тк она вежливая бабушка, она не хочет, чтобы машины ждали на свой зелёный :)
странное объяснение :) абалтус может нажать кнопку и на красной фазе , а потом пойти в другую сторону :)
Плюс использования кнопки как триггера (ну или как флага) заключается в том, что можно выкинуть всю логику, которая завязана на кнопке :) а мы знаем, что чем меньше логики, тем меньше ошибок :) Я уж не говорю о том, что пешеходы не отжимают кнопку светофора ;
Только если людям красный - только тогда кнопка воспринимается.
Точно, это я фигню спорол именно так постоянно и делаю
скажи как кнопка должна работать и сделаем
Дело не в этом. Кнопке нужно слишком много данных и заранее неизвестно каких.
Я хочу иметь отдельный класс для логики кнопки, а не размазывать всё по остальному коду.
Она вежливая бабушка и знает, что на переход дороги ей надо 9 секунд,тут от вежливости ничего не зависит. Если бабушка подошла к светофору за 2 секунды до отключения зелёного, то на светофоре не написано что 2 секунды осталось, поэтому бабушка даже об это не узнает, а пойдет через дорогу.
абалтус может нажать кнопку и на красной фазе , а потом пойти в другую сторону :)красной фазе чего? ежели он нажмет когда машинам красный - то флаг ему в руки, все его потуги пойдут в игнор.
Плюс использования кнопки как триггераоборудование не было оговорено, что в кнопке тригер сидит.
программа расчитана на тупое замыкание контактов.
Я уж не говорю о том, что пешеходы не отжимают кнопку светофора ;это программой предусмотренно.
Дело не в этом. Кнопке нужно слишком много данных и заранее неизвестно каких. Я хочу иметь отдельный класс для логики кнопки, а не размазывать всё по остальному коду.понятно: ты не знаешь как кнопка работает, но знаешь что она в классе.

Мне как раз главнее знать как она работает, а реализация до лампочки.
Сегодня кнопка работает так, а завтра по другому.может быть. но я не могу себе представить как кнопка может работать по другому?! в программе ловится сигнал от кнопки, а как он был выработан - до лампочки
впрочем можно конечно себе представить, что сигнал будет выработан только после неких манипуляций с кнопкой, типа: два коротких, три длинных нажатия, а после второго длинного надо подпрыгнуть и оббежать вокруг столба, и проорать "кукареку".
Ты подобное имел ввиду, говоря что не знаешь как кнопка работает?
Начали мы с самой простой функции, но как оказалось, что в данной реализации дополнительную кнопку просто негде опрашивать. Извратиться конечно можно, но извращения нам ни к чему.
Так что функцию Delay /Задержка/ нужно как то убрать. Нужно ее просто преобразовать во что то, что не стоит тупо на месте. Можно просто проверять сколько прошло времени, но тогда потеряется последовательность состояний.
Какой выход? Увы только усложнять.
Давайте еще раз глянем на нашу функцию, что там можно увидеть?
Видим 4 состояния которые связаны между собой. Каждой состояние имеет определенный паттерн: инициализация при входе, задержка, некая работа перед выходом из состояния.
Так как классы мы уже начали изучать, то сразу виден некий базовый объект и наследуемые от него объекты которые будут определять инициализацию при входе в состояние и работу перед выходом. (Хотя в данном случае эта работа одинаковая для всех состояний)
internal class State { private readonly int _durationMs; private State _next; private int _startTime; public State(int durationMs) { _durationMs = durationMs; } public virtual void DoStateStep() { // do nothing here } public virtual void EnterState() { _startTime = Environment.TickCount; } public virtual void ExitState() { // do nothing here } public bool IsStateFinished() { return Environment.TickCount - _startTime >= _durationMs ; } public int DurationMs { get { return _durationMs; } } public State Next { get { return _next; } set { _next = value; } } }
Для сокращения места приведем только одно состояние, так как остальные состояния, будут отличаться всего одной функцией EnterState(), код которых берется из состояний 2,3,4
internal class AutoRedState : State { private readonly CombinedTrafficLight _trafficLight; public AutoRedState(CombinedTrafficLight trafficLight, int durationMs, State next = null) : base(durationMs, next) { _trafficLight = trafficLight; } public override void EnterState() { base.EnterState(); _trafficLight.DisableAutoTraffic(); _trafficLight.EnablePedestrianTraffic(); } public override void ExitState() { base.ExitState(); Program.TraceState(_trafficLight); } }
Еще будет интересно знать как выглядит основная функция.
private static void Main() { CombinedTrafficLight trafficLight = new CombinedTrafficLight(); InitTraceState(); //инициализация состояний ButtonSimulator button = new ButtonSimulator(); State redState = new AutoRedState(trafficLight, RedLightTimeMs); State yellowStateAfterRed = new AutoYellowAfterRedState(trafficLight, YellowLightTimeMs); State greenState = new AutoGreenState(trafficLight, GreenLightTimeMs, button); State yellowStateAfterGreen = new AutoYellowAfterGreenState(trafficLight, YellowLightTimeMs); redState.Next = yellowStateAfterRed; yellowStateAfterRed.Next = greenState; greenState.Next = yellowStateAfterGreen; yellowStateAfterGreen.Next = redState; // цикл перехода между состояниями State currentState = redState; currentState.EnterState(); while (true) { button.CheckButtonState(); currentState.DoStateStep(); if (currentState.IsStateFinished()) { currentState.ExitState(); button.ClearPressedState(); currentState = currentState.Next; if (currentState == null) { break; } currentState.EnterState(); } Thread.Sleep(100); } }
Вроде бы кода много добавили, но более запутанным, он по идее не стал. По крайней мере если надо изменить состояние - изменяем класс конкретного состояния.
Нужно добавить новое состояние, тоже происходит без проблем, не нужно исправлять много разных частей.
Ты подобное имел ввиду, говоря что не знаешь как кнопка работает?
Нет, мы же в разных мирах
Сегодня, хочу что нажатие кнопки сокращало зелёный машинам на какое то время.
Завтра, что бы следующее сокращение могло происходило только после одного полного цикла.
Послезавтра, что бы машины ездили не менее 15 секунд до срабатывания следующего запроса.
Через неделю может еще, что захочется. И каждый раз надо думать как "собрать" все условия и где это всё разместить.
Я загнал классы Программиста в яву и запустил. Работает. Кнопку прикрутил отдельным потоком, просто как реакцию на нажатие любой кнопки на клавиатуре. Все работает согласно его логике. Потом чуть изменил контроллер. Поменялась логика. Состояния , где пешеходам красный, просто крутятся в цикле. При достижении состояния, где пешеходу МОЖЕТ БЫТЬ включен зеленый, проверяется кнопка. И если она нажата, то включается состояние "красный-зеленый". Без кнопки "красный-красный". Код подправлен для логики одного светофора на перекрестке. Где переключение цикличное.
И еще. Если код для начинающих, то он должен чему то учить. Цель не научить рисовать светофоры. Поэтому во-первых не нужно усложнять задание задержками включения кнопки. Слишком много деталей. Во-вторых на примере должно быть видно, насколько код устойчив к изменениям. Небольшие изменения в техзадании - насколько нужно переписывать код? Насколько легко код понимают и могут воспроизвести коллеги? Насколько легко колеги могут код допилить?
Если бабушка подошла к светофору за 2 секунды до отключения зелёного, то на светофоре не написано что 2 секунды осталось, поэтому бабушка даже об это не узнает, а пойдет через дорогу.
Бабушка зрячая и видит, что зеленый уже долго горит. Так что даже если нет таймера, бабушка все равно трезво оценивает ситуацию и понимает, что перейти в зеленую фазу она не успеет.
красной фазе чего? ежели он нажмет когда машинам красный - то флаг ему в руки, все его потуги пойдут в игнор.
Красной фазе пешеходам и соответственно зеленой фазе машинам.
оборудование не было оговорено, что в кнопке тригер сидит.программа расчитана на тупое замыкание контактов.
Так это ради бога. Вопрос в том, как кнопку интерпритирует программист. Ее (кнопку) удобно представлять в виде простого триггера, который умеет делать всего 2 вещи: 1) сообщать о своем состоянии (на важно как) и 2) сбрасывать состояние в "неактивное".
это программой предусмотренно.
Да? В каком месте? Я у тебя в диаграмме вижу "пешеход отжал кнопку". Так вот уверяю тебя, что ни один пешеход никогда в жизни не будет отжимать кнопку. Так что твоя диаграмма заведомо нерабочая.
Так что даже если нет таймера, бабушка все равно трезво оценивает ситуацию и понимает, что перейти в зеленую фазу она не успеет.какая умная бабушка! видимо годы свои не зря прожила, а светофорный опыт всю жизнь оттачивала.

Но почему бабушка не знает, что ежели она хоть шаг на дорогу сделала (как положено, когда ей зеленый горел), то машины обязаны ее подождать?
Впрочем, чего спорить, если логику поменять - раз плюнуть?!
Какие у тебя предложения? Никогда не игнорировать кнопку?
Так вот уверяю тебя, что ни один пешеход никогда в жизни не будет отжимать кнопку. Так что твоя диаграмма заведомо нерабочая.так кнопки на светофорах вроде суперклеем не мажут

........
в диаграме указано что кнопка замыкает контакт и размыкает его. Сейчас светофор реагирует на размыкание, но можно сделать реакцию на замыкание.
Важно реагировать именно на изменение состояния кнопки, а не на само состояние.
Но почему бабушка не знает, что ежели она хоть шаг на дорогу сделала (как положено, когда ей зеленый горел), то машины обязаны ее подождать?
Я же писал, что бабушка это знает :) И я писал, что она очень вежлива и не любит, когда другие ее ждут :)
Какие у тебя предложения? Никогда не игнорировать кнопку?
Логика простая - когда пешеходам красный - можно опрашивать кнопку. Когда пешеходам зеленый - сбрасывать состояние кнопки. Все :) Во всех остальных состояниях кнопка никого не интересует.
когда пешеходам красный - можно опрашивать кнопку.так именно так и есть.
Когда пешеходам зеленый - сбрасывать состояние кнопки.когда зеленый - нажатия игнорируются, как будто их и не было.
Всё работает как ты желаешь.
Сегодня, хочу что нажатие кнопки сокращало зелёный машинам на какое то время. Завтра, что бы следующее сокращение могло происходило только после одного полного цикла. Послезавтра, что бы машины ездили не менее 15 секунд до срабатывания следующего запроса. Через неделю может еще, что захочется. И каждый раз надо думать как "собрать" все условия и где это всё разместить.так это просто смещение логики.
Если я рассматриваю сейчас всё устройство, как светофор(лампочки и логику) с кнопкой, то ты сейчас думаешь о кнопке с логикой, а сам светофор - одни лампочки.
Если очень хочется, то разделить логику лампочек и логику кнопки.
Но по-моему, плодить классы в задаче светофора уже одержимостью попахивает.
На мой взгляд тут один класс, у которого на вход подаётся состояние кнопки, а выходы подключаются к лампочкам. Но ни кнопка ни лампочки - не относятся к этому классу.
И если нужна какая-то логика для работы с лампочкой или кнопкой, то это должно быть сделано в других классах.
Но класс светофора от этого вообще не зависит. Ибо ему всё равно: пришел сигнал непосредственно с кнопки или из класса обслуживающего кнопку. Тоже - и о лампочках.
плодить классы в задаче светофора уже одержимостью попахивает.
Классы или есть или их нет. Не пишут сегодня классы, а завтра простыни. Твой код рабочий, но читать его очень тяжело. Там то кода один метод, но не хотел бы я править баги в таком коде.
мой взгляд тут один класс,
На твой взгляд тут классов нет. Ты пытаешься всунуть код в какой то контейнер , который ты считаешь классом и по количеству кода прикидывает, не нужен ли ещё один пвсевдокласс, а то первый великоват получается. Или не получается. Количество кода не критерий для инкапсуляции его в класс.
Количество кода не критерий для инкапсуляции его в класс.а кто выдвинул тут такой критерий?
Твой код рабочий, но читать его очень тяжело. Там то кода один метод, но не хотел бы я править баги в таком коде.а его читать и не надо. Это код автоматически сгенерированный из диаграммы. Читать и править надо диаграмму.
так кнопки на светофорах вроде суперклеем не мажут. Достаточно убрать руку чтоб кнопку отжать. Конечно это от устройства кнопки завсит.
В таком случае у меня 2 замечания:
1) если для того, чтобы отжать кнопку достаточно убрать руку, то не понятно, почему это действие присутствует в диаграмме. Ведь по-сути действия "отжать кнопку" не существует.
2) сейчас кнопки делаются в виде сенсора, а не в виде кнопки, т.е. там нет действия "нажать" или "отжать" :)
Важно реагировать именно на изменение состояния кнопки, а не на само состояние.
В этом твоя ошибка :) Потому что на самом деле все как раз наоборот. Изменение состояния кнопки - не интересно. Интересно состояние. При этом состояние интересно только в одной фазе светофора - когда машинам зеленый.
Во всех остальных случаях состояние кнопки тоже не интересно :) (единственный момент - надо не забыть "скинуть" состояние, когда пешеходам будет зеленый).
1) если для того, чтобы отжать кнопку достаточно убрать руку, то не понятно, почему это действие присутствует в диаграмме. Ведь по-сути действия "отжать кнопку" не существует. 2) сейчас кнопки делаются в виде сенсора, а не в виде кнопки, т.е. там нет действия "нажать" или "отжать" :)Серсор вырабатывает два события: переход из FALSE в TRUE, и назад в FALSE. Это соответствует нажатию и отжатию кнопки. Т.е. он вырабатывает импульс, а у импульса есть передний и задний фронт сигнала.
Программа ничего не знает об устройстве кнопки, и даже о ее существовании. У программы есть только булевский вход: сигнал запроса зеленого пешеходам. Сейчас программ реагирует на задний фронт сигнала, но можно отреагировать и на передний - принципиально ничего не поменяется.
В этом твоя ошибка :)да нет, всё правильно. Именно событие надо ловить - изменение состояния кнопки, и запомнить его до применения (которое может быть сразу, а может чуть позже).
динственный момент - надо не забыть "скинуть" состояние,это и делается: запомненное событие забывается после применения.
При этом состояние интересно только в одной фазе светофора - когда машинам зеленый. Во всех остальных случаях состояние кнопки тоже не интересно :) (единственный момент - надо не забыть "скинуть" состояние, когда пешеходам будет зеленый).
Имхо. Если мы говорим о светофоре на перекрестке. Состояние кнопки интересно, когда нужно включать состояние "машинам красный". В этом случае есть 2 варианта - включать пешеходам зелёный, если состояние кнопки "нажата". Или не включать и тогда у всех красный.по окончании состояния "машинам красный, пешеходам зелёный" состояние кнопки сбросить.
Если мы говорим о светофоре на перекрестке. Состояние кнопки интересно, когда нужно включать состояние "машинам красный". В этом случае есть 2 варианта - включать пешеходам зелёный, если состояние кнопки "нажата". Или не включать и тогда у всех красный.по окончании состояния "машинам красный, пешеходам зелёный" состояние кнопки сбросить.мне вообще не понятно зачем НЕ включать зелёный пешеходам, когда машинам - красный?
Простая противофаза - лучшее решение.
мне вообще не понятно зачем НЕ включать зелёный пешеходам, когда машинам - красный?
Не знаю. Дебильная система, которая везде у нас установлена. Но так работают все светофоры на перекрестке с кнопкой. Я симулировал реальную систему
то ты сейчас думаешь о кнопке с логикой, а сам светофор - одни лампочки
В данный момент были именно размышления о кнопке с логикой.
Светофор и его логика как бы отдельная вещь и именно эти две вещи хочется иметь раздельными.
А лампочки были отделены еще на самой первой стадии При этом получился объект с тремя фиксированными состояниями.
Еще есть логика переключения состояний.
А к этому есть кнопка которая должна как то изменить логику переключений. При этом необходимо знать актуальное состояние и возможно предыдущие.
На мой взгляд тут один класс
Один класс не может быть даже при обычном светофоре. Так как у нас есть по крайней мере, две задачи: включение/выключение лампочек и логика их смены.
Любая система должна делится на простейшие части.
У нас вот сейчас 5 лампочек, которые должны реагировать на 3 сигнала определенным образом. Если оставить их как есть то возрастет вероятность ошибки так как эта логика должна быть где-то в другом месте.
то это должно быть сделано в других классах
именно так, один класс никак не катит. Дело тут никак не в одержимости.
Хотя можно сделать и больше классов чем действительно нужно, на все возможные случаи жизни. В данном случае будет просто неоправданное усложнение реализации.