Merge branch 'interaction-nested-functions' into 'master'
Moved code over to nested function approach, working See merge request medlabboulder/modpol!27
This commit is contained in:
commit
fa4283dce6
@ -9,22 +9,46 @@ modpol.interactions = {}
|
|||||||
-- DASHBOARDS
|
-- DASHBOARDS
|
||||||
-- ==========
|
-- ==========
|
||||||
|
|
||||||
-- Function: modpol.dashboard(user)
|
function modpol.interactions.login()
|
||||||
|
print("Log in as which user?")
|
||||||
|
local username = io.read()
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local org = modpol.interactions.dashboard(username)
|
||||||
|
if org then
|
||||||
|
modpol.interactions.org_dashboard(username, org)
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function: modpol.interactions.dashboard(user)
|
||||||
-- Params: user (string)
|
-- Params: user (string)
|
||||||
-- Q: Should this return a menu of commands relevant to the specific user?
|
-- Q: Should this return a menu of commands relevant to the specific user?
|
||||||
-- Output: Displays a menu of commands to the user
|
-- Output: Displays a menu of commands to the user
|
||||||
-- TKTK currently just prints all of modpol---needs major improvement
|
-- TKTK currently just prints all of modpol---needs major improvement
|
||||||
function modpol.dashboard(user)
|
function modpol.interactions.dashboard(user)
|
||||||
local output = ""
|
print()
|
||||||
-- Org status
|
local org_list = modpol.orgs.list_all()
|
||||||
output = output .. "Orgs:\n" ..
|
|
||||||
table.concat(modpol.orgs.list_all(),"\n")
|
print('Select an org')
|
||||||
-- Command list (should be redone to be org-specific)
|
for i, org_name in ipairs(org_list) do
|
||||||
output = output .. "\nCommand list:\n"
|
local org = modpol.orgs.get_org(org_name)
|
||||||
for key,value in pairs(modpol) do
|
local indicator = ""
|
||||||
output = output .. "modpol." .. key .. " "
|
if org:has_pending_actions(user) then
|
||||||
|
indicator = "*"
|
||||||
|
end
|
||||||
|
print('['..i..']'..' '..org_name..indicator)
|
||||||
end
|
end
|
||||||
print(output)
|
|
||||||
|
local sel = io.read()
|
||||||
|
local sel_org = org_list[tonumber(sel)]
|
||||||
|
|
||||||
|
if not sel_org then return end
|
||||||
|
|
||||||
|
modpol.interactions.org_dashboard(user, sel_org)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -32,40 +56,58 @@ end
|
|||||||
-- Params: user (string), org_name (string)
|
-- Params: user (string), org_name (string)
|
||||||
-- Output: Displays a menu of org-specific commands to the user
|
-- Output: Displays a menu of org-specific commands to the user
|
||||||
function modpol.interactions.org_dashboard(user, org_name)
|
function modpol.interactions.org_dashboard(user, org_name)
|
||||||
|
print()
|
||||||
local org = modpol.orgs.get_org(org_name)
|
local org = modpol.orgs.get_org(org_name)
|
||||||
if not org then return nil end
|
if not org then return nil end
|
||||||
local is_member = org:has_member(user)
|
|
||||||
local membership_toggle = function()
|
|
||||||
local toggle_code = ""
|
|
||||||
if is_member then
|
|
||||||
toggle_code = "[Leave]"
|
|
||||||
else
|
|
||||||
toggle_code = "[Join]"
|
|
||||||
end
|
|
||||||
return toggle_code
|
|
||||||
end
|
|
||||||
local children = {}
|
local children = {}
|
||||||
for k,v in ipairs(org.children) do
|
for k,v in ipairs(org.children) do
|
||||||
local this_child = modpol.orgs.get_org(v)
|
local this_child = modpol.orgs.get_org(v)
|
||||||
table.insert(children, this_child.name)
|
table.insert(children, this_child.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local processes = {}
|
||||||
|
for k,v in ipairs(org.processes) do
|
||||||
|
print(k, v)
|
||||||
|
local this_request = org.requests[v.request_id]
|
||||||
|
if type(this_request) == "table" then
|
||||||
|
local active = ''
|
||||||
|
if org.pending[user] then
|
||||||
|
if org.pending[user][v.id] then
|
||||||
|
active = '*'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local req_str = "[" .. v.id .. "] " ..
|
||||||
|
active .. this_request.type
|
||||||
|
if this_request.params[1] then
|
||||||
|
req_str = req_str ": " ..
|
||||||
|
table.concat(this_request.params, ", ")
|
||||||
|
end
|
||||||
|
local req_str = v.id .. " (" .. this_request.type .. " -> " .. table.concat(this_request.params, ", ") .. ")" .. active
|
||||||
|
table.insert(processes, req_str)
|
||||||
|
end
|
||||||
|
end
|
||||||
-- set up output
|
-- set up output
|
||||||
local dashboard_table = {
|
print("Org: " .. org_name)
|
||||||
"Org: " .. org_name,
|
print("Members: " .. table.concat(org.members, ", "))
|
||||||
membership_toggle(),
|
print("Children: " .. table.concat(children, ", "))
|
||||||
"Members: " .. table.concat(org.members, ", "),
|
print("Processes: " .. table.concat(processes, ", "))
|
||||||
"Children: " .. table.concat(children, ", "),
|
|
||||||
"Policies: " .. table.concat(org.policies, ", "),
|
print('Interact with which process?')
|
||||||
"Processes: " .. table.concat(org.processes, ", "),
|
local sel = io.read()
|
||||||
"[Add child]",
|
local process = org.processes[tonumber(sel)]
|
||||||
"[Remove org]",
|
if not process then return end
|
||||||
"[Dashboard: modpol.dashboard()]"
|
process:interact(user)
|
||||||
}
|
|
||||||
-- present to player
|
|
||||||
print(table.concat(dashboard_table, "\n"))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
-- Function: modpol.interactions.policy_dashboard
|
||||||
|
-- input: user (string), org_id (int), policy (string)
|
||||||
|
-- if policy is nil, enables creating a new policy
|
||||||
|
-- output: opens a dashboard for viewing/editing policy details
|
||||||
|
-- TODO
|
||||||
|
|
||||||
|
|
||||||
-- Function: modpol.interactions.message
|
-- Function: modpol.interactions.message
|
||||||
-- input: user (string), message (string)
|
-- input: user (string), message (string)
|
||||||
-- output: prints message to CLI
|
-- output: prints message to CLI
|
||||||
@ -73,31 +115,86 @@ function modpol.interactions.message(user, message)
|
|||||||
print(user .. ": " .. message)
|
print(user .. ": " .. message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
|
||||||
-- Function: modpol.interactions.text_query
|
-- Function: modpol.interactions.text_query
|
||||||
-- input: Query (string)
|
-- input: User (string), Query (string), func (function)
|
||||||
-- output: User response (string)
|
-- func input: user input (string)
|
||||||
function modpol.interactions.text_query(query)
|
-- output: Applies "func" to user input
|
||||||
-- TODO
|
function modpol.interactions.text_query(user, query, func)
|
||||||
|
print(user .. ": " .. query)
|
||||||
|
answer = io.read()
|
||||||
|
func(answer)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function: dropdown_query
|
||||||
|
-- input: user (string), label (string), options (table of strings), func(choice) (function)
|
||||||
|
-- func input: choice (string)
|
||||||
|
-- output: calls func on choice
|
||||||
|
function modpol.interactions.dropdown_query(user, label, options, func)
|
||||||
|
-- set up options
|
||||||
|
local options_display = ""
|
||||||
|
local options_number = 0
|
||||||
|
for k,v in ipairs(options) do
|
||||||
|
options_display = options_display .. k .. ". " ..
|
||||||
|
options[k] .. "\n"
|
||||||
|
options_number = options_number + 1
|
||||||
|
end
|
||||||
|
options_display = options_display .. "Select number:"
|
||||||
|
if options_number == 0 then
|
||||||
|
print("Error: No options given for dropdown")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
-- begin displaying
|
||||||
|
print(user .. ": " .. label)
|
||||||
|
print(options_display)
|
||||||
|
-- read input and produce output
|
||||||
|
local answer
|
||||||
|
answer = io.read()
|
||||||
|
answer = tonumber(answer)
|
||||||
|
if answer then
|
||||||
|
if answer >= 1 and answer <= options_number then
|
||||||
|
print("Selection: " .. options[answer])
|
||||||
|
func(options[answer])
|
||||||
|
else
|
||||||
|
print("Error: Not in dropdown range")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("Error: Must be a number")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
|
||||||
-- Function: modpol.binary_poll_user(user, question)
|
-- Function: modpol.binary_poll_user(user, question)
|
||||||
-- Params: user (string), question (string)
|
-- Params: user (string), question (string), func (function)
|
||||||
-- Output:
|
-- func input: user input (string: y/n)
|
||||||
-- presents a yes/no/abstain poll to a user, returns answer
|
-- Output: Applies "func" to user input
|
||||||
function modpol.interactions.binary_poll_user(user, question)
|
function modpol.interactions.binary_poll_user(user, question, func)
|
||||||
local query = "Poll for " .. user .. " (y/n): ".. question
|
local query = "Poll for " .. user .. " (y/n): ".. question
|
||||||
local answer
|
local answer
|
||||||
repeat
|
repeat
|
||||||
print(query)
|
print(query)
|
||||||
answer = io.read()
|
answer = io.read()
|
||||||
until answer == "y" or answer == "n" or answer == "a"
|
until answer == "y" or answer == "n"
|
||||||
if answer == "y" then
|
if answer == "y" then
|
||||||
return "Yes"
|
modpol.interactions.message(user, "Response recorded")
|
||||||
|
func("yes")
|
||||||
elseif answer == "n" then
|
elseif answer == "n" then
|
||||||
return "No"
|
modpol.interactions.message(user, "Response recorded")
|
||||||
|
func("no")
|
||||||
else
|
else
|
||||||
return "Abstain"
|
modpol.interactions.message(user, "Error: invalid response")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- COMPLEX INTERACTIONS
|
||||||
|
-- ====================
|
||||||
|
|
||||||
|
-- Function: modpol.interactions.message_org
|
||||||
|
-- input: initiator (string), org_id (number), message (string)
|
||||||
|
-- output: broadcasts message to all org members
|
||||||
|
|
||||||
|
-- Function: modpol.interactions.binary_poll_org
|
||||||
|
-- input: initator (user string), org_id (number)
|
||||||
|
-- output: gets question from initiator, asks all org members, broadcasts answers
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +38,21 @@ function modpol.modules.consent:new_process(id, request_id, org_id)
|
|||||||
return process
|
return process
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ============================
|
||||||
|
-- interact function for the consent module
|
||||||
|
-- input: user (string)
|
||||||
|
function modpol.modules.consent:interact(user)
|
||||||
|
-- TODO this needs more context on the vote at hand
|
||||||
|
modpol.interactions.binary_poll_user(
|
||||||
|
user, "Do you consent?",
|
||||||
|
function(vote)
|
||||||
|
if vote == 'yes' then
|
||||||
|
self:approve(user, true)
|
||||||
|
elseif vote == 'no' then
|
||||||
|
self:approve(user, false)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
-- =========================================
|
-- =========================================
|
||||||
-- function to delete a process, called when process finishes
|
-- function to delete a process, called when process finishes
|
||||||
@ -90,4 +105,4 @@ function modpol.modules.consent:update_status()
|
|||||||
else
|
else
|
||||||
modpol.ocutil.log('Waiting for more votes...')
|
modpol.ocutil.log('Waiting for more votes...')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,7 +11,12 @@ function temp_org()
|
|||||||
return {
|
return {
|
||||||
id = nil,
|
id = nil,
|
||||||
name = nil,
|
name = nil,
|
||||||
policies = {},
|
policies = {
|
||||||
|
add_org={process_type='consent', must_be_member=false},
|
||||||
|
delete={process_type='consent', must_be_member=false},
|
||||||
|
add_member={process_type='consent', must_be_member=false},
|
||||||
|
remove_member={process_type='consent', must_be_member=false}
|
||||||
|
},
|
||||||
processes = {},
|
processes = {},
|
||||||
requests = {},
|
requests = {},
|
||||||
pending = {},
|
pending = {},
|
||||||
@ -96,15 +101,15 @@ function modpol.orgs.init_instance()
|
|||||||
|
|
||||||
local instance = temp_org()
|
local instance = temp_org()
|
||||||
instance.id = 1
|
instance.id = 1
|
||||||
instance.name = "instance"
|
instance.name = "root"
|
||||||
|
|
||||||
setmetatable(instance, modpol.orgs)
|
setmetatable(instance, modpol.orgs)
|
||||||
|
|
||||||
-- adding instance to org list
|
-- adding instance to org list
|
||||||
modpol.orgs.array[1] = instance
|
modpol.orgs.array[1] = instance
|
||||||
|
|
||||||
modpol.ocutil.log('Initialized the instance org')
|
modpol.ocutil.log('Initialized the instance root org')
|
||||||
modpol.orgs:record('Initialized the instance org', 'create_instance')
|
modpol.orgs:record('Initialized the instance root org', 'create_instance')
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
end
|
end
|
||||||
@ -148,6 +153,7 @@ end
|
|||||||
|
|
||||||
-- ==================================================
|
-- ==================================================
|
||||||
-- adds a new sub org to the org it is called on
|
-- adds a new sub org to the org it is called on
|
||||||
|
-- input: name (string), user (string)
|
||||||
-- ex: instance:add_org('town hall')
|
-- ex: instance:add_org('town hall')
|
||||||
function modpol.orgs:add_org(name, user)
|
function modpol.orgs:add_org(name, user)
|
||||||
if self.id == nil then
|
if self.id == nil then
|
||||||
@ -171,6 +177,7 @@ function modpol.orgs:add_org(name, user)
|
|||||||
child_org.id = modpol.orgs.count
|
child_org.id = modpol.orgs.count
|
||||||
child_org.name = name
|
child_org.name = name
|
||||||
child_org.parent = self.id
|
child_org.parent = self.id
|
||||||
|
child_org.processes = self.processes
|
||||||
|
|
||||||
setmetatable(child_org, modpol.orgs)
|
setmetatable(child_org, modpol.orgs)
|
||||||
|
|
||||||
@ -275,18 +282,14 @@ function modpol.orgs:has_member(user)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- ==================================
|
-- ==================================
|
||||||
-- returns a list of users in an org
|
-- Function: modpol.orgs:list_members()
|
||||||
function modpol.orgs:list_member()
|
-- output: a table of the names (string) of members
|
||||||
local str
|
function modpol.orgs:list_members()
|
||||||
for k, v in ipairs(self.members) do
|
local members = {}
|
||||||
-- checking to see if member name is valid
|
for k, v in ipairs(self.members) do
|
||||||
if str and str ~= '' then
|
table.insert(members, v)
|
||||||
str = str .. '\n' .. v
|
end
|
||||||
else
|
return members
|
||||||
str = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return str
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ==============================
|
-- ==============================
|
||||||
@ -311,6 +314,7 @@ function modpol.orgs:set_policy(policy_type, process_type, must_be_member)
|
|||||||
}
|
}
|
||||||
self.policies[policy_type] = new_policy
|
self.policies[policy_type] = new_policy
|
||||||
modpol.ocutil.log('Added policy for ' .. policy_type .. ' in ' .. self.name)
|
modpol.ocutil.log('Added policy for ' .. policy_type .. ' in ' .. self.name)
|
||||||
|
self:record('Added policy for ' .. policy_type, 'set_policy')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,10 +13,11 @@ function modpol.orgs:create_process(process_type, request_id)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local empty_index = nil
|
||||||
-- linear search for empty process slots (lazy deletion)
|
-- linear search for empty process slots (lazy deletion)
|
||||||
for k, v in ipairs(self.processes) do
|
for k, v in ipairs(self.processes) do
|
||||||
if v == 'deleted' then
|
if v == 'deleted' then
|
||||||
local empty_index = k
|
empty_index = k
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -35,6 +36,9 @@ function modpol.orgs:create_process(process_type, request_id)
|
|||||||
|
|
||||||
self.processes[index] = new_process
|
self.processes[index] = new_process
|
||||||
|
|
||||||
|
modpol.ocutil.log('Created process #' .. index .. ' - ' .. process_type .. ' for ' .. self.name)
|
||||||
|
self:record('Created process #' .. index .. ' - ' .. process_type, 'add_process')
|
||||||
|
|
||||||
return index
|
return index
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -46,7 +50,8 @@ function modpol.orgs:add_pending_action(process_id, user)
|
|||||||
-- flagging actual action
|
-- flagging actual action
|
||||||
self.pending[user][process_id] = true
|
self.pending[user][process_id] = true
|
||||||
|
|
||||||
modpol.ocutil.log("Added pending action to " .. user .. " in process #" .. process_id)
|
modpol.ocutil.log("Added pending action to " .. user .. " in process #" .. process_id .. ' from ' .. self.name)
|
||||||
|
self:record('Added pending action to ' .. user .. ' in process #' .. process_id, "add_pending_action")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ========================
|
-- ========================
|
||||||
@ -55,7 +60,8 @@ function modpol.orgs:remove_pending_action(process_id, user)
|
|||||||
|
|
||||||
if self.pending[user] then
|
if self.pending[user] then
|
||||||
self.pending[user][process_id] = nil
|
self.pending[user][process_id] = nil
|
||||||
modpol.ocutil.log("Removed pending action from " .. user .. " in process #" .. process_id)
|
modpol.ocutil.log("Removed pending action from " .. user .. " in process #" .. process_id .. ' from ' .. self.name)
|
||||||
|
self:record('Removed pending action from ' .. user .. ' in process #' .. process_id, "del_pending_action")
|
||||||
else
|
else
|
||||||
modpol.ocutil.log("Could not remove pending action from " .. user .. " in process #" .. process_id)
|
modpol.ocutil.log("Could not remove pending action from " .. user .. " in process #" .. process_id)
|
||||||
end
|
end
|
||||||
@ -68,6 +74,23 @@ function modpol.orgs:wipe_pending_actions(process_id)
|
|||||||
self.pending[user][process_id] = nil
|
self.pending[user][process_id] = nil
|
||||||
end
|
end
|
||||||
modpol.ocutil.log("Removed all pending actions for process #" .. process_id)
|
modpol.ocutil.log("Removed all pending actions for process #" .. process_id)
|
||||||
|
self:record('Removed all pending actions for process #' .. process_id, "del_pending_action")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ======================
|
||||||
|
-- returns a boolean to indicate whether a user has any active pending actions
|
||||||
|
function modpol.orgs:has_pending_actions(user)
|
||||||
|
-- next() will return the next pair in a table
|
||||||
|
-- if next() returns nil, the table is empty
|
||||||
|
if not self.pending[user] then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
if not next(self.pending[user]) then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===========================
|
-- ===========================
|
||||||
@ -130,6 +153,9 @@ function modpol.orgs:resolve_request(request_id, approve)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.requests[request_id] = "deleted"
|
self.requests[request_id] = "deleted"
|
||||||
|
|
||||||
|
modpol.ocutil.log("Resolved request #" .. request_id .. ' in ' .. self.name)
|
||||||
|
self:record("Resolved request #" .. request_id, "resolve_request")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ================================
|
-- ================================
|
||||||
@ -189,10 +215,11 @@ function modpol.orgs:make_request(request)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local empty_index = nil
|
||||||
-- linear search for empty process slots (lazy deletion)
|
-- linear search for empty process slots (lazy deletion)
|
||||||
for k, v in ipairs(self.requests) do
|
for k, v in ipairs(self.requests) do
|
||||||
if v == 'deleted' then
|
if v == 'deleted' then
|
||||||
local empty_index = k
|
empty_index = k
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -206,7 +233,9 @@ function modpol.orgs:make_request(request)
|
|||||||
table.insert(self.requests, request)
|
table.insert(self.requests, request)
|
||||||
request_id = #self.requests
|
request_id = #self.requests
|
||||||
end
|
end
|
||||||
modpol.ocutil.log("Request made by " .. request.user .. " to " .. request.type)
|
|
||||||
|
modpol.ocutil.log("Request made by " .. request.user .. " to " .. request.type .. " in " .. self.name)
|
||||||
|
self:record("Request made by " .. request.user .. " to " .. request.type, "make_request")
|
||||||
|
|
||||||
-- launching process tied to this request
|
-- launching process tied to this request
|
||||||
local process_id = self:create_process(requested_policy.process_type, request_id)
|
local process_id = self:create_process(requested_policy.process_type, request_id)
|
||||||
|
@ -25,18 +25,17 @@ dofile (modpol.topdir .. "/util/serpent/serpent.lua")
|
|||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- This function stores "ledger" data to disk.
|
-- This function stores "ledger" data to disk.
|
||||||
|
|
||||||
local store_ledger = function()
|
local store_ledger = function(verbose)
|
||||||
local ok = modpol.ocutil.file_write (modpol.file_ledger,
|
local ok = modpol.ocutil.file_write (modpol.file_ledger, modpol.serpent.dump (modpol.ledger))
|
||||||
modpol.serpent.dump (modpol.ledger))
|
|
||||||
|
|
||||||
if ok ~= true then
|
if ok ~= true then
|
||||||
modpol.ocutil.fatal_error ("store_data: ledger")
|
modpol.ocutil.fatal_error ("store_data: ledger")
|
||||||
end
|
end
|
||||||
|
|
||||||
local nn = modpol.ocutil.table_length (modpol.ledger)
|
local nn = modpol.ocutil.table_length (modpol.ledger)
|
||||||
local str = "entries"
|
local str = "entries"
|
||||||
if nn == 1 then str = "entry" end
|
if nn == 1 then str = "entry" end
|
||||||
modpol.ocutil.log (nn .. " global ledger entries stored to disk")
|
if verbose then modpol.ocutil.log (nn .. " global ledger entries stored to disk") end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
@ -52,35 +51,16 @@ local store_orgs = function()
|
|||||||
local nn = modpol.ocutil.table_length (modpol.orgs.array)
|
local nn = modpol.ocutil.table_length (modpol.orgs.array)
|
||||||
local str = "entries"
|
local str = "entries"
|
||||||
if nn == 1 then str = "entry" end
|
if nn == 1 then str = "entry" end
|
||||||
modpol.ocutil.log (nn .. " orgs stored to disk")
|
if verbose then modpol.ocutil.log (nn .. " orgs stored to disk") end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
|
||||||
-- This function stores "old_ledgers" data to disk.
|
|
||||||
|
|
||||||
local store_old_ledgers = function()
|
|
||||||
|
|
||||||
local ok = modpol.ocutil.file_write (modpol.file_old_ledgers,
|
|
||||||
modpol.serpent.dump (modpol.old_ledgers))
|
|
||||||
|
|
||||||
|
|
||||||
if ok ~= true then
|
|
||||||
modpol.ocutil.fatal_error ("store_data: orgs")
|
|
||||||
end
|
|
||||||
|
|
||||||
local nn = modpol.ocutil.table_length (modpol.old_ledgers)
|
|
||||||
local str = "entries"
|
|
||||||
if nn == 1 then str = "entry" end
|
|
||||||
modpol.ocutil.log (nn .. " orgs stored to disk")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- This function stores data to disk.
|
-- This function stores data to disk.
|
||||||
|
|
||||||
modpol.store_data = function()
|
modpol.store_data = function(verbose)
|
||||||
store_ledger()
|
store_ledger(verbose)
|
||||||
store_orgs()
|
store_orgs(verbose)
|
||||||
-- store_old_ledgers()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
|
31
modpol/tests/nested_functions.lua
Normal file
31
modpol/tests/nested_functions.lua
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
dofile("../modpol.lua")
|
||||||
|
|
||||||
|
print('\nRemoving existing orgs')
|
||||||
|
modpol.orgs.reset()
|
||||||
|
|
||||||
|
print('\nCreating an org called "test_org"')
|
||||||
|
test_org = modpol.instance:add_org('test_org', 'luke')
|
||||||
|
|
||||||
|
print('\nAdding user "nathan" to test_org')
|
||||||
|
test_org:add_member('nathan')
|
||||||
|
|
||||||
|
print("\nOkay, let's start with requests. Setting up an org...")
|
||||||
|
modpol.instance:add_org('test_org', 'luke')
|
||||||
|
test_org:add_member('nathan')
|
||||||
|
|
||||||
|
print('\nMaking consent the add_member policy')
|
||||||
|
test_org:set_policy("add_member", "consent", false);
|
||||||
|
|
||||||
|
print('\nMaking a request to add Josh')
|
||||||
|
add_josh = {
|
||||||
|
user = "josh",
|
||||||
|
type = "add_member",
|
||||||
|
params = {"josh"}
|
||||||
|
}
|
||||||
|
request_id = test_org:make_request(add_josh)
|
||||||
|
|
||||||
|
|
||||||
|
print('\nHave the two members vote on it')
|
||||||
|
modpol.interactions.org_dashboard("nathan","test_org")
|
||||||
|
modpol.interactions.org_dashboard("luke","test_org")
|
||||||
|
|
@ -28,7 +28,7 @@ end
|
|||||||
modpol.instance:set_policy("add_org", "consent", false);
|
modpol.instance:set_policy("add_org", "consent", false);
|
||||||
|
|
||||||
new_request = {
|
new_request = {
|
||||||
user = "lukvmil",
|
user = "luke",
|
||||||
type = "add_org",
|
type = "add_org",
|
||||||
params = {"new_org"}
|
params = {"new_org"}
|
||||||
}
|
}
|
||||||
@ -39,6 +39,13 @@ modpol.instance:add_member('josh')
|
|||||||
modpol.instance:add_member('nathan')
|
modpol.instance:add_member('nathan')
|
||||||
|
|
||||||
request_id = modpol.instance:make_request(new_request)
|
request_id = modpol.instance:make_request(new_request)
|
||||||
|
modpol.instance:make_request({
|
||||||
|
user="luke",
|
||||||
|
type="add_org",
|
||||||
|
params={"second_org"}
|
||||||
|
})
|
||||||
|
|
||||||
|
modpol.interactions.login()
|
||||||
|
|
||||||
for id, process in ipairs(modpol.instance.processes) do
|
for id, process in ipairs(modpol.instance.processes) do
|
||||||
-- process:approve('luke', true)
|
-- process:approve('luke', true)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
-- CONTEXTUAL STUFF
|
-- CONTEXTUAL STUFF
|
||||||
-- ================
|
-- ================
|
||||||
|
|
||||||
-- First, set up contexts to enable passing across formspecs
|
-- _contexts to enable passing across formspecs
|
||||||
-- https://rubenwardy.com/minetest_modding_book/en/players/formspecs.html#contexts
|
-- https://rubenwardy.com/minetest_modding_book/en/players/formspecs.html#contexts
|
||||||
|
|
||||||
local _contexts = {}
|
local _contexts = {}
|
||||||
@ -16,10 +16,6 @@ minetest.register_on_leaveplayer(function(player)
|
|||||||
_contexts[player:get_player_name()] = nil
|
_contexts[player:get_player_name()] = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- table of formspec field responses
|
|
||||||
local formspec_fields = {}
|
|
||||||
|
|
||||||
|
|
||||||
-- UTILITIES
|
-- UTILITIES
|
||||||
-- =========
|
-- =========
|
||||||
|
|
||||||
@ -38,7 +34,6 @@ local function formspec_list(array)
|
|||||||
return table.concat(escaped,",")
|
return table.concat(escaped,",")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- DASHBOARDS
|
-- DASHBOARDS
|
||||||
-- ==========
|
-- ==========
|
||||||
|
|
||||||
@ -57,7 +52,7 @@ function modpol.interactions.dashboard(user)
|
|||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
"size[10,8]",
|
"size[10,8]",
|
||||||
"label[0.5,0.5;M O D U L A R P O L I T I C S]",
|
"label[0.5,0.5;MODPOL DASHBOARD]",
|
||||||
"label[0.5,2;All orgs:]",
|
"label[0.5,2;All orgs:]",
|
||||||
"dropdown[2,1.5;5,0.8;all_orgs;"..formspec_list(all_orgs)..";;]",
|
"dropdown[2,1.5;5,0.8;all_orgs;"..formspec_list(all_orgs)..";;]",
|
||||||
"label[0.5,3;Your orgs:]",
|
"label[0.5,3;Your orgs:]",
|
||||||
@ -67,6 +62,7 @@ function modpol.interactions.dashboard(user)
|
|||||||
"button[0.5,7;1,0.8;test_poll;Test poll]",
|
"button[0.5,7;1,0.8;test_poll;Test poll]",
|
||||||
"button[2,7;1,0.8;add_org;Add org]",
|
"button[2,7;1,0.8;add_org;Add org]",
|
||||||
"button[3.5,7;1.5,0.8;remove_org;Remove org]",
|
"button[3.5,7;1.5,0.8;remove_org;Remove org]",
|
||||||
|
"button[5.5,7;1.5,0.8;reset_orgs;Reset orgs]",
|
||||||
"button_exit[8.5,7;1,0.8;close;Close]",
|
"button_exit[8.5,7;1,0.8;close;Close]",
|
||||||
}
|
}
|
||||||
local formspec_string = table.concat(formspec, "")
|
local formspec_string = table.concat(formspec, "")
|
||||||
@ -78,14 +74,29 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
if formname == "modpol:dashboard" then
|
if formname == "modpol:dashboard" then
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
if nil then
|
if nil then
|
||||||
-- buttons first
|
-- buttons first
|
||||||
elseif fields.test_poll then
|
elseif fields.test_poll then
|
||||||
modpol.interactions.binary_poll_org(pname, 1, "Poll question (yes/no):")
|
-- FOR TESTING PURPOSES ONLY
|
||||||
|
modpol.interactions.text_query(
|
||||||
|
pname,"Poll question:",
|
||||||
|
function(input)
|
||||||
|
modpol.interactions.binary_poll_user(
|
||||||
|
pname, input,
|
||||||
|
function(vote)
|
||||||
|
modpol.interactions.message(
|
||||||
|
pname, pname .. " voted " .. vote)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
elseif fields.add_org then
|
elseif fields.add_org then
|
||||||
modpol.interactions.add_org(pname, 1)
|
modpol.interactions.add_org(pname, 1)
|
||||||
elseif fields.remove_org then
|
elseif fields.remove_org then
|
||||||
modpol.interactions.remove_org(pname)
|
modpol.interactions.remove_org(pname)
|
||||||
-- dropdowns need to go last
|
elseif fields.reset_orgs then
|
||||||
|
modpol.orgs.reset()
|
||||||
|
modpol.instance:add_member(pname)
|
||||||
|
modpol.interactions.dashboard(pname)
|
||||||
|
|
||||||
|
-- Put all dropdowns at the end
|
||||||
elseif fields.close then
|
elseif fields.close then
|
||||||
minetest.close_formspec(pname, formname)
|
minetest.close_formspec(pname, formname)
|
||||||
elseif fields.all_orgs or fields.user_orgs then
|
elseif fields.all_orgs or fields.user_orgs then
|
||||||
@ -117,11 +128,43 @@ function modpol.interactions.org_dashboard(user, org_name)
|
|||||||
end
|
end
|
||||||
return toggle_code
|
return toggle_code
|
||||||
end
|
end
|
||||||
local children = {}
|
-- identify parent
|
||||||
|
local parent = modpol.orgs.get_org(org.parent)
|
||||||
|
if parent then parent = parent.name
|
||||||
|
else parent = "none" end
|
||||||
|
-- prepare children menu
|
||||||
|
local children = {"View..."}
|
||||||
for k,v in ipairs(org.children) do
|
for k,v in ipairs(org.children) do
|
||||||
local this_child = modpol.orgs.get_org(v)
|
local this_child = modpol.orgs.get_org(v)
|
||||||
table.insert(children, this_child.name)
|
table.insert(children, this_child.name)
|
||||||
end
|
end
|
||||||
|
-- prepare policies menu
|
||||||
|
local policies = {"View..."}
|
||||||
|
for k,v in pairs(org.policies) do
|
||||||
|
table.insert(policies, k .. ": " ..
|
||||||
|
org.policies[k].process_type)
|
||||||
|
end
|
||||||
|
table.insert(policies, "Add policy")
|
||||||
|
-- prepare processes menu
|
||||||
|
local processes = {"View..."}
|
||||||
|
for k,v in ipairs(org.processes) do
|
||||||
|
local this_request = org.requests[v.request_id]
|
||||||
|
if type(this_request) == "table" then
|
||||||
|
local active = ''
|
||||||
|
if org.pending[user] then
|
||||||
|
if org.pending[user][v.id] then
|
||||||
|
active = '*'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local req_str = "[" .. v.id .. "] " ..
|
||||||
|
active .. this_request.type
|
||||||
|
if this_request.params[1] then
|
||||||
|
req_str = req_str .. ": " ..
|
||||||
|
table.concat(this_request.params, ", ")
|
||||||
|
end
|
||||||
|
table.insert(processes, req_str)
|
||||||
|
end
|
||||||
|
end
|
||||||
-- set player context
|
-- set player context
|
||||||
local user_context = {}
|
local user_context = {}
|
||||||
user_context["current_org"] = org_name
|
user_context["current_org"] = org_name
|
||||||
@ -132,16 +175,16 @@ function modpol.interactions.org_dashboard(user, org_name)
|
|||||||
"size[10,8]",
|
"size[10,8]",
|
||||||
"label[0.5,0.5;Org: "..
|
"label[0.5,0.5;Org: "..
|
||||||
minetest.formspec_escape(org_name).."]",
|
minetest.formspec_escape(org_name).."]",
|
||||||
"label[0.5,1;Parent: TODO]",
|
"label[0.5,1;Parent: "..parent.."]",
|
||||||
"button[8.5,0.5;1,0.8;"..membership_toggle(),
|
"button[8.5,0.5;1,0.8;"..membership_toggle(),
|
||||||
"label[0.5,2;Members:]",
|
"label[0.5,2;Members:]",
|
||||||
"dropdown[2,1.5;5,0.8;user_orgs;"..formspec_list(org.members)..";;]",
|
"dropdown[2,1.5;5,0.8;user_orgs;"..formspec_list(org.members)..";;]",
|
||||||
"label[0.5,3;Children:]",
|
"label[0.5,3;Children:]",
|
||||||
"dropdown[2,2.5;5,0.8;children;"..formspec_list(children)..";;]",
|
"dropdown[2,2.5;5,0.8;children;"..formspec_list(children)..";;]",
|
||||||
"label[0.5,4;Policies:]",
|
"label[0.5,4;Policies:]",
|
||||||
"dropdown[2,3.5;5,0.8;policies;"..formspec_list(org.policies)..";;]",
|
"dropdown[2,3.5;5,0.8;policies;"..formspec_list(policies)..";;]",
|
||||||
"label[0.5,5;Processes:]",
|
"label[0.5,5;Processes:]",
|
||||||
"dropdown[2,4.5;5,0.8;processes;"..formspec_list(org.processes)..";;]",
|
"dropdown[2,4.5;5,0.8;processes;"..formspec_list(processes)..";;]",
|
||||||
"button[0.5,7;1,0.8;test_poll;Test poll]",
|
"button[0.5,7;1,0.8;test_poll;Test poll]",
|
||||||
"button[2,7;1,0.8;add_child;Add child]",
|
"button[2,7;1,0.8;add_child;Add child]",
|
||||||
"button[3.5,7;1.5,0.8;remove_org;Remove org]",
|
"button[3.5,7;1.5,0.8;remove_org;Remove org]",
|
||||||
@ -159,29 +202,89 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
if nil then
|
if nil then
|
||||||
elseif fields.join then
|
elseif fields.join then
|
||||||
local new_request = {
|
local new_request = {
|
||||||
user = player,
|
user = pname,
|
||||||
type = "add_member",
|
type = "add_member",
|
||||||
params = {player}
|
params = {pname}
|
||||||
}
|
}
|
||||||
org:make_request(new_request)
|
org:make_request(new_request)
|
||||||
--org:add_member(pname)
|
|
||||||
modpol.interactions.org_dashboard(pname,org.name)
|
modpol.interactions.org_dashboard(pname,org.name)
|
||||||
elseif fields.leave then
|
elseif fields.leave then
|
||||||
org:remove_member(pname)
|
org:remove_member(pname)
|
||||||
modpol.interactions.dashboard(pname)
|
modpol.interactions.dashboard(pname)
|
||||||
elseif fields.test_poll then
|
elseif fields.test_poll then
|
||||||
modpol.interactions.binary_poll_org(pname, _contexts.pname.current_org.id, "Poll question (yes/no):")
|
modpol.interactions.binary_poll_org(
|
||||||
|
pname, org.id,
|
||||||
|
function(input)
|
||||||
|
modpol.interactions.message_org(
|
||||||
|
pname,
|
||||||
|
org.id,
|
||||||
|
pname .. " responded " .. input)
|
||||||
|
end)
|
||||||
elseif fields.add_child then
|
elseif fields.add_child then
|
||||||
modpol.interactions.add_org(pname, org.id)
|
modpol.interactions.text_query(
|
||||||
|
pname, "Child org name:",
|
||||||
|
function(input)
|
||||||
|
local new_request = {
|
||||||
|
user = pname,
|
||||||
|
type = "add_org",
|
||||||
|
params = {input,pname}
|
||||||
|
}
|
||||||
|
org:make_request(new_request)
|
||||||
|
modpol.interactions.message(pname,"requested")
|
||||||
|
modpol.interactions.org_dashboard(
|
||||||
|
pname,org.name)
|
||||||
|
end)
|
||||||
elseif fields.remove_org then
|
elseif fields.remove_org then
|
||||||
modpol.interactions.remove_org(pname)
|
local new_request = {
|
||||||
|
user = pname,
|
||||||
|
type = "delete",
|
||||||
|
params = {}
|
||||||
|
}
|
||||||
|
org:make_request(new_request)
|
||||||
|
modpol.interactions.org_dashboard(pname,org.name)
|
||||||
elseif fields.back then
|
elseif fields.back then
|
||||||
modpol.interactions.dashboard(pname)
|
modpol.interactions.dashboard(pname)
|
||||||
|
|
||||||
|
-- Put all dropdowns at the end
|
||||||
|
elseif fields.policies
|
||||||
|
and fields.policies ~= "View..." then
|
||||||
|
local policy
|
||||||
|
if fields.policies == "Add policy" then
|
||||||
|
policy = nil
|
||||||
|
elseif fields.policies == "View..." then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
policy = string.match(fields.policies,"(%w+)%:")
|
||||||
|
end
|
||||||
|
modpol.interactions.policy_dashboard(
|
||||||
|
pname, org.id, policy)
|
||||||
|
elseif fields.processes
|
||||||
|
and fields.processes ~= "View..." then
|
||||||
|
local sel = string.match(fields.processes,"%[(%d)%]")
|
||||||
|
local process = org.processes[tonumber(sel)]
|
||||||
|
if process then
|
||||||
|
process:interact(pname)
|
||||||
|
end
|
||||||
|
elseif fields.children
|
||||||
|
and fields.children ~= "View..." then
|
||||||
|
local org_name = fields.children
|
||||||
|
modpol.interactions.org_dashboard(pname, org_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
-- Function: modpol.interactions.policy_dashboard
|
||||||
|
-- input: user (string), org_id (int), policy (string)
|
||||||
|
-- output: opens a dashboard for viewing/editing policy details
|
||||||
|
-- TODO
|
||||||
|
function modpol.interactions.policy_dashboard(
|
||||||
|
user, org_id, policy)
|
||||||
|
modpol.interactions.message(
|
||||||
|
user,
|
||||||
|
"Not yet implemented: " .. policy)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- BASIC INTERACTION FUNCTIONS
|
-- BASIC INTERACTION FUNCTIONS
|
||||||
-- ===========================
|
-- ===========================
|
||||||
@ -189,16 +292,16 @@ end)
|
|||||||
-- Function: modpol.interactions.message
|
-- Function: modpol.interactions.message
|
||||||
-- input: message (string)
|
-- input: message (string)
|
||||||
-- output
|
-- output
|
||||||
modpol.interactions.message = function(user, message)
|
function modpol.interactions.message(user, message)
|
||||||
minetest.chat_send_player(user, message)
|
minetest.chat_send_player(user, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function: modpol.interactions.text_query
|
-- Function: modpol.interactions.text_query
|
||||||
-- Overrides function at modpol/interactions.lua
|
-- Overrides function at modpol/interactions.lua
|
||||||
-- input: Query (string), User (string)
|
-- input: user (string), query (string), func (function)
|
||||||
-- output: User response (string)
|
-- func input: user input (string)
|
||||||
-- TODO Need to switch "user" to index not name
|
-- output: Applies "func" to user input
|
||||||
function modpol.interactions.text_query(user, query)
|
function modpol.interactions.text_query(user, query, func)
|
||||||
-- set up formspec
|
-- set up formspec
|
||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
@ -210,40 +313,63 @@ function modpol.interactions.text_query(user, query)
|
|||||||
local formspec_string = table.concat(formspec, "")
|
local formspec_string = table.concat(formspec, "")
|
||||||
-- present to players
|
-- present to players
|
||||||
minetest.show_formspec(user, "modpol:text_query", formspec_string)
|
minetest.show_formspec(user, "modpol:text_query", formspec_string)
|
||||||
|
-- put func in _contexts
|
||||||
|
if _contexts[user] == nil then _contexts[user] = {} end
|
||||||
|
_contexts[user]["text_query_func"] = func
|
||||||
end
|
end
|
||||||
-- receive fields
|
-- receive fields
|
||||||
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
||||||
if formname == "modpol:text_query" then
|
if formname == "modpol:text_query" then
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
if _contexts[pname] then
|
local input = fields.input
|
||||||
_contexts[pname](fields.input)
|
if not input then
|
||||||
|
-- no input, do nothing
|
||||||
|
else
|
||||||
|
local func = _contexts[pname]["text_query_func"]
|
||||||
|
if func then
|
||||||
|
func(input)
|
||||||
|
else
|
||||||
|
modpol.interactions.message(pname, "text_query: " .. input)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
minetest.close_formspec(pname, formname)
|
minetest.close_formspec(pname, formname)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
-- Function: dropdown_query
|
-- Function: dropdown_query
|
||||||
-- input: user (string), label (string), options (table of strings)
|
-- input: user (string), label (string), options (table of strings), func (function)
|
||||||
function modpol.interactions.dropdown_query(user, label, options)
|
-- func input: choice (string)
|
||||||
|
-- output: calls func on user choice
|
||||||
|
function modpol.interactions.dropdown_query(user, label, options, func)
|
||||||
-- set up formspec
|
-- set up formspec
|
||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
"size[10,4]",
|
"size[10,4]",
|
||||||
"label[0.5,1;"..minetest.formspec_escape(label).."]",
|
"label[0.5,1;"..minetest.formspec_escape(label).."]",
|
||||||
"dropdown[0.5,1.25;9,0.8;input;"..formspec_list(options)..";;]",
|
"dropdown[0.5,1.25;9,0.8;input;"..formspec_list(options)..";;]",
|
||||||
"button[0.5,2.5;1,0.8;yes;OK]",
|
"button[0.5,2.5;1,0.8;cancel;Cancel]",
|
||||||
}
|
}
|
||||||
local formspec_string = table.concat(formspec, "")
|
local formspec_string = table.concat(formspec, "")
|
||||||
-- present to players
|
-- present to players
|
||||||
minetest.show_formspec(user, "modpol:dropdown_query", formspec_string)
|
minetest.show_formspec(user, "modpol:dropdown_query", formspec_string)
|
||||||
|
-- put func in _contexts
|
||||||
|
if _contexts[user] == nil then _contexts[user] = {} end
|
||||||
|
_contexts[user]["dropdown_query_func"] = func
|
||||||
end
|
end
|
||||||
-- receive fields
|
-- receive fields
|
||||||
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
||||||
if formname == "modpol:dropdown_query" then
|
if formname == "modpol:dropdown_query" then
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
if _contexts[pname] then
|
if fields.cancel ~= "cancel" then
|
||||||
_contexts[pname](fields.input)
|
local choice = fields.input
|
||||||
|
local func = _contexts[pname]["dropdown_query_func"]
|
||||||
|
if not choice then
|
||||||
|
-- no choice, do nothing
|
||||||
|
elseif func then
|
||||||
|
func(choice)
|
||||||
|
else
|
||||||
|
modpol.interactions.message(pname, "dropdown_query: " .. choice)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
minetest.close_formspec(pname, formname)
|
minetest.close_formspec(pname, formname)
|
||||||
end
|
end
|
||||||
@ -253,27 +379,28 @@ end)
|
|||||||
-- SECONDARY INTERACTIONS
|
-- SECONDARY INTERACTIONS
|
||||||
-- ======================
|
-- ======================
|
||||||
|
|
||||||
-- Function: modpol.binary_poll_user(user, question)
|
-- Function: modpol.binary_poll_user(user, question, function)
|
||||||
-- Overrides function at modpol/interactions.lua
|
-- Overrides function at modpol/interactions.lua
|
||||||
-- presents a yes/no poll to a user, returns answer
|
-- Params: user (string), question (string), func (function)
|
||||||
--
|
-- func input: user input (string: y/n)
|
||||||
function modpol.interactions.binary_poll_user(user, question)
|
-- Output: Applies "func" to user input
|
||||||
|
function modpol.interactions.binary_poll_user(user, question, func)
|
||||||
-- set up formspec
|
-- set up formspec
|
||||||
local text = "Poll: " .. question
|
|
||||||
local formspec = {
|
local formspec = {
|
||||||
"formspec_version[4]",
|
"formspec_version[4]",
|
||||||
"size[5,3]",
|
"size[5,3]",
|
||||||
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
|
"label[0.375,0.5;",minetest.formspec_escape(question), "]",
|
||||||
"button[1,1.5;1,0.8;yes;Yes]",
|
"button[1,1.5;1,0.8;yes;Yes]",
|
||||||
"button[2,1.5;1,0.8;no;No]",
|
"button[2,1.5;1,0.8;no;No]",
|
||||||
--TKTK can we enable text wrapping?
|
--TKTK can we enable text wrapping?
|
||||||
--TKTK we could use scroll boxes to contain the text
|
--TKTK we could use scroll boxes to contain the text
|
||||||
}
|
}
|
||||||
local formspec_string = table.concat(formspec, "")
|
local formspec_string = table.concat(formspec, "")
|
||||||
|
if _contexts[user] == nil then _contexts[user] = {} end
|
||||||
|
_contexts[user]["binary_poll_func"] = func
|
||||||
-- present to player
|
-- present to player
|
||||||
minetest.show_formspec(user, "modpol:binary_poll_user", formspec_string)
|
minetest.show_formspec(user, "modpol:binary_poll_user", formspec_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
minetest.register_on_player_receive_fields(function (player, formname, fields)
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
-- modpol:binary_poll
|
-- modpol:binary_poll
|
||||||
@ -281,79 +408,80 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
|
|||||||
local vote = nil
|
local vote = nil
|
||||||
if fields.yes then vote = fields.yes
|
if fields.yes then vote = fields.yes
|
||||||
elseif fields.no then vote = fields.no
|
elseif fields.no then vote = fields.no
|
||||||
elseif fields.abstain then vote = fields.abstain
|
|
||||||
end
|
end
|
||||||
if vote then
|
if vote then
|
||||||
modpol.interactions.message(pname, "Vote recorded")
|
modpol.interactions.message(pname, "Responded " .. vote)
|
||||||
minetest.chat_send_all(pname .. " voted " .. vote)
|
local func = _contexts[pname]["binary_poll_func"]
|
||||||
--TODO : we should send the message to all in that org, not to all players
|
if func then func(vote) end
|
||||||
end
|
end
|
||||||
minetest.close_formspec(pname, formname)
|
minetest.close_formspec(pname, formname)
|
||||||
return vote
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- COMPLEX INTERACTIONS
|
-- COMPLEX INTERACTIONS
|
||||||
-- ====================
|
-- ====================
|
||||||
|
|
||||||
|
-- Function: modpol.interactions.message_org
|
||||||
|
-- input: initiator (string), org_id (number), message (string)
|
||||||
|
-- output: broadcasts message to all org members
|
||||||
|
function modpol.interactions.message_org(initiator, org_id, message)
|
||||||
|
local org = modpol.orgs.get_org(org_id)
|
||||||
|
local users = org:list_members()
|
||||||
|
for k,v in ipairs(users) do
|
||||||
|
modpol.interactions.message(v, message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Function: modpol.interactions.binary_poll_org
|
-- Function: modpol.interactions.binary_poll_org
|
||||||
-- input: initator (user string), org (number)
|
-- input: initator (user string), org_id (number)
|
||||||
-- output: interaction begins
|
-- output: gets question from initiator, asks all org members, broadcasts answers
|
||||||
function modpol.interactions.binary_poll_org(initiator, org)
|
-- TODO for testing. This should be implemented as a request.
|
||||||
-- start formspec
|
function modpol.interactions.binary_poll_org(initiator, org_id, func)
|
||||||
modpol.interactions.text_query(initiator, "Poll question (yes/no):")
|
local org = modpol.orgs.get_org(org_id)
|
||||||
-- set user's context to followup function
|
local users = org:list_members()
|
||||||
_contexts[initiator] =
|
modpol.interactions.text_query(
|
||||||
|
initiator, "Yes/no poll question:",
|
||||||
function(input)
|
function(input)
|
||||||
local users = modpol.list_users()
|
|
||||||
for k,v in ipairs(users) do
|
for k,v in ipairs(users) do
|
||||||
modpol.interactions.binary_poll_user(v, input)
|
modpol.interactions.binary_poll_user(v, input, func)
|
||||||
end
|
end
|
||||||
_contexts[initiator] = nil
|
end)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function: modpol.interactions.add_org
|
-- Function: modpol.interactions.add_org
|
||||||
-- input: initator (user string), base_org_id (ID)
|
-- input: initator (user string), base_org_id (ID)
|
||||||
-- output: interaction begins
|
-- output: interaction begins
|
||||||
function modpol.interactions.add_org(initiator, base_org_id)
|
-- GODMODE
|
||||||
-- start formspec
|
function modpol.interactions.add_org(user, base_org_id)
|
||||||
modpol.interactions.text_query(initiator, "Org name:")
|
modpol.interactions.text_query(
|
||||||
-- set user's context to followup function
|
user,"Org name:",
|
||||||
_contexts[initiator] = function(input)
|
function(input)
|
||||||
if input then
|
local base_org = modpol.orgs.get_org(1)
|
||||||
local base_org = modpol.orgs.get_org(base_org_id)
|
local result = base_org:add_org(input, user)
|
||||||
local result = base_org:add_org(input, initiator)
|
local message = input .. " created"
|
||||||
if result then
|
modpol.interactions.message(user, message)
|
||||||
local message = input .. " created"
|
modpol.interactions.dashboard(user)
|
||||||
modpol.interactions.message(initiator, message)
|
end)
|
||||||
end
|
|
||||||
end
|
|
||||||
_contexts[initiator] = nil
|
|
||||||
modpol.interactions.dashboard(initiator)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function: modpol.interactions.remove_org
|
-- Function: modpol.interactions.remove_org
|
||||||
-- input: initator (user string)
|
-- input: initator (user string)
|
||||||
-- output: interaction begins
|
-- output: interaction begins
|
||||||
function modpol.interactions.remove_org(initiator)
|
-- GODMODE
|
||||||
|
function modpol.interactions.remove_org(user)
|
||||||
-- start formspec
|
-- start formspec
|
||||||
local orgs_list = modpol.orgs.list_all()
|
local orgs_list = modpol.orgs.list_all()
|
||||||
local label = "Choose an org to remove:"
|
local label = "Choose an org to remove:"
|
||||||
modpol.interactions.dropdown_query(initiator, label, orgs_list)
|
modpol.interactions.dropdown_query(
|
||||||
-- set user's context to followup function
|
user, label, orgs_list,
|
||||||
_contexts[initiator] = function(input)
|
function(input)
|
||||||
if input then
|
if input then
|
||||||
local target_org = modpol.orgs.get_org(input)
|
local target_org = modpol.orgs.get_org(input)
|
||||||
local result = target_org:delete()
|
local result = target_org:delete()
|
||||||
if result then
|
|
||||||
local message = input .. " deleted"
|
local message = input .. " deleted"
|
||||||
modpol.interactions.message(initiator, message)
|
modpol.interactions.message(user, message)
|
||||||
end
|
end
|
||||||
end
|
modpol.interactions.dashboard(user)
|
||||||
_contexts[initiator] = nil
|
end)
|
||||||
modpol.interactions.dashboard(initiator)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user