]> git.lizzy.rs Git - lmz_opening_hours.git/blobdiff - init.lua
configure and apply time intervals for all weekdays
[lmz_opening_hours.git] / init.lua
index c8593797224b2f0d845e939c7c7333de00e19577..85d91c24bd7ca5db174e686e1106939ba440a9ba 100644 (file)
--- a/init.lua
+++ b/init.lua
@@ -3,7 +3,39 @@ local storage = minetest.get_mod_storage()
 
 opening_hours = {}
 
-local opening_hours_default = {weekday_start = 14, weekday_end = 21, weekend_start = 8, weekend_end = 21, warn_offset = 15, warn_interval = 5}
+local opening_hours_default = {
+       version = 2,
+       day0_start_hour = 8,
+       day0_start_minute = 0,
+       day0_end_hour = 21,
+       day0_end_minute = 0,
+       day1_start_hour = 14,
+       day1_start_minute = 0,
+       day1_end_hour = 21,
+       day1_end_minute = 0,
+       day2_start_hour = 14,
+       day2_start_minute = 0,
+       day2_end_hour = 21,
+       day2_end_minute = 0,
+       day3_start_hour = 14,
+       day3_start_minute = 0,
+       day3_end_hour = 21,
+       day3_end_minute = 0,
+       day4_start_hour = 14,
+       day4_start_minute = 0,
+       day4_end_hour = 21,
+       day4_end_minute = 0,
+       day5_start_hour = 14,
+       day5_start_minute = 0,
+       day5_end_hour = 21,
+       day5_end_minute = 0,
+       day6_start_hour = 8,
+       day6_start_minute = 0,
+       day6_end_hour = 21,
+       day6_end_minute = 0,
+       warn_offset = 15,
+       warn_interval = 5
+}
 
 local warn_cooldown = 0
 
@@ -15,9 +47,48 @@ local function get_date_formated()
        return os.date("%d.%m.%y")
 end
 
-local function is_weekend()
-       local d = os.date("%w")
-       return d == "0" or d == "6"
+local function upgrade_configuration(old)
+       local new = {
+               version = 2,
+               day0_start_hour = tonumber(old.weekend_start),
+               day0_start_minute = 0,
+               day0_end_hour = tonumber(old.weekend_end),
+               day0_end_minute = 0,
+               day1_start_hour = tonumber(old.weekday_start),
+               day1_start_minute = 0,
+               day1_end_hour = tonumber(old.weekday_end),
+               day1_end_minute = 0,
+               day2_start_hour = tonumber(old.weekday_start),
+               day2_start_minute = 0,
+               day2_end_hour = tonumber(old.weekday_end),
+               day2_end_minute = 0,
+               day3_start_hour = tonumber(old.weekday_start),
+               day3_start_minute = 0,
+               day3_end_hour = tonumber(old.weekday_end),
+               day3_end_minute = 0,
+               day4_start_hour = tonumber(old.weekday_start),
+               day4_start_minute = 0,
+               day4_end_hour = tonumber(old.weekday_end),
+               day4_end_minute = 0,
+               day5_start_hour = tonumber(old.weekday_start),
+               day5_start_minute = 0,
+               day5_end_hour = tonumber(old.weekday_end),
+               day5_end_minute = 0,
+               day6_start_hour = tonumber(old.weekend_start),
+               day6_start_minute = 0,
+               day6_end_hour = tonumber(old.weekend_end),
+               day6_end_minute = 0,
+               warn_offset = tonumber(old.warn_offset),
+               warn_interval = tonumber(old.warn_interval)
+       }
+       if old.today then
+               new.exception_today = old.today
+               new.exception_start_hour = old.today_start
+               new.exception_start_minute = 0
+               new.exception_end_hour = old.today_end
+               new.exception_end_minute = 0
+       end
+       return new
 end
 
 local function save_data()
@@ -26,53 +97,62 @@ end
 
 local function load_data()
        opening_hours = storage:to_table().fields
-       if not opening_hours.weekday_start then
+       if opening_hours.weekday_start then
+               opening_hours = upgrade_configuration(opening_hours)
+       elseif not opening_hours.version then
                opening_hours = opening_hours_default
        end
 end
 
 local function reset_execption()
-       opening_hours.today = nil
-       opening_hours.today_start = nil
-       opening_hours.today_end = nil
+       opening_hours.exception_today = nil
 end
 
 local function opening_today()
-       local today = opening_hours.today
-       if today and today == get_date_formated() then
-               return opening_hours.today_start, opening_hours.today_end
-       elseif is_weekend() then
-               return opening_hours.weekend_start, opening_hours.weekend_end
+       local exception = opening_hours.exception_today
+       local day_key
+       if exception and exception == get_date_formated() then
+               day_key = "exception"
        else
-               return opening_hours.weekday_start, opening_hours.weekday_end
+               local d = os.date("%w")
+               day_key = "day" .. d
        end
+       return {
+               start_hour = opening_hours[day_key .. "_start_hour"],
+               start_minute = opening_hours[day_key .. "_start_minute"],
+               end_hour = opening_hours[day_key .. "_end_hour"],
+               end_minute = opening_hours[day_key .. "_end_minute"]
+       }
 end
 
 local function create_exception()
-       local today_start, today_end = opening_today()
-       opening_hours.today = get_date_formated()
-       opening_hours.today_start = today_start
-       opening_hours.today_end = today_end
+       local today = opening_today()
+       opening_hours.exception_today = get_date_formated()
+       opening_hours.exception_start_hour = today.start_hour
+       opening_hours.exception_start_minute = today.start_minute
+       opening_hours.exception_end_hour = today.end_hour
+       opening_hours.exception_end_minute = today.end_minute
 end
 
 local function tick(dtime)
        local d = get_date()
-       if opening_hours.today and opening_hours.today ~= get_date_formated() then
+       local exception = opening_hours.exception_today
+       if exception and exception ~= get_date_formated() then
                reset_execption()
        end
-       local today_start, today_end = opening_today()
-       local diff = tonumber(today_end) - d.hour
-       if diff == 1 then
-               local minutes_remaining = (60 - d.min)
-               if minutes_remaining <= tonumber(opening_hours.warn_offset) then
-                       if warn_cooldown <= 0 then
-                               minetest.chat_send_all(minetest.colorize("#FF4D00", "Der Server schießt in " .. minutes_remaining .. " Minuten."))
-                               warn_cooldown = tonumber(opening_hours.warn_interval) * 60
-                       else
-                               warn_cooldown = warn_cooldown - dtime
-                       end
+       local today = opening_today()
+       local end_time = today.end_hour * 60 + today.end_minute
+       local now_time = d.hour * 60 + d.min
+       local minutes_remaining = end_time - now_time
+       if 0 < minutes_remaining
+       and minutes_remaining <= opening_hours.warn_offset then
+               if warn_cooldown <= 0 then
+                       minetest.chat_send_all(minetest.colorize("#FF4D00", "Der Server schießt in " .. minutes_remaining .. " Minuten."))
+                       warn_cooldown = tonumber(opening_hours.warn_interval) * 60
+               else
+                       warn_cooldown = warn_cooldown - dtime
                end
-       elseif diff <= 0 then
+       elseif minutes_remaining <= 0 then
                for _, player in pairs(minetest.get_connected_players()) do
                        local name = player:get_player_name()
                        if not minetest.check_player_privs(name, {server = true}) then
@@ -84,51 +164,160 @@ end
 
 local function on_join(name)
        if minetest.check_player_privs(name, {server = true}) then return end
-       local today_start, today_end = opening_today()
+       local today = opening_today()
        local d = get_date()
-       local diff = tonumber(today_start) - d.hour
+       local start_time = today.start_hour * 60 + today.start_minute
+       local end_time = today.end_hour * 60 + today.end_minute
+       local now_time = d.hour * 60 + d.min
+       local diff = start_time - now_time
        if diff > 0 then
-               return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat in " .. math.ceil(diff) .. " Stunde(n) wieder geöffnet."
-       elseif tonumber(today_end) <= d.hour then
+               return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat in " .. math.ceil(diff / 60) .. " Stunde(n) wieder geöffnet."
+       elseif end_time <= now_time then
                return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat bereits geschlossen und hat Morgen wieder geöffnet."
        end
 end
 
+local minute_step = 5
+
 local function show_gui(name)
-       local fld_w = 1.0
+       local fld_w = 0.88
        local fld_h = 0.82429501084599
        local fld_sz = fld_w .. "," .. fld_h
+       local inline_off = 0.2427394885132
        local lab_close_y = 6.3935847420893
        local fld_close_y = lab_close_y + 0.2427394885132
+       local pre_colon_off = 0.4
+       local minute_off = 0.04
+       local to_off = 1.24
+       local day_off = 3.6
        local lab_day1_x = 0.1
-       local fld_day1_f_x = 0.64
-       local fld_day1_t_x = 1.6
-       local time_off = 1.1530125704378
+       local fld_day1_f_hour_x = 0.64
+       local fld_day1_f_minute_x = fld_day1_f_hour_x + fld_w - minute_off
+       local lab_day1_f_colon_x = fld_day1_f_minute_x - pre_colon_off
+       local fld_day1_t_hour_x = lab_day1_f_colon_x + to_off
+       local fld_day1_t_minute_x = fld_day1_t_hour_x + fld_w - minute_off
+       local lab_day1_t_colon_x = fld_day1_t_minute_x - pre_colon_off
+       local lab_day2_x = lab_day1_x + day_off
+       local fld_day2_f_hour_x = fld_day1_f_hour_x + day_off
+       local fld_day2_f_minute_x = fld_day1_f_minute_x + day_off
+       local lab_day2_f_colon_x = lab_day1_f_colon_x + day_off
+       local fld_day2_t_hour_x = fld_day1_t_hour_x + day_off
+       local fld_day2_t_minute_x = fld_day1_t_minute_x + day_off
+       local lab_day2_t_colon_x = lab_day1_t_colon_x + day_off
+       local lab_day3_x = lab_day2_x + day_off
+       local fld_day3_f_hour_x = fld_day2_f_hour_x + day_off
+       local fld_day3_f_minute_x = fld_day2_f_minute_x + day_off
+       local lab_day3_f_colon_x = lab_day2_f_colon_x + day_off
+       local fld_day3_t_hour_x = fld_day2_t_hour_x + day_off
+       local fld_day3_t_minute_x = fld_day2_t_minute_x + day_off
+       local lab_day3_t_colon_x = lab_day2_t_colon_x + day_off
+       local lab_day4_x = lab_day3_x + day_off
+       local fld_day4_f_hour_x = fld_day3_f_hour_x + day_off
+       local fld_day4_f_minute_x = fld_day3_f_minute_x + day_off
+       local lab_day4_f_colon_x = lab_day3_f_colon_x + day_off
+       local fld_day4_t_hour_x = fld_day3_t_hour_x + day_off
+       local fld_day4_t_minute_x = fld_day3_t_minute_x + day_off
+       local lab_day4_t_colon_x = lab_day3_t_colon_x + day_off
+       local lab_day5_x = lab_day4_x + day_off
+       local fld_day5_f_hour_x = fld_day4_f_hour_x + day_off
+       local fld_day5_f_minute_x = fld_day4_f_minute_x + day_off
+       local lab_day5_f_colon_x = lab_day4_f_colon_x + day_off
+       local fld_day5_t_hour_x = fld_day4_t_hour_x + day_off
+       local fld_day5_t_minute_x = fld_day4_t_minute_x + day_off
+       local lab_day5_t_colon_x = lab_day4_t_colon_x + day_off
+       local below_off = 1.1530125704378
        local lab_b_y = 0.28175119202427
-       local fld_b_y = lab_b_y + time_off
+       local fld_b_y = lab_b_y + below_off
+       local lab_b_colon_y = fld_b_y - inline_off
        local lab_w_y = 2.0156046814044
-       local fld_w_y = lab_w_y + time_off
+       local fld_w_y = lab_w_y + below_off
+       local lab_w_colon_y = fld_w_y - inline_off
        local lab_e_y = 3.7494581707846
-       local fld_e_y = lab_e_y + time_off
+       local fld_e_y = lab_e_y + below_off
+       local lab_e_colon_y = fld_e_y - inline_off
        local o = opening_hours
-       local formspec = "size[10.01,7.9267895878525]"
-       .. "label[-0.14,-0.23840485478977;Öffnungszeiten]"
-       .. "label[" .. lab_day1_x .. "," .. lab_b_y .. ";Mo.-Fr.]"
-       .. "field[" .. fld_day1_f_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_weekday_start;von;" .. o.weekday_start .. "]"
-       .. "field[" .. fld_day1_t_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_weekday_end;bis;" .. o.weekday_end .. "]"
-       .. "label[" .. lab_day1_x .. "," .. lab_w_y .. ";Sa.-So.]"
-       .. "field[" .. fld_day1_f_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_weekend_start;von;" .. o.weekend_start .. "]"
-       .. "field[" .. fld_day1_t_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_weekend_end;bis;" .. o.weekend_end .. "]"
-       .. "label[" .. lab_day1_x .. "," .. lab_e_y .. ";Heute]"
-       .. (o.today
+       local formspec_day1 = ""
+       .. "label[" .. lab_day1_x .. "," .. lab_b_y .. ";Mo.]"
+       .. "field[" .. fld_day1_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_hour;von;" .. string.format("%02d", o.day1_start_hour) .. "]"
+       .. "label[" .. lab_day1_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day1_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_minute;;" .. string.format("%02d", o.day1_start_minute) .. "]"
+       .. "field[" .. fld_day1_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_hour;bis;" .. string.format("%02d", o.day1_end_hour) .. "]"
+       .. "label[" .. lab_day1_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day1_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_minute;;" .. string.format("%02d", o.day1_end_minute) .. "]"
+       local formspec_day2 = ""
+       .. "label[" .. lab_day2_x .. "," .. lab_b_y .. ";Di.]"
+       .. "field[" .. fld_day2_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_start_hour;von;" .. string.format("%02d", o.day2_start_hour) .. "]"
+       .. "label[" .. lab_day2_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day2_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_start_minute;;" .. string.format("%02d", o.day2_start_minute) .. "]"
+       .. "field[" .. fld_day2_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_end_hour;bis;" .. string.format("%02d", o.day2_end_hour) .. "]"
+       .. "label[" .. lab_day2_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day2_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_end_minute;;" .. string.format("%02d", o.day2_end_minute) .. "]"
+       local formspec_day3 = ""
+       .. "label[" .. lab_day3_x .. "," .. lab_b_y .. ";Mi.]"
+       .. "field[" .. fld_day3_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_start_hour;von;" .. string.format("%02d", o.day3_start_hour) .. "]"
+       .. "label[" .. lab_day3_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day3_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_start_minute;;" .. string.format("%02d", o.day3_start_minute) .. "]"
+       .. "field[" .. fld_day3_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_end_hour;bis;" .. string.format("%02d", o.day3_end_hour) .. "]"
+       .. "label[" .. lab_day3_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day3_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_end_minute;;" .. string.format("%02d", o.day3_end_minute) .. "]"
+       local formspec_day4 = ""
+       .. "label[" .. lab_day4_x .. "," .. lab_b_y .. ";Do.]"
+       .. "field[" .. fld_day4_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_start_hour;von;" .. string.format("%02d", o.day4_start_hour) .. "]"
+       .. "label[" .. lab_day4_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day4_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_start_minute;;" .. string.format("%02d", o.day4_start_minute) .. "]"
+       .. "field[" .. fld_day4_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_end_hour;bis;" .. string.format("%02d", o.day4_end_hour) .. "]"
+       .. "label[" .. lab_day4_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day4_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_end_minute;;" .. string.format("%02d", o.day4_end_minute) .. "]"
+       local formspec_day5 = ""
+       .. "label[" .. lab_day5_x .. "," .. lab_b_y .. ";Fr.]"
+       .. "field[" .. fld_day5_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_start_hour;von;" .. string.format("%02d", o.day5_start_hour) .. "]"
+       .. "label[" .. lab_day5_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day5_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_start_minute;;" .. string.format("%02d", o.day5_start_minute) .. "]"
+       .. "field[" .. fld_day5_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_end_hour;bis;" .. string.format("%02d", o.day5_end_hour) .. "]"
+       .. "label[" .. lab_day5_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
+       .. "field[" .. fld_day5_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_end_minute;;" .. string.format("%02d", o.day5_end_minute) .. "]"
+       local formspec_business_days = ""
+       .. formspec_day1
+       .. formspec_day2
+       .. formspec_day3
+       .. formspec_day4
+       .. formspec_day5
+       local formspec_day6 = ""
+       .. "label[" .. lab_day1_x .. "," .. lab_w_y .. ";Sa.]"
+       .. "field[" .. fld_day1_f_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_start_hour;von;" .. string.format("%02d", o.day6_start_hour) .. "]"
+       .. "label[" .. lab_day1_f_colon_x .. "," .. lab_w_colon_y .. ";:]"
+       .. "field[" .. fld_day1_f_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_start_minute;;" .. string.format("%02d", o.day6_start_minute) .. "]"
+       .. "field[" .. fld_day1_t_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_end_hour;bis;" .. string.format("%02d", o.day6_end_hour) .. "]"
+       .. "label[" .. lab_day1_t_colon_x .. "," .. lab_w_colon_y .. ";:]"
+       .. "field[" .. fld_day1_t_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_end_minute;;" .. string.format("%02d", o.day6_end_minute) .. "]"
+       local formspec_day0 = ""
+       .. "label[" .. lab_day2_x .. "," .. lab_w_y .. ";So.]"
+       .. "field[" .. fld_day2_f_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_hour;von;" .. string.format("%02d", o.day0_start_hour) .. "]"
+       .. "label[" .. lab_day2_f_colon_x .. "," .. lab_w_colon_y .. ";:]"
+       .. "field[" .. fld_day2_f_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_minute;;" .. string.format("%02d", o.day0_start_minute) .. "]"
+       .. "field[" .. fld_day2_t_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_hour;bis;" .. string.format("%02d", o.day0_end_hour) .. "]"
+       .. "label[" .. lab_day2_t_colon_x .. "," .. lab_w_colon_y .. ";:]"
+       .. "field[" .. fld_day2_t_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_minute;;" .. string.format("%02d", o.day0_end_minute) .. "]"
+       local formspec_exception = (o.exception_today
                        and ""
-                               .. "field[" .. fld_day1_f_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_today_start;von;" .. o.today_start .. "]"
-                               .. "field[" .. fld_day1_t_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_today_end;bis;" .. o.today_end .. "]"
+                               .. "label[" .. lab_day1_x .. "," .. lab_e_y .. ";Heute]"
+                               .. "field[" .. fld_day1_f_hour_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_hour;von;" .. string.format("%02d", o.exception_start_hour) .. "]"
+                               .. "label[" .. lab_day1_f_colon_x .. "," .. lab_e_colon_y .. ";:]"
+                               .. "field[" .. fld_day1_f_minute_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_minute;;" .. string.format("%02d", o.exception_start_minute) .. "]"
+                               .. "field[" .. fld_day1_t_hour_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_hour;bis;" .. string.format("%02d", o.exception_end_hour) .. "]"
+                               .. "label[" .. lab_day1_t_colon_x .. "," .. lab_e_colon_y .. ";:]"
+                               .. "field[" .. fld_day1_t_minute_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_minute;;" .. string.format("%02d", o.exception_end_minute) .. "]"
                        or "image_button[0.34,4.5296922410056;4.205,0.7835;;add_exception;Ausnahmeregelung hinzufügen]"
                )
+       local formspec = "size[18.01,7.9267895878525]"
+       .. "label[-0.14,-0.23840485478977;Öffnungszeiten]"
+       .. formspec_business_days
+       .. formspec_day6
+       .. formspec_day0
+       .. formspec_exception
        .. "label[" .. lab_day1_x .. ",5.4833116601647;Einstellungen]"
        .. "label[0.34," .. lab_close_y .. ";Spieler ]"
-       .. "field[" .. fld_day1_t_x .. "," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_offset;;" .. o.warn_offset .. "]"
+       .. "field[1.6," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_offset;;" .. o.warn_offset .. "]"
        .. "label[2.18," .. lab_close_y .. ";Minuten vor Ablauf der Zeit alle]"
        .. "field[6.0," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_interval;;" .. o.warn_interval .. "]"
        .. "label[6.6," .. lab_close_y .. ";Minuten warnen.]"
@@ -144,8 +333,41 @@ local function progress_gui_input(player, formname, fields)
                create_exception()
        end
        for k, v in pairs(fields) do
-               if k:sub(1, 4) == "fld_" and tonumber(v) then
-                       opening_hours[k:gsub("fld_", "")] = v
+               if k:sub(1, 4) == "fld_" then
+                       local field = k:gsub("fld_", "")
+                       local old = opening_hours[field]
+                       opening_hours[field] = tonumber(v) or old
+               end
+       end
+       for k, v in pairs(opening_hours) do
+               if k:match("_hour$") then
+                       opening_hours[k] = math.max(0, math.min(23, v))
+               elseif k:match("_minute$") then
+                       opening_hours[k] = math.max(
+                               0,
+                               math.min(
+                                       60 - minute_step,
+                                       minute_step * math.floor(
+                                               v / minute_step + 0.5
+                                       )
+                               )
+                       )
+               end
+       end
+       for k, v in pairs(opening_hours) do
+               if k:match("_end_hour$") then
+                       local start = opening_hours[k:gsub("_end_", "_start_")]
+                       if start > v then
+                               opening_hours[k] = start
+                       end
+               elseif k:match("_end_minute$") then
+                       local hour_k = k:gsub("_minute$", "_hour")
+                       local hour_start_k = hour_k:gsub("_end_", "_start_")
+                       local start_k = k:gsub("_end_", "_start_")
+                       if opening_hours[hour_start_k] >= opening_hours[hour_k]
+                       and opening_hours[start_k] > v then
+                               opening_hours[k] = opening_hours[start_k]
+                       end
                end
        end
        if not fields.quit and not fields.close then show_gui(name) end