interactions.lua 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. -- INTERACTIONS.LUA (CLI)
  2. -- User interaction functions for Modular Politics
  3. -- Called by modpol.lua
  4. modpol.interactions = {}
  5. -- DASHBOARDS
  6. -- ==========
  7. -- Function: modpol.interactions.dashboard(user)
  8. -- Params: user (string)
  9. -- Q: Should this return a menu of commands relevant to the specific user?
  10. -- Output: Displays a menu of commands to the user
  11. -- TKTK currently just prints all of modpol---needs major improvement
  12. function modpol.interactions.dashboard(user)
  13. -- adds user to root org if not already in it
  14. if not modpol.instance:has_member(user) then
  15. modpol.instance:add_member(user)
  16. end
  17. local all_users = modpol.instance:list_members()
  18. print('All orgs: (user orgs indicated by *)')
  19. for id, org in ipairs(modpol.orgs.array) do
  20. if type(org) == "table" then
  21. local indicator = ""
  22. if org:has_member(user) then indicator = "*" end
  23. print('['..id..'] '..indicator..org.name)
  24. end
  25. end
  26. -- pending list
  27. local user_pending = {}
  28. local user_pending_count = 0
  29. for k,v in ipairs(modpol.orgs.array) do
  30. if v.pending and v.pending[user] then
  31. modpol.msg(v.name)
  32. table.insert(user_pending, v.name)
  33. user_pending_count = user_pending_count + 1
  34. end
  35. end
  36. print('Pending actions in: '..table.concat(user_pending,', '))
  37. print('All users: ' .. table.concat(all_users, ', '))
  38. print()
  39. print('Access which org id?')
  40. local sel = io.read()
  41. print()
  42. if modpol.orgs.array[tonumber(sel)] then
  43. local sel_org = modpol.orgs.array[tonumber(sel)].name
  44. modpol.interactions.org_dashboard(user, sel_org)
  45. else
  46. print("Org id not found.")
  47. end
  48. end
  49. -- Function: modpol.interactions.org_dashboard
  50. -- Params: user (string), org_string (string or id)
  51. -- Output: Displays a menu of org-specific commands to the user
  52. function modpol.interactions.org_dashboard(user, org_string)
  53. local org = modpol.orgs.get_org(org_string)
  54. if not org then return nil end
  55. -- identify parent
  56. local parent = ""
  57. if org.id == 1 then
  58. parent = "none"
  59. else
  60. parent = modpol.orgs.get_org(org.parent).name
  61. end
  62. -- identify children
  63. local children = {}
  64. for k,v in ipairs(org.children) do
  65. local this_child = modpol.orgs.get_org(v)
  66. table.insert(children, this_child.name)
  67. end
  68. -- list available modules
  69. local org_modules = {}
  70. for k,v in pairs(org.modules) do
  71. if not v.hide then
  72. table.insert(org_modules, v.slug)
  73. end
  74. end
  75. -- list pending
  76. local process_msg = #org.processes .. " total processes"
  77. if org.pending[user] then
  78. process_msg = process_msg .. " (" .. #org.pending[user] .. " pending)"
  79. else
  80. process_msg = process_msg .. " (0 pending)"
  81. end
  82. -- set up output
  83. print("Org: " .. org.name)
  84. print("Parent: " .. parent)
  85. print("Members: " .. table.concat(org.members, ", "))
  86. print("Children: " .. table.concat(children, ", "))
  87. print("Modules: " .. table.concat(org_modules, ", "))
  88. print("Pending: " .. process_msg)
  89. print()
  90. print("Commands: (M)odules, (P)ending")
  91. local sel = io.read()
  92. print()
  93. if sel == 'm' or sel == 'M' then
  94. print("Type module name: ")
  95. local module_sel = io.read()
  96. print()
  97. local module_result = false
  98. for k,v in ipairs(org_modules) do
  99. if v == module_sel then
  100. module_result = true
  101. end
  102. end
  103. if module_result then
  104. org:call_module(module_sel, user)
  105. else
  106. print("Error: Module not found.")
  107. end
  108. elseif sel == 'a' or sel == 'A' then
  109. local processes = {}
  110. print("All processes: (* indicates pending)")
  111. for k,v in ipairs(org.processes) do
  112. local active = ''
  113. if org.pending[user] then
  114. if org.pending[user][v.id] then
  115. active = '*'
  116. end
  117. end
  118. end
  119. print()
  120. print("Interact with which one?")
  121. local to_interact = io.read()
  122. local process = org.processes[tonumber(to_interact)]
  123. if not process then return end
  124. if org:has_pending_actions(user) then
  125. if org.pending[user][process.id] then
  126. org:interact(process.id, user)
  127. end
  128. end
  129. else
  130. print("Command not found")
  131. modpol.interactions.org_dashboard(user, org.name)
  132. end
  133. end
  134. -- Function: modpol.interactions.policy_dashboard
  135. -- input: user (string), org_id (int), policy (string)
  136. -- if policy is nil, enables creating a new policy
  137. -- output: opens a dashboard for viewing/editing policy details
  138. -- TODO
  139. -- Function: modpol.interactions.message
  140. -- input: user (string), message (string)
  141. -- output: prints message to CLI
  142. function modpol.interactions.message(user, message)
  143. print(user .. ": " .. message)
  144. end
  145. -- Function: modpol.interactions.text_query
  146. -- input: User (string), Query (string), func (function)
  147. -- func input: user input (string)
  148. -- output: Applies "func" to user input
  149. function modpol.interactions.text_query(user, query, func)
  150. print(user .. ": " .. query)
  151. answer = io.read()
  152. func(answer)
  153. end
  154. -- Function: dropdown_query
  155. -- input: user (string), label (string), options (table of strings), func(choice) (function)
  156. -- func input: choice (string)
  157. -- output: calls func on choice
  158. function modpol.interactions.dropdown_query(user, label, options, func)
  159. -- set up options
  160. local options_display = ""
  161. local options_number = 0
  162. for k,v in ipairs(options) do
  163. options_display = options_display .. k .. ". " ..
  164. options[k] .. "\n"
  165. options_number = options_number + 1
  166. end
  167. options_display = options_display .. "Select number:"
  168. if options_number == 0 then
  169. print("Error: No options given for dropdown")
  170. return nil
  171. end
  172. -- begin displaying
  173. print(user .. ": " .. label)
  174. print(options_display)
  175. -- read input and produce output
  176. local answer
  177. answer = io.read()
  178. answer = tonumber(answer)
  179. if answer then
  180. if answer >= 1 and answer <= options_number then
  181. print("Selection: " .. options[answer])
  182. func(options[answer])
  183. else
  184. print("Error: Not in dropdown range")
  185. return nil
  186. end
  187. else
  188. print("Error: Must be a number")
  189. return nil
  190. end
  191. end
  192. -- Function: modpol.binary_poll_user(user, question)
  193. -- Params: user (string), question (string), func (function)
  194. -- func input: user input (string: y/n)
  195. -- Output: Applies "func" to user input
  196. function modpol.interactions.binary_poll_user(user, question, func)
  197. local query = "Poll for " .. user .. " (y/n): ".. question
  198. local answer
  199. repeat
  200. print(query)
  201. answer = io.read()
  202. until answer == "y" or answer == "n"
  203. if answer == "y" then
  204. modpol.interactions.message(user, "Response recorded")
  205. func("Yes")
  206. elseif answer == "n" then
  207. modpol.interactions.message(user, "Response recorded")
  208. func("No")
  209. else
  210. modpol.interactions.message(user, "Error: invalid response")
  211. end
  212. end
  213. -- COMPLEX INTERACTIONS
  214. -- ====================
  215. -- Function: modpol.interactions.message_org
  216. -- input: initiator (string), org (number or string), message (string)
  217. -- output: broadcasts message to all org members
  218. function modpol.interactions.message_org(initiator, org, message)
  219. local this_org = modpol.orgs.get_org(org)
  220. local users = this_org:list_members()
  221. for k,v in ipairs(users) do
  222. modpol.interactions.message(v, message)
  223. end
  224. end
  225. -- Function: modpol.interactions.binary_poll_org
  226. -- input: initator (user string), org_id (number)
  227. -- output: gets question from initiator, asks all org members, broadcasts answers