Stopwatch function to SmartLine Controller added

This commit is contained in:
Joachim Stolberg 2018-09-26 19:24:39 +02:00
parent 58ed780c13
commit 9a1ad7349f
5 changed files with 207 additions and 20 deletions

@ -182,10 +182,15 @@ function lcdlib.make_multiline_texture(font_name, text, width, height,
local lines = {} local lines = {}
local textheight = 0 local textheight = 0
local y, w, h local y, w, h
h = get_font(font_name).height
for num, line in pairs(split_lines(text, maxlines)) do for num, line in pairs(split_lines(text, maxlines)) do
w, h = lcdlib.get_text_size(font_name, line) if line:byte(1) == 60 then -- '<'
lines[num] = { text = line, width = w, height = h, } lines[num] = { text = line:sub(2,-1), width = width - 4, height = h, }
else
w, h = lcdlib.get_text_size(font_name, line)
lines[num] = { text = line, width = w, height = h, }
end
textheight = textheight + h textheight = textheight + h
end end

@ -2,6 +2,17 @@
## V1.16.4 (2018-09-26)
### Additions
- Stopwatch function to SmartLine Controller added
- Display supports now left oriented text outputs via prefix '<'
### Fixes
- Owner bugfix for the SmartLine Controller
## V1.16.3 (2018-09-26) ## V1.16.3 (2018-09-26)

@ -39,7 +39,7 @@ local function integer(s, min, max)
return min return min
end end
local sOUTPUT = "Edit commands" local sOUTPUT = "Edit commands (see help)"
local Cache = {} local Cache = {}
local FS_DATA = gen_table(smartline.NUM_RULES, {}) local FS_DATA = gen_table(smartline.NUM_RULES, {})
@ -71,6 +71,22 @@ end
-- env.blocked[1] = false -- env.blocked[1] = false
-- end -- end
-- -- Callback variant
-- if env.blocked[1] == false and env.ticks % <cycle> == 0 then
-- env.result[1], env.blocked[1] = <callback>
-- if env.blocked[1] then
-- env.timer[1] = env.ticks + <after>
-- end
-- env.conditions[1] = env.blocked[1]
-- else
-- env.conditions[1] = false
-- end
-- if env.blocked[1] and env.timer[1] == env.ticks then
-- <action>
-- env.blocked[1] = false
-- end
-- cyclic execution -- cyclic execution
local TemplCyc = [[ local TemplCyc = [[
-- Rule # -- Rule #
@ -109,6 +125,24 @@ if env.blocked[#] and env.timer[#] == env.ticks then
end end
]] ]]
-- event based execution of callback function
local TemplEvtClbk = [[
-- Rule #
if env.blocked[#] == false and env.event then
env.result[#], env.blocked[#] = %s(env, %s)
if env.blocked[#] then
env.timer[#] = env.ticks + %s
end
env.condition[#] = env.blocked[#]
else
env.condition[#] = false
end
if env.blocked[#] and env.timer[#] == env.ticks then
%s
env.blocked[#] = false
end
]]
-- generate the Lua code from the NUM_RULES rules -- generate the Lua code from the NUM_RULES rules
local function generate(pos, meta, environ) local function generate(pos, meta, environ)
local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
@ -124,7 +158,12 @@ local function generate(pos, meta, environ)
-- add rule number -- add rule number
local s local s
if cycle == 0 then -- event? if cycle == 0 then -- event?
s = string.format(TemplEvt, cond, result, after, actn) if result then
s = string.format(TemplEvt, cond, result, after, actn)
else -- callback function
local data = dump(fs_data[idx].cond)
s = string.format(TemplEvtClbk, cond, data, after, actn)
end
else -- cyclic else -- cyclic
s = string.format(TemplCyc, cycle, cond, result, after, actn) s = string.format(TemplCyc, cycle, cond, result, after, actn)
end end
@ -216,7 +255,8 @@ local function start_controller(pos, meta)
if compile(pos, meta, number) then if compile(pos, meta, number) then
meta:set_int("state", tubelib.RUNNING) meta:set_int("state", tubelib.RUNNING)
minetest.get_node_timer(pos):start(1) minetest.get_node_timer(pos):start(1)
meta:set_string("formspec", smartline.formspecOutput(meta)) local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
meta:set_string("formspec", smartline.formspecRules(meta, fs_data, sOUTPUT))
meta:set_string("infotext", "Controller "..number..": running") meta:set_string("infotext", "Controller "..number..": running")
return true return true
end end
@ -280,7 +320,9 @@ local function on_receive_fields(pos, formname, fields, player)
if not player or not player:is_player() then if not player or not player:is_player() then
return return
end end
local readonly = player:get_player_name() ~= owner if player:get_player_name() ~= owner then
return
end
--print("fields", dump(fields)) --print("fields", dump(fields))
if fields.quit then -- cancel button if fields.quit then -- cancel button
@ -290,18 +332,14 @@ local function on_receive_fields(pos, formname, fields, player)
meta:set_string("notes", fields.notes) meta:set_string("notes", fields.notes)
end end
if fields.go then if fields.go then
if not readonly then local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA
local fs_data = minetest.deserialize(meta:get_string("fs_data")) or FS_DATA local output = smartline.edit_command(fs_data, fields.cmnd)
local output = smartline.edit_command(fs_data, fields.cmnd) stop_controller(pos, meta)
stop_controller(pos, meta) meta:set_string("formspec", smartline.formspecRules(meta, fs_data, output))
meta:set_string("formspec", smartline.formspecRules(meta, fs_data, output)) meta:set_string("fs_data", minetest.serialize(fs_data))
meta:set_string("fs_data", minetest.serialize(fs_data))
end
end end
if fields._type_ == "main" then if fields._type_ == "main" then
if not readonly then smartline.store_main_form_data(meta, fields)
smartline.store_main_form_data(meta, fields)
end
local key = smartline.main_form_button_pressed(fields) local key = smartline.main_form_button_pressed(fields)
if key then if key then
-- store data before going into sub-menu -- store data before going into sub-menu
@ -438,9 +476,10 @@ minetest.register_craft({
local function set_input(pos, own_number, rmt_number, val) local function set_input(pos, own_number, rmt_number, val)
if rmt_number then if rmt_number then
if Cache[own_number] and Cache[own_number].env.input then if Cache[own_number] and Cache[own_number].env.input then
Cache[own_number].env.input[rmt_number] = val
-- only two events per second
local t = minetest.get_us_time() local t = minetest.get_us_time()
Cache[own_number].env.input[rmt_number] = val
Cache[own_number].env.last_event = t
-- only two events per second
if not Cache[own_number].last_event or Cache[own_number].last_event < t then if not Cache[own_number].last_event or Cache[own_number].last_event < t then
minetest.after(0.01, on_timer, pos, -1) minetest.after(0.01, on_timer, pos, -1)
Cache[own_number].last_event = t + 500000 -- add 500 ms Cache[own_number].last_event = t + 500000 -- add 500 ms
@ -453,10 +492,11 @@ tubelib.register_node("smartline:controller2", {}, {
on_recv_message = function(pos, topic, payload) on_recv_message = function(pos, topic, payload)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local number = meta:get_string("number") local number = meta:get_string("number")
local state = meta:get_int("state")
if topic == "on" then if state == tubelib.RUNNING and topic == "on" then
set_input(pos, number, payload, topic) set_input(pos, number, payload, topic)
elseif topic == "off" then elseif state == tubelib.RUNNING and topic == "off" then
set_input(pos, number, payload, topic) set_input(pos, number, payload, topic)
elseif topic == "state" then elseif topic == "state" then
local state = meta:get_int("state") local state = meta:get_int("state")

@ -0,0 +1,130 @@
--[[
ICTA Controller
===============
Part of the SmartLine mod
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
stopwatch.lua
Start/stop the watch with an on/off commands.
The player name clicking the stop is stored in addition.
]]--
local sl = smartline
local function retrieve_clicker_name(number)
local pos = tubelib.get_node_info(number).pos
if pos then
local meta = minetest.get_meta(pos)
return meta:get_string("clicker_name") or "<unknown>"
end
return "<error>"
end
-- env = {
-- event = <bool>,
-- last_event = <number> -- last event time
-- ticks = <number,
-- pos = <pos>,
-- timer = gen_table(8, 0),
-- blocked = gen_table(8, false),
-- result = gen_table(8, false),
-- condition = gen_table(8, false),
-- input = <table>, -- node number is key
-- number = <number>,
-- owner = <string>,
-- },
--
-- return cond_result, trigger_action
function smartline.stopwatch(env, data)
if env.input[data.number] == "on" then
env.time = env.last_event
if not env.highscore then
env.highscore = 99999
end
return nil, false
else
local time = (env.last_event - env.time) / 1000000
local name = retrieve_clicker_name(data.number)
env.highscore = math.min(time, env.highscore)
local s1 = string.format("%2.1f s", time)
local s2 = string.format("%2.1f s", env.highscore)
env.stopwatch_result = {s1, s2, name}
return nil, true
end
end
smartline.icta_register_condition("stopwatch", {
title = "stopwatch",
formspec = {
{
type = "numbers",
name = "number",
label = "Switch number",
default = "",
},
{
type = "label",
name = "lbl",
label = "Hint: Stop the time between switching on\nand switching off of the connected switch.",
},
},
code = function(data, environ)
return "smartline.stopwatch"
end,
button = function(data, environ)
return 'stopwatch('..sl.fmt_number(data.number)..')'
end,
})
smartline.icta_register_action("stopwatch", {
title = "stopwatch",
formspec = {
{
type = "numbers",
name = "number",
label = "Display number",
default = "",
},
{
type = "textlist",
name = "row",
label = "Display line",
choices = "1,2,3,4,5,6,7,8,9",
default = "1",
},
{
type = "ascii",
name = "text",
label = "label",
default = "",
},
{
type = "textlist",
name = "type",
label = "type",
choices = "time,highscore,name",
default = "time",
},
{
type = "label",
name = "lbl",
label = "Hint: Display number for the output\nof time, highscore and player name.",
},
},
button = function(data, environ)
return "lcd("..sl.fmt_number(data.number)..","..data.row..","..data.type..')'
end,
code = function(data, environ)
local idx = ({time=1, highscore= 2, name=3})[data.type]
local s1 = string.format('local payload = {row = %s, str = "%s "..env.stopwatch_result['..idx..']}', data.row, smartline.escape(data.text))
local s2 = string.format('tubelib.send_message("%s", "%s", nil, "row", payload)', data.number, environ.owner)
return s1.."\n\t"..s2
end,
})

@ -33,3 +33,4 @@ dofile(MP.."/icta/commands.lua")
dofile(MP.."/icta/edit.lua") dofile(MP.."/icta/edit.lua")
dofile(MP.."/icta/battery.lua") dofile(MP.."/icta/battery.lua")
dofile(MP.."/icta/balancer.lua") dofile(MP.."/icta/balancer.lua")
dofile(MP.."/icta/stopwatch.lua")