]> git.lizzy.rs Git - lmz_opening_hours.git/blob - init.lua
server side translation
[lmz_opening_hours.git] / init.lua
1 local modname = minetest.get_current_modname()
2 local storage = minetest.get_mod_storage()
3 local S = minetest.get_translator("lmz_opening_hours")
4
5 opening_hours = {}
6
7 local opening_hours_default = {
8         version = 2,
9         day0_start_hour = 8,
10         day0_start_minute = 0,
11         day0_end_hour = 21,
12         day0_end_minute = 0,
13         day1_start_hour = 14,
14         day1_start_minute = 0,
15         day1_end_hour = 21,
16         day1_end_minute = 0,
17         day2_start_hour = 14,
18         day2_start_minute = 0,
19         day2_end_hour = 21,
20         day2_end_minute = 0,
21         day3_start_hour = 14,
22         day3_start_minute = 0,
23         day3_end_hour = 21,
24         day3_end_minute = 0,
25         day4_start_hour = 14,
26         day4_start_minute = 0,
27         day4_end_hour = 21,
28         day4_end_minute = 0,
29         day5_start_hour = 14,
30         day5_start_minute = 0,
31         day5_end_hour = 21,
32         day5_end_minute = 0,
33         day6_start_hour = 8,
34         day6_start_minute = 0,
35         day6_end_hour = 21,
36         day6_end_minute = 0,
37         warn_offset = 15,
38         warn_interval = 5
39 }
40
41 local warn_cooldown = 0
42
43 local function get_date()
44         return os.date("*t")
45 end
46
47 local function get_date_formated()
48         return os.date("%d.%m.%y")
49 end
50
51 local function upgrade_configuration(old)
52         local new = {
53                 version = 2,
54                 day0_start_hour = tonumber(old.weekend_start),
55                 day0_start_minute = 0,
56                 day0_end_hour = tonumber(old.weekend_end),
57                 day0_end_minute = 0,
58                 day1_start_hour = tonumber(old.weekday_start),
59                 day1_start_minute = 0,
60                 day1_end_hour = tonumber(old.weekday_end),
61                 day1_end_minute = 0,
62                 day2_start_hour = tonumber(old.weekday_start),
63                 day2_start_minute = 0,
64                 day2_end_hour = tonumber(old.weekday_end),
65                 day2_end_minute = 0,
66                 day3_start_hour = tonumber(old.weekday_start),
67                 day3_start_minute = 0,
68                 day3_end_hour = tonumber(old.weekday_end),
69                 day3_end_minute = 0,
70                 day4_start_hour = tonumber(old.weekday_start),
71                 day4_start_minute = 0,
72                 day4_end_hour = tonumber(old.weekday_end),
73                 day4_end_minute = 0,
74                 day5_start_hour = tonumber(old.weekday_start),
75                 day5_start_minute = 0,
76                 day5_end_hour = tonumber(old.weekday_end),
77                 day5_end_minute = 0,
78                 day6_start_hour = tonumber(old.weekend_start),
79                 day6_start_minute = 0,
80                 day6_end_hour = tonumber(old.weekend_end),
81                 day6_end_minute = 0,
82                 warn_offset = tonumber(old.warn_offset),
83                 warn_interval = tonumber(old.warn_interval)
84         }
85         if old.today then
86                 new.exception_today = old.today
87                 new.exception_start_hour = old.today_start
88                 new.exception_start_minute = 0
89                 new.exception_end_hour = old.today_end
90                 new.exception_end_minute = 0
91         end
92         return new
93 end
94
95 local function save_data()
96         storage:from_table({fields = opening_hours})
97 end
98
99 local function load_data()
100         opening_hours = storage:to_table().fields
101         if opening_hours.weekday_start then
102                 opening_hours = upgrade_configuration(opening_hours)
103         elseif not opening_hours.version then
104                 opening_hours = opening_hours_default
105         end
106         for k, v in pairs(opening_hours) do
107                 if k ~= "exception_today" then
108                         opening_hours[k] = tonumber(v)
109                 end
110         end
111 end
112
113 local function reset_execption()
114         opening_hours.exception_today = nil
115 end
116
117 local function opening_today()
118         local exception = opening_hours.exception_today
119         local day_key
120         if exception and exception == get_date_formated() then
121                 day_key = "exception"
122         else
123                 local d = os.date("%w")
124                 day_key = "day" .. d
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", S("The server will close in @1 minutes.", minutes_remaining)))
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, S("The server is closing!"))
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 S("You visited outside of the opening hours") .. ". " .. S("The server will open again in @1 hours", math.ceil(diff / 60)) .. "."
181         elseif end_time <= now_time then
182                 return S("You visited outside of the opening hours") .. ". " .. S("The server has already closed and will open again tomorrow") .. "."
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 pre_colon_off = 0.4
196         local minute_off = 0.04
197         local to_off = 1.24
198         local day_off = 3.6
199         local x = {
200                 day1 = {}
201         }
202         x.day1.lab = 0.1
203         x.day1.fld_f_hour = 0.64
204         x.day1.fld_f_minute = x.day1.fld_f_hour + fld_w - minute_off
205         x.day1.lab_f_colon = x.day1.fld_f_minute - pre_colon_off
206         x.day1.fld_t_hour = x.day1.lab_f_colon + to_off
207         x.day1.fld_t_minute = x.day1.fld_t_hour + fld_w - minute_off
208         x.day1.lab_t_colon = x.day1.fld_t_minute - pre_colon_off
209         local last
210         for day = 1, 5, 1 do
211                 if last then
212                         x["day" .. day] = {}
213                         for k, v in pairs(x["day" .. last]) do
214                                 x["day" .. day][k] = v + day_off
215                         end
216                 end
217                 last = day
218         end
219         local below_off = 1.1530125704378
220         local lab_b_y = 0.28175119202427
221         local fld_b_y = lab_b_y + below_off
222         local lab_b_colon_y = fld_b_y - inline_off
223         local lab_w_y = 2.0156046814044
224         local fld_w_y = lab_w_y + below_off
225         local lab_w_colon_y = fld_w_y - inline_off
226         local lab_e_y = 3.7494581707846
227         local fld_e_y = lab_e_y + below_off
228         local lab_e_colon_y = fld_e_y - inline_off
229         local o = opening_hours
230         local day_abbreviations = {
231                 [0] = S("Su."),
232                 [1] = S("Mo."),
233                 [2] = S("Tu."),
234                 [3] = S("We."),
235                 [4] = S("Th."),
236                 [5] = S("Fr."),
237                 [6] = S("Sa.")
238         }
239         local player_info = minetest.get_player_information(name)
240         local warning_config_translation_string = S(
241                 "@1 minutes before closing, warn the players every @2 minutes.",
242                 "<warn_offset>",
243                 "<warn_interval>"
244         )
245         local warning_config = minetest.get_translated_string(
246                 player_info.lang_code,
247                 warning_config_translation_string
248         ) .. "<"
249         local formspec_warning = ""
250         local warning_x = 0.34
251         for fragment in warning_config:gmatch("([^<>]+<?)") do
252                 local label = fragment:match("<$")
253                 if label then
254                         fragment = fragment:gsub("<$", "")
255                 end
256                 if label then
257                         formspec_warning = formspec_warning ..
258                         "label[" .. warning_x .. "," .. lab_close_y .. ";" .. fragment .. "]"
259                         warning_x = warning_x + 0.125 * fragment:len()
260                 else
261                         formspec_warning = formspec_warning ..
262                         "field[" .. (warning_x + 0.2) .. "," .. fld_close_y .. ";" .. fld_sz .. ";fld_" .. fragment .. ";;" .. o[fragment] .. "]"
263                         warning_x = warning_x + 0.6
264                 end
265         end
266         local formspec_business_days = ""
267         for day = 1, 5, 1 do
268                 formspec_business_days = formspec_business_days
269                 .. "label[" .. x["day" .. day].lab .. "," .. lab_b_y .. ";" .. day_abbreviations[day] .. "]"
270                 .. "field[" .. x["day" .. day].fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_start_hour;" .. S("from") .. ";" .. string.format("%02d", o["day" .. day .. "_start_hour"]) .. "]"
271                 .. "label[" .. x["day" .. day].lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
272                 .. "field[" .. x["day" .. day].fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_start_minute;;" .. string.format("%02d", o["day" .. day .. "_start_minute"]) .. "]"
273                 .. "field[" .. x["day" .. day].fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_end_hour;" .. S("to") .. ";" .. string.format("%02d", o["day" .. day .. "_end_hour"]) .. "]"
274                 .. "label[" .. x["day" .. day].lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
275                 .. "field[" .. x["day" .. day].fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_end_minute;;" .. string.format("%02d", o["day" .. day .. "_end_minute"]) .. "]"
276         end
277         local formspec_weekend = ""
278         for col = 1, 2, 1 do
279                 local day = (5 + col) % 7
280                 formspec_weekend = formspec_weekend
281                 .. "label[" .. x["day" .. col].lab .. "," .. lab_w_y .. ";" .. day_abbreviations[day] .. "]"
282                 .. "field[" .. x["day" .. col].fld_f_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_start_hour;" .. S("from") .. ";" .. string.format("%02d", o["day" .. day .. "_start_hour"]) .. "]"
283                 .. "label[" .. x["day" .. col].lab_f_colon .. "," .. lab_w_colon_y .. ";:]"
284                 .. "field[" .. x["day" .. col].fld_f_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_start_minute;;" .. string.format("%02d", o["day" .. day .. "_start_minute"]) .. "]"
285                 .. "field[" .. x["day" .. col].fld_t_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_end_hour;" .. S("to") .. ";" .. string.format("%02d", o["day" .. day .. "_end_hour"]) .. "]"
286                 .. "label[" .. x["day" .. col].lab_t_colon .. "," .. lab_w_colon_y .. ";:]"
287                 .. "field[" .. x["day" .. col].fld_t_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day" .. day .. "_end_minute;;" .. string.format("%02d", o["day" .. day .. "_end_minute"]) .. "]"
288         end
289         local formspec_exception = (o.exception_today
290                         and ""
291                                 .. "label[" .. x.day1.lab .. "," .. lab_e_y .. ";" .. S("Today") .. "]"
292                                 .. "field[" .. x.day1.fld_f_hour .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_hour;" .. S("from") .. ";" .. string.format("%02d", o.exception_start_hour) .. "]"
293                                 .. "label[" .. x.day1.lab_f_colon .. "," .. lab_e_colon_y .. ";:]"
294                                 .. "field[" .. x.day1.fld_f_minute .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_minute;;" .. string.format("%02d", o.exception_start_minute) .. "]"
295                                 .. "field[" .. x.day1.fld_t_hour .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_hour;" .. S("to") .. ";" .. string.format("%02d", o.exception_end_hour) .. "]"
296                                 .. "label[" .. x.day1.lab_t_colon .. "," .. lab_e_colon_y .. ";:]"
297                                 .. "field[" .. x.day1.fld_t_minute .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_minute;;" .. string.format("%02d", o.exception_end_minute) .. "]"
298                         or "image_button[0.34,4.5296922410056;4.205,0.7835;;add_exception;" .. S("Add exception") .. "]"
299                 )
300         local formspec = "size[18.01,7.9267895878525]"
301         .. "label[-0.14,-0.23840485478977;" .. S("Opening hours") .. "]"
302         .. formspec_business_days
303         .. formspec_weekend
304         .. formspec_exception
305         .. "label[" .. x.day1.lab .. ",5.4833116601647;" .. S("Settings") .. "]"
306         .. formspec_warning
307         .. "image_button[5.14,7.6072821846554;2.605,0.7835;;save;" .. S("Save") .. "]"
308         .. "image_button_exit[7.62,7.6072821846554;2.605,0.7835;;close;" .. S("Close") .. "]"
309         minetest.show_formspec(name, "lmz_opening_hours:gui", formspec)
310 end
311
312 local function progress_gui_input(player, formname, fields)
313         local name = player:get_player_name()
314         if formname ~= "lmz_opening_hours:gui" or not minetest.check_player_privs(name, {server = true}) then return end
315         if fields.add_exception then
316                 create_exception()
317         end
318         for k, v in pairs(fields) do
319                 if k:sub(1, 4) == "fld_" then
320                         local field = k:gsub("fld_", "")
321                         local old = opening_hours[field]
322                         opening_hours[field] = tonumber(v) or old
323                 end
324         end
325         for k, v in pairs(opening_hours) do
326                 if k:match("_hour$") then
327                         opening_hours[k] = math.max(0, math.min(23, v))
328                 elseif k:match("_minute$") then
329                         opening_hours[k] = math.max(
330                                 0,
331                                 math.min(
332                                         60 - minute_step,
333                                         minute_step * math.floor(
334                                                 v / minute_step + 0.5
335                                         )
336                                 )
337                         )
338                 end
339         end
340         for k, v in pairs(opening_hours) do
341                 if k:match("_end_hour$") then
342                         local start = opening_hours[k:gsub("_end_", "_start_")]
343                         if start > v then
344                                 opening_hours[k] = start
345                         end
346                 elseif k:match("_end_minute$") then
347                         local hour_k = k:gsub("_minute$", "_hour")
348                         local hour_start_k = hour_k:gsub("_end_", "_start_")
349                         local start_k = k:gsub("_end_", "_start_")
350                         if opening_hours[hour_start_k] >= opening_hours[hour_k]
351                         and opening_hours[start_k] > v then
352                                 opening_hours[k] = opening_hours[start_k]
353                         end
354                 end
355         end
356         if not fields.quit and not fields.close then show_gui(name) end
357 end
358
359 load_data()
360
361 minetest.register_globalstep(tick)
362 minetest.register_on_shutdown(save_data)
363 minetest.register_on_prejoinplayer(on_join)
364 minetest.register_chatcommand(
365         "opening_hours",
366         {
367                 privs = {server = true},
368                 description = S("Configure the opening hours"),
369                 func = show_gui
370         }
371 )
372 minetest.register_chatcommand(
373         "öffnungszeiten",
374         {
375                 privs = {server = true},
376                 description = S("Configure the opening hours"),
377                 func = show_gui
378         }
379 )
380 minetest.register_on_player_receive_fields(progress_gui_input)
381
382