]> git.lizzy.rs Git - lmz_opening_hours.git/blob - init.lua
apply minute granularity
[lmz_opening_hours.git] / init.lua
1 local modname = minetest.get_current_modname()
2 local storage = minetest.get_mod_storage()
3
4 opening_hours = {}
5
6 local opening_hours_default = {
7         version = 2,
8         day0_start_hour = 8,
9         day0_start_minute = 0,
10         day0_end_hour = 21,
11         day0_end_minute = 0,
12         day1_start_hour = 14,
13         day1_start_minute = 0,
14         day1_end_hour = 21,
15         day1_end_minute = 0,
16         day2_start_hour = 14,
17         day2_start_minute = 0,
18         day2_end_hour = 21,
19         day2_end_minute = 0,
20         day3_start_hour = 14,
21         day3_start_minute = 0,
22         day3_end_hour = 21,
23         day3_end_minute = 0,
24         day4_start_hour = 14,
25         day4_start_minute = 0,
26         day4_end_hour = 21,
27         day4_end_minute = 0,
28         day5_start_hour = 14,
29         day5_start_minute = 0,
30         day5_end_hour = 21,
31         day5_end_minute = 0,
32         day6_start_hour = 8,
33         day6_start_minute = 0,
34         day6_end_hour = 21,
35         day6_end_minute = 0,
36         warn_offset = 15,
37         warn_interval = 5
38 }
39
40 local warn_cooldown = 0
41
42 local function get_date()
43         return os.date("*t")
44 end
45
46 local function get_date_formated()
47         return os.date("%d.%m.%y")
48 end
49
50 local function is_weekend()
51         local d = os.date("%w")
52         return d == "0" or d == "6"
53 end
54
55 local function upgrade_configuration(old)
56         local new = {
57                 version = 2,
58                 day0_start_hour = tonumber(old.weekend_start),
59                 day0_start_minute = 0,
60                 day0_end_hour = tonumber(old.weekend_end),
61                 day0_end_minute = 0,
62                 day1_start_hour = tonumber(old.weekday_start),
63                 day1_start_minute = 0,
64                 day1_end_hour = tonumber(old.weekday_end),
65                 day1_end_minute = 0,
66                 day2_start_hour = tonumber(old.weekday_start),
67                 day2_start_minute = 0,
68                 day2_end_hour = tonumber(old.weekday_end),
69                 day2_end_minute = 0,
70                 day3_start_hour = tonumber(old.weekday_start),
71                 day3_start_minute = 0,
72                 day3_end_hour = tonumber(old.weekday_end),
73                 day3_end_minute = 0,
74                 day4_start_hour = tonumber(old.weekday_start),
75                 day4_start_minute = 0,
76                 day4_end_hour = tonumber(old.weekday_end),
77                 day4_end_minute = 0,
78                 day5_start_hour = tonumber(old.weekday_start),
79                 day5_start_minute = 0,
80                 day5_end_hour = tonumber(old.weekday_end),
81                 day5_end_minute = 0,
82                 day6_start_hour = tonumber(old.weekend_start),
83                 day6_start_minute = 0,
84                 day6_end_hour = tonumber(old.weekend_end),
85                 day6_end_minute = 0,
86                 warn_offset = tonumber(old.warn_offset),
87                 warn_interval = tonumber(old.warn_interval)
88         }
89         if old.today then
90                 new.exception_today = old.today
91                 new.exception_start_hour = old.today_start
92                 new.exception_start_minute = 0
93                 new.exception_end_hour = old.today_end
94                 new.exception_end_minute = 0
95         end
96         return new
97 end
98
99 local function save_data()
100         storage:from_table({fields = opening_hours})
101 end
102
103 local function load_data()
104         opening_hours = storage:to_table().fields
105         if opening_hours.weekday_start then
106                 opening_hours = upgrade_configuration(opening_hours)
107         elseif not opening_hours.version then
108                 opening_hours = opening_hours_default
109         end
110 end
111
112 local function reset_execption()
113         opening_hours.exception_today = nil
114 end
115
116 local function opening_today()
117         local exception = opening_hours.exception_today
118         local day_key
119         if exception and exception == get_date_formated() then
120                 day_key = "exception"
121         elseif is_weekend() then
122                 day_key = "day0"
123         else
124                 day_key = "day1"
125         end
126         return {
127                 start_hour = opening_hours[day_key .. "_start_hour"],
128                 start_minute = opening_hours[day_key .. "_start_minute"],
129                 end_hour = opening_hours[day_key .. "_end_hour"],
130                 end_minute = opening_hours[day_key .. "_end_minute"]
131         }
132 end
133
134 local function create_exception()
135         local today = opening_today()
136         opening_hours.exception_today = get_date_formated()
137         opening_hours.exception_start_hour = today.start_hour
138         opening_hours.exception_start_minute = today.start_minute
139         opening_hours.exception_end_hour = today.end_hour
140         opening_hours.exception_end_minute = today.end_minute
141 end
142
143 local function tick(dtime)
144         local d = get_date()
145         local exception = opening_hours.exception_today
146         if exception and exception ~= get_date_formated() then
147                 reset_execption()
148         end
149         local today = opening_today()
150         local end_time = today.end_hour * 60 + today.end_minute
151         local now_time = d.hour * 60 + d.min
152         local minutes_remaining = end_time - now_time
153         if 0 < minutes_remaining
154         and minutes_remaining <= opening_hours.warn_offset then
155                 if warn_cooldown <= 0 then
156                         minetest.chat_send_all(minetest.colorize("#FF4D00", "Der Server schießt in " .. minutes_remaining .. " Minuten."))
157                         warn_cooldown = tonumber(opening_hours.warn_interval) * 60
158                 else
159                         warn_cooldown = warn_cooldown - dtime
160                 end
161         elseif minutes_remaining <= 0 then
162                 for _, player in pairs(minetest.get_connected_players()) do
163                         local name = player:get_player_name()
164                         if not minetest.check_player_privs(name, {server = true}) then
165                                 minetest.kick_player(name, "Der Server schließt!")
166                         end
167                 end
168         end
169 end
170
171 local function on_join(name)
172         if minetest.check_player_privs(name, {server = true}) then return end
173         local today = opening_today()
174         local d = get_date()
175         local start_time = today.start_hour * 60 + today.start_minute
176         local end_time = today.end_hour * 60 + today.end_minute
177         local now_time = d.hour * 60 + d.min
178         local diff = start_time - now_time
179         if diff > 0 then
180                 return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat in " .. math.ceil(diff / 60) .. " Stunde(n) wieder geöffnet."
181         elseif end_time <= now_time then
182                 return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat bereits geschlossen und hat Morgen wieder geöffnet."
183         end
184 end
185
186 local minute_step = 5
187
188 local function show_gui(name)
189         local fld_w = 0.88
190         local fld_h = 0.82429501084599
191         local fld_sz = fld_w .. "," .. fld_h
192         local inline_off = 0.2427394885132
193         local lab_close_y = 6.3935847420893
194         local fld_close_y = lab_close_y + 0.2427394885132
195         local lab_day1_x = 0.1
196         local pre_colon_off = 0.4
197         local fld_day1_f_hour_x = 0.64
198         local minute_off = 0.04
199         local to_off = 1.24
200         local fld_day1_f_minute_x = fld_day1_f_hour_x + fld_w - minute_off
201         local lab_day1_f_colon_x = fld_day1_f_minute_x - pre_colon_off
202         local fld_day1_t_hour_x = lab_day1_f_colon_x + to_off
203         local fld_day1_t_minute_x = fld_day1_t_hour_x + fld_w - minute_off
204         local lab_day1_t_colon_x = fld_day1_t_minute_x - pre_colon_off
205         local below_off = 1.1530125704378
206         local lab_b_y = 0.28175119202427
207         local fld_b_y = lab_b_y + below_off
208         local lab_b_colon_y = fld_b_y - inline_off
209         local lab_w_y = 2.0156046814044
210         local fld_w_y = lab_w_y + below_off
211         local lab_w_colon_y = fld_w_y - inline_off
212         local lab_e_y = 3.7494581707846
213         local fld_e_y = lab_e_y + below_off
214         local lab_e_colon_y = fld_e_y - inline_off
215         local o = opening_hours
216         local formspec = "size[10.01,7.9267895878525]"
217         .. "label[-0.14,-0.23840485478977;Öffnungszeiten]"
218         .. "label[" .. lab_day1_x .. "," .. lab_b_y .. ";Mo.-Fr.]"
219         .. "field[" .. fld_day1_f_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_hour;von;" .. string.format("%02d", o.day1_start_hour) .. "]"
220         .. "label[" .. lab_day1_f_colon_x .. "," .. lab_b_colon_y .. ";:]"
221         .. "field[" .. fld_day1_f_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_minute;;" .. string.format("%02d", o.day1_start_minute) .. "]"
222         .. "field[" .. fld_day1_t_hour_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_hour;bis;" .. string.format("%02d", o.day1_end_hour) .. "]"
223         .. "label[" .. lab_day1_t_colon_x .. "," .. lab_b_colon_y .. ";:]"
224         .. "field[" .. fld_day1_t_minute_x .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_minute;;" .. string.format("%02d", o.day1_end_minute) .. "]"
225         .. "label[" .. lab_day1_x .. "," .. lab_w_y .. ";Sa.-So.]"
226         .. "field[" .. fld_day1_f_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_hour;von;" .. string.format("%02d", o.day0_start_hour) .. "]"
227         .. "label[" .. lab_day1_f_colon_x .. "," .. lab_w_colon_y .. ";:]"
228         .. "field[" .. fld_day1_f_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_minute;;" .. string.format("%02d", o.day0_start_minute) .. "]"
229         .. "field[" .. fld_day1_t_hour_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_hour;bis;" .. string.format("%02d", o.day0_end_hour) .. "]"
230         .. "label[" .. lab_day1_t_colon_x .. "," .. lab_w_colon_y .. ";:]"
231         .. "field[" .. fld_day1_t_minute_x .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_minute;;" .. string.format("%02d", o.day0_end_minute) .. "]"
232         .. "label[" .. lab_day1_x .. "," .. lab_e_y .. ";Heute]"
233         .. (o.exception_today
234                         and ""
235                                 .. "field[" .. fld_day1_f_hour_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_hour;von;" .. string.format("%02d", o.exception_start_hour) .. "]"
236                                 .. "label[" .. lab_day1_f_colon_x .. "," .. lab_e_colon_y .. ";:]"
237                                 .. "field[" .. fld_day1_f_minute_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_minute;;" .. string.format("%02d", o.exception_start_minute) .. "]"
238                                 .. "field[" .. fld_day1_t_hour_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_hour;bis;" .. string.format("%02d", o.exception_end_hour) .. "]"
239                                 .. "label[" .. lab_day1_t_colon_x .. "," .. lab_e_colon_y .. ";:]"
240                                 .. "field[" .. fld_day1_t_minute_x .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_minute;;" .. string.format("%02d", o.exception_end_minute) .. "]"
241                         or "image_button[0.34,4.5296922410056;4.205,0.7835;;add_exception;Ausnahmeregelung hinzufügen]"
242                 )
243         .. "label[" .. lab_day1_x .. ",5.4833116601647;Einstellungen]"
244         .. "label[0.34," .. lab_close_y .. ";Spieler ]"
245         .. "field[1.6," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_offset;;" .. o.warn_offset .. "]"
246         .. "label[2.18," .. lab_close_y .. ";Minuten vor Ablauf der Zeit alle]"
247         .. "field[6.0," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_interval;;" .. o.warn_interval .. "]"
248         .. "label[6.6," .. lab_close_y .. ";Minuten warnen.]"
249         .. "image_button[5.14,7.6072821846554;2.605,0.7835;;save;Speichern]"
250         .. "image_button_exit[7.62,7.6072821846554;2.605,0.7835;;close;Schließen]"
251         minetest.show_formspec(name, "lmz_opening_hours:gui", formspec)
252 end
253
254 local function progress_gui_input(player, formname, fields)
255         local name = player:get_player_name()
256         if formname ~= "lmz_opening_hours:gui" or not minetest.check_player_privs(name, {server = true}) then return end
257         if fields.add_exception then
258                 create_exception()
259         end
260         for k, v in pairs(fields) do
261                 if k:sub(1, 4) == "fld_" then
262                         local field = k:gsub("fld_", "")
263                         local old = opening_hours[field]
264                         opening_hours[field] = tonumber(v) or old
265                 end
266         end
267         for k, v in pairs(opening_hours) do
268                 if k:match("_hour$") then
269                         opening_hours[k] = math.max(0, math.min(23, v))
270                 elseif k:match("_minute$") then
271                         opening_hours[k] = math.max(
272                                 0,
273                                 math.min(
274                                         60 - minute_step,
275                                         minute_step * math.floor(
276                                                 v / minute_step + 0.5
277                                         )
278                                 )
279                         )
280                 end
281         end
282         for k, v in pairs(opening_hours) do
283                 if k:match("_end_hour$") then
284                         local start = opening_hours[k:gsub("_end_", "_start_")]
285                         if start > v then
286                                 opening_hours[k] = start
287                         end
288                 elseif k:match("_end_minute$") then
289                         local hour_k = k:gsub("_minute$", "_hour")
290                         local hour_start_k = hour_k:gsub("_end_", "_start_")
291                         local start_k = k:gsub("_end_", "_start_")
292                         if opening_hours[hour_start_k] >= opening_hours[hour_k]
293                         and opening_hours[start_k] > v then
294                                 opening_hours[k] = opening_hours[start_k]
295                         end
296                 end
297         end
298         if not fields.quit and not fields.close then show_gui(name) end
299 end
300
301 load_data()
302
303 minetest.register_globalstep(tick)
304 minetest.register_on_shutdown(save_data)
305 minetest.register_on_prejoinplayer(on_join)
306 minetest.register_chatcommand("opening_hours", {privs = {server = true}, description = "Die Öffnungszeiten konfigurieren", func = show_gui})
307 minetest.register_chatcommand("öffnungszeiten", {privs = {server = true}, description = "Die Öffnungszeiten konfigurieren", func = show_gui})
308 minetest.register_on_player_receive_fields(progress_gui_input)
309
310