interactions.lua 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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.list_users()
  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. print('All users: ' .. table.concat(all_users, ', '))
  27. print()
  28. print('Access which org?')
  29. local sel = io.read()
  30. print()
  31. local sel_org = modpol.orgs.array[tonumber(sel)].name
  32. if not sel_org then return end
  33. modpol.interactions.org_dashboard(user, sel_org)
  34. end
  35. -- Function: modpol.interactions.org_dashboard
  36. -- Params: user (string), org_name (string)
  37. -- Output: Displays a menu of org-specific commands to the user
  38. function modpol.interactions.org_dashboard(user, org_name)
  39. local org = modpol.orgs.get_org(org_name)
  40. if not org then return nil end
  41. local parent = ""
  42. if org.id == 1 then
  43. parent = "none"
  44. else
  45. parent = modpol.orgs.get_org(org.parent).name
  46. end
  47. local children = {}
  48. for k,v in ipairs(org.children) do
  49. local this_child = modpol.orgs.get_org(v)
  50. table.insert(children, this_child.name)
  51. end
  52. local process_msg = #org.processes .. " total"
  53. if org.pending[user] then
  54. process_msg = process_msg .. " (" .. #org.pending[user] .. " pending)"
  55. else
  56. process_msg = process_msg .. " (0 pending)"
  57. end
  58. -- set up output
  59. print("Org: " .. org_name)
  60. print("Parent: " .. parent)
  61. print("Members: " .. table.concat(org.members, ", "))
  62. print("Children: " .. table.concat(children, ", "))
  63. print("Processes: " .. process_msg)
  64. print()
  65. print("Commands: (L)eave, (J)oin, (P)rocesses, (A)dd child, (D)elete org")
  66. local sel = io.read()
  67. print()
  68. if sel == 'l' or sel == 'L' then
  69. org:remove_member(user)
  70. elseif sel == 'j' or sel == 'J' then
  71. org:make_request({user=user, type="add_member", params={user}})
  72. elseif sel == 'a' or sel == 'A' then
  73. print("What should the new org be named?")
  74. local new_org_name = io.read()
  75. org:make_request({user=user, type="add_org", params={new_org_name}})
  76. elseif sel == 'd' or sel == 'D' then
  77. org:make_request({user=user, type="delete", params={}})
  78. elseif sel == 'p' or sel == 'P' then
  79. local processes = {}
  80. print("All processes: (* indicates pending action)")
  81. for k,v in ipairs(org.processes) do
  82. local this_request = org.requests[v.request_id]
  83. if type(this_request) == "table" then
  84. local active = ''
  85. if org.pending[user] then
  86. if org.pending[user][v.id] then
  87. active = '*'
  88. end
  89. end
  90. local req_str = "[" .. v.id .. "] " ..
  91. active .. this_request.type
  92. if this_request.params[1] then
  93. req_str = req_str .. ": " ..
  94. table.concat(this_request.params, ", ")
  95. end
  96. print(req_str)
  97. end
  98. end
  99. print()
  100. print("Interact with which one?")
  101. local to_interact = io.read()
  102. local process = org.processes[tonumber(to_interact)]
  103. if not process then return end
  104. if org:has_pending_actions(user) then
  105. if org.pending[user][process.id] then
  106. process:interact(user)
  107. end
  108. end
  109. end
  110. end
  111. -- Function: modpol.interactions.policy_dashboard
  112. -- input: user (string), org_id (int), policy (string)
  113. -- if policy is nil, enables creating a new policy
  114. -- output: opens a dashboard for viewing/editing policy details
  115. -- TODO
  116. -- Function: modpol.interactions.message
  117. -- input: user (string), message (string)
  118. -- output: prints message to CLI
  119. function modpol.interactions.message(user, message)
  120. print(user .. ": " .. message)
  121. end
  122. -- Function: modpol.interactions.text_query
  123. -- input: User (string), Query (string), func (function)
  124. -- func input: user input (string)
  125. -- output: Applies "func" to user input
  126. function modpol.interactions.text_query(user, query, func)
  127. print(user .. ": " .. query)
  128. answer = io.read()
  129. func(answer)
  130. end
  131. -- Function: dropdown_query
  132. -- input: user (string), label (string), options (table of strings), func(choice) (function)
  133. -- func input: choice (string)
  134. -- output: calls func on choice
  135. function modpol.interactions.dropdown_query(user, label, options, func)
  136. -- set up options
  137. local options_display = ""
  138. local options_number = 0
  139. for k,v in ipairs(options) do
  140. options_display = options_display .. k .. ". " ..
  141. options[k] .. "\n"
  142. options_number = options_number + 1
  143. end
  144. options_display = options_display .. "Select number:"
  145. if options_number == 0 then
  146. print("Error: No options given for dropdown")
  147. return nil
  148. end
  149. -- begin displaying
  150. print(user .. ": " .. label)
  151. print(options_display)
  152. -- read input and produce output
  153. local answer
  154. answer = io.read()
  155. answer = tonumber(answer)
  156. if answer then
  157. if answer >= 1 and answer <= options_number then
  158. print("Selection: " .. options[answer])
  159. func(options[answer])
  160. else
  161. print("Error: Not in dropdown range")
  162. return nil
  163. end
  164. else
  165. print("Error: Must be a number")
  166. return nil
  167. end
  168. end
  169. -- Function: modpol.binary_poll_user(user, question)
  170. -- Params: user (string), question (string), func (function)
  171. -- func input: user input (string: y/n)
  172. -- Output: Applies "func" to user input
  173. function modpol.interactions.binary_poll_user(user, question, func)
  174. local query = "Poll for " .. user .. " (y/n): ".. question
  175. local answer
  176. repeat
  177. print(query)
  178. answer = io.read()
  179. until answer == "y" or answer == "n"
  180. if answer == "y" then
  181. modpol.interactions.message(user, "Response recorded")
  182. func("Yes")
  183. elseif answer == "n" then
  184. modpol.interactions.message(user, "Response recorded")
  185. func("No")
  186. else
  187. modpol.interactions.message(user, "Error: invalid response")
  188. end
  189. end
  190. -- COMPLEX INTERACTIONS
  191. -- ====================
  192. -- Function: modpol.interactions.message_org
  193. -- input: initiator (string), org_id (number), message (string)
  194. -- output: broadcasts message to all org members
  195. -- Function: modpol.interactions.binary_poll_org
  196. -- input: initator (user string), org_id (number)
  197. -- output: gets question from initiator, asks all org members, broadcasts answers