diff --git a/modpol/api.lua b/modpol/api.lua index e1daaec..9fa3c03 100644 --- a/modpol/api.lua +++ b/modpol/api.lua @@ -15,5 +15,7 @@ dofile (localdir .. "/interactions/interactions.lua") --modules dofile (localdir .. "/modules/join_org.lua") dofile (localdir .. "/modules/join_org_class.lua") +dofile (localdir .. "/modules/join_org_consent.lua") +dofile (localdir .. "/modules/consent.lua") dofile (localdir .. "/modules/remove_org.lua") dofile (localdir .. "/modules/child_org.lua") diff --git a/modpol/modules/consent.lua b/modpol/modules/consent.lua new file mode 100644 index 0000000..27b1cd8 --- /dev/null +++ b/modpol/modules/consent.lua @@ -0,0 +1,42 @@ + + +Consent = {} + +Consent.setup = { + name = "Consent", + slug = "consent", + desc = "Other modules can use to implement consent based decision making", + votes = 0 +} + +Consent.config = { + prompt = "Would you like to approve this action?", + votes_required = 1 +} + +function Consent:initiate(result) + self.result = result + for id, member in pairs(self.org.members) do + self.org:add_pending_action(self.id, member, "callback") + end +end + +function Consent:callback(member) + modpol.interactions.binary_poll_user( + member, + self.config.prompt, + function (resp) + if resp == "Yes" then + self.votes = self.votes + 1 + end + + if self.votes >= self.config.votes_required then + self.result() + self.org:wipe_pending_actions(self.id) + end + end + ) +end + + +modpol.modules.consent = Consent \ No newline at end of file diff --git a/modpol/modules/join_org_class.lua b/modpol/modules/join_org_class.lua index 0533e8a..9160425 100644 --- a/modpol/modules/join_org_class.lua +++ b/modpol/modules/join_org_class.lua @@ -2,22 +2,12 @@ -- Module that enables a user to join an org JoinOrg = {} -JoinOrg_mt = { __index = JoinOrg } - -function JoinOrg.create(initiator, org, id) - local inst = { - name = "Join an org", - desc = "Initiator chooses an org to become a member of. Nothing happens if they are already in an org.", - initiator = initiator, - org = org, - id = id, - votes_yes = 0 - } - setmetatable(inst, JoinOrg_mt) - return inst - -end +JoinOrg.setup = { + name = "Join an org", + desc = "Initiator chooses an org to become a member of. Nothing happens if they are already in an org.", + votes_yes = 0 +} function JoinOrg:initiate(result) modpol.interactions.binary_poll_user( @@ -33,8 +23,6 @@ function JoinOrg:initiate(result) end ) - - if result then result() end end diff --git a/modpol/modules/join_org_consent.lua b/modpol/modules/join_org_consent.lua new file mode 100644 index 0000000..cc02d4e --- /dev/null +++ b/modpol/modules/join_org_consent.lua @@ -0,0 +1,30 @@ + + +JoinOrg = {} + +JoinOrg.setup = { + name = "Join an org", + slug = "join_org_consent", + desc = "Consent based join org module" +} + +function JoinOrg:initiate() + self.org:call_module( + "consent", + self.initiator, + { + prompt = "Allow " .. self.initiator .. " to join?", + votes_required = 1 + }, + function () + self:complete() + end + ) +end + +function JoinOrg:complete() + self.org:add_member(self.initiator) + print("Added " .. self.initiator .. " to the org!") +end + +modpol.modules.join_org_consent = JoinOrg \ No newline at end of file diff --git a/modpol/modules/template.lua b/modpol/modules/template.lua new file mode 100644 index 0000000..7a3fbc6 --- /dev/null +++ b/modpol/modules/template.lua @@ -0,0 +1,39 @@ +--- Template for modules +-- function initiate and table setup are required as a base. +-- @module Template +Template = {} + +--- (Required): setup table containing name and description of the module +-- @field name "Module Human-Readable Name" +-- @field slug "Template" same as module name +-- @field desc "Description of the module" +Template.setup = { + name = "Module Human-Readable Name", + slug = "Template", + desc = "Description of the module" +} + +--- (Optional): config for module +-- Defines the input parameters to the module initiate function. +-- When calling a module from within another module, +-- variables not defined in config will be ignored. +-- Default values set in config can be overridden +-- @field field_1 ex: votes_required, default = 5 +-- @field field_2 ex: voting_type, default = "majority" +Template.config = { + field_1 = 5 + field_2 = "majority" +} + +--- (Required): initiate function +-- Modules have access to the following instance variables: +--
  • self.org (the org the module was called in),
  • +--
  • self.initiator (the user that callced the module),
  • +--
  • self.id (the process id of the module instance)
  • +-- @function initiate +function Template:initiate(config, result) + -- call interaction functions here! + + -- call result function + if result then result() end +end diff --git a/modpol/orgs/process.lua b/modpol/orgs/process.lua index d514f5b..1b963ed 100644 --- a/modpol/orgs/process.lua +++ b/modpol/orgs/process.lua @@ -1,6 +1,6 @@ -function modpol.orgs:call_module(module_name, initiator) +function modpol.orgs:call_module(module_name, initiator, config, result) if not modpol.modules[module_name] then - modpol.ocutil.log('Error in ' .. self.name .. ':call_module -> module "' .. name .. '" not found') + modpol.ocutil.log('Error in ' .. self.name .. ':call_module -> module "' .. module_name .. '" not found') return end @@ -22,11 +22,34 @@ function modpol.orgs:call_module(module_name, initiator) end local module = modpol.modules[module_name] - local new_process = module.create(initiator, self, index) + + -- sets default values for undeclared config variables + if module.config then + for k, v in pairs(module.config) do + if config[k] == nil then + config[k] = v + end + end + end + + -- setting default params + local new_process = { + metatable = {__index = module}, + initiator = initiator, + org = self, + id = index, + config = config + } + + -- copying default fields from setup + for k, v in pairs(module.setup) do + new_process[k] = v + end + + setmetatable(new_process, new_process.metatable) self.processes[index] = new_process - - self.processes[index]:initiate() + self.processes[index]:initiate(result) return index end diff --git a/modpol/tests/nested_functions.lua b/modpol/tests/nested_functions.lua deleted file mode 100644 index 914d68f..0000000 --- a/modpol/tests/nested_functions.lua +++ /dev/null @@ -1,31 +0,0 @@ -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") - diff --git a/modpol/tests/nested_module_test.lua b/modpol/tests/nested_module_test.lua new file mode 100644 index 0000000..611a616 --- /dev/null +++ b/modpol/tests/nested_module_test.lua @@ -0,0 +1,13 @@ +dofile('../modpol.lua'); + +modpol.orgs.reset() + +test_org = modpol.instance:add_org('test_org', 'luke') +test_org:add_member('nathan') + +print(table.concat(test_org:list_members(), ", ")) + +test_org:call_module( + "join_org_consent", + "paul" +) \ No newline at end of file