xavierlebel

tableUtils

Jan 30th, 2025 (edited)
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.06 KB | None | 0 0
  1. -- tableUtils18.lua
  2.  
  3. local tableUtils = {}
  4.  
  5. -- Writes text with specified colors and restores original colors afterward
  6. function tableUtils.writeText(target, text, textColor, backgroundColor, y, fillLine)
  7. local originalTextColor = target.getTextColor()
  8. local originalBackgroundColor = target.getBackgroundColor()
  9. local width = target.getSize()
  10.  
  11. if y then
  12. target.setCursorPos(1, y)
  13. end
  14.  
  15. target.setTextColor(textColor)
  16. target.setBackgroundColor(backgroundColor)
  17.  
  18. if fillLine then
  19. text = text .. string.rep(" ", width - #text)
  20. end
  21.  
  22. target.write(text)
  23.  
  24. target.setTextColor(originalTextColor)
  25. target.setBackgroundColor(originalBackgroundColor)
  26. end
  27.  
  28. -- Formats a number into a string with two decimal places
  29. function tableUtils.formatDecimals(value)
  30. if type(value) == "number" then
  31. return string.format("%.2f", value)
  32. end
  33. return tostring(value or "N/A")
  34. end
  35.  
  36. -- Formats a string to keep only the first letter and make it capital
  37. function tableUtils.formatFirstLetterCapital(value)
  38. if type(value) == "string" and value ~= "" then
  39. return string.upper(string.sub(value, 1, 1))
  40. end
  41. return "N/A"
  42. end
  43.  
  44. -- Formats a location table into a string (e.g., "x, y, z")
  45. function tableUtils.formatLocation(v)
  46. if type(v) == "table" and v.x and v.y and v.z then
  47. return string.format("%d, %d, %d", v.x, v.y, v.z)
  48. else
  49. return "N/A"
  50. end
  51. end
  52.  
  53. -- Formats a list of resources into a comma-separated string
  54. function tableUtils.formatResources(resources)
  55. if type(resources) ~= "table" then return "N/A" end
  56. local names = {}
  57. for _, resource in ipairs(resources) do
  58. table.insert(names, resource.displayName or "N/A")
  59. end
  60. return table.concat(names, ", ")
  61. end
  62.  
  63. -- Sums a specific field in a table of items
  64. function tableUtils.sumFieldInTable(data, fieldToSum)
  65. if not data or type(data) ~= "table" or #data == 0 then
  66. return "N/A"
  67. end
  68.  
  69. local total = 0
  70.  
  71. for _, item in ipairs(data) do
  72. if item[fieldToSum] then
  73. total = total + item[fieldToSum]
  74. end
  75. end
  76.  
  77. return total
  78. end
  79.  
  80. -- Processes records into rows based on the provided fields
  81. function tableUtils.processRecords(records, fields)
  82. local rows = {}
  83. for _, record in ipairs(records) do
  84. local row = {}
  85. for _, field in ipairs(fields) do
  86. local parts = {}
  87. for part in field.path:gmatch("[^.]+") do
  88. table.insert(parts, part)
  89. end
  90.  
  91. local value = record
  92. for _, part in ipairs(parts) do
  93. value = value[part]
  94. if value == nil then break end
  95. end
  96.  
  97. if field.formatter then
  98. value = field.formatter(value) or "N/A"
  99. else
  100. if type(value) == "boolean" then
  101. value = value and "True" or "False"
  102. else
  103. value = tostring(value or "N/A")
  104. end
  105. end
  106.  
  107. table.insert(row, value)
  108. end
  109. table.insert(rows, row)
  110. end
  111. return rows
  112. end
  113.  
  114. -- Flattens nested records into a single list, extracting a specific field
  115. function tableUtils.flattenRecords(data, field)
  116. if not data or type(data) ~= "table" or #data == 0 then
  117. return "N/A"
  118. end
  119.  
  120. local records = {}
  121. for _, outerTable in ipairs(data) do
  122. if outerTable and outerTable[field] then
  123. table.insert(records, outerTable[field])
  124. end
  125. end
  126.  
  127. if #records == 0 then
  128. return "N/A"
  129. end
  130.  
  131. return table.concat(records, ", ")
  132. end
  133.  
  134. -- Sorts records based on the provided sort configuration
  135. function tableUtils.sortRecords(records, sortConfig)
  136. if not sortConfig then return records end
  137.  
  138. table.sort(records, function(a, b)
  139. local parts = {}
  140. for part in sortConfig.field:gmatch("[^.]+") do
  141. table.insert(parts, part)
  142. end
  143.  
  144. local valueA = a
  145. local valueB = b
  146.  
  147. for _, part in ipairs(parts) do
  148. valueA = valueA and valueA[part]
  149. valueB = valueB and valueB[part]
  150. end
  151.  
  152. if valueA == nil then return false end
  153. if valueB == nil then return true end
  154.  
  155. local numA, numB = tonumber(valueA), tonumber(valueB)
  156.  
  157. if numA and numB then
  158. if sortConfig.direction == "desc" then
  159. return numA > numB
  160. else
  161. return numA < numB
  162. end
  163. else
  164. if sortConfig.direction == "desc" then
  165. return tostring(valueA) > tostring(valueB)
  166. else
  167. return tostring(valueA) < tostring(valueB)
  168. end
  169. end
  170. end)
  171.  
  172. return records
  173. end
  174.  
  175. -- Calculates column widths based on the provided fields and rows
  176. function tableUtils.calculateColumnWidths(rows, fields)
  177. local colWidths = {}
  178. for i, field in ipairs(fields) do
  179. colWidths[i] = #field.header
  180. for _, row in ipairs(rows) do
  181. colWidths[i] = math.max(colWidths[i], #row[i])
  182. end
  183. colWidths[i] = colWidths[i] + 1 -- Add padding
  184. end
  185. return colWidths
  186. end
  187.  
  188. -- Builds a formatted line for output
  189. function tableUtils.buildLine(values, colWidths)
  190. local line = ""
  191. for i, value in ipairs(values) do
  192. line = line .. value .. " " .. string.rep(" ", colWidths[i] - #value - 1)
  193. end
  194. return line
  195. end
  196.  
  197. -- Generates the final output for display
  198. function tableUtils.generateOutput(rows, colWidths, fields)
  199. local output = {
  200. tableUtils.buildLine((function()
  201. local t = {}
  202. for _, field in ipairs(fields) do
  203. table.insert(t, field.header)
  204. end
  205. return t
  206. end)(), colWidths)
  207. }
  208.  
  209. for _, row in ipairs(rows) do
  210. table.insert(output, tableUtils.buildLine(row, colWidths))
  211. end
  212.  
  213. return output
  214. end
  215.  
  216. -- Displays data on a monitor or terminal
  217. function tableUtils.displayData(target, titleLines, header, pageData, currentPage, totalPages, totalRecords)
  218. target.clear()
  219. if target.setTextScale then
  220. target.setTextScale(1)
  221. end
  222. local width, height = target.getSize()
  223.  
  224. local paginationText = string.format("Page %d/%d", currentPage, totalPages)
  225.  
  226. local titleLine = titleLines[1]
  227.  
  228. local originalTextColor = target.getTextColor()
  229. local originalBgColor = target.getBackgroundColor()
  230.  
  231. target.setCursorPos(1, 1)
  232. target.setBackgroundColor(titleLine.bgColor)
  233. target.clearLine()
  234.  
  235. target.setCursorPos(1, 1)
  236. tableUtils.writeText(target, titleLine.text, titleLine.textColor, titleLine.bgColor, nil, false)
  237.  
  238. target.setCursorPos(width - #paginationText + 1, 1)
  239. tableUtils.writeText(target, paginationText, colors.white, titleLine.bgColor, nil, false)
  240.  
  241. target.setTextColor(originalTextColor)
  242. target.setBackgroundColor(originalBgColor)
  243.  
  244. for i = 2, #titleLines do
  245. tableUtils.writeText(target, titleLines[i].text, titleLines[i].textColor, titleLines[i].bgColor, i, true)
  246. end
  247.  
  248. tableUtils.writeText(target, header, colors.gray, colors.black, #titleLines + 1, false)
  249.  
  250. local lineY = #titleLines + 2
  251. for _, line in ipairs(pageData) do
  252. if lineY >= height then break end
  253. target.setCursorPos(1, lineY)
  254. target.setTextColor(colors.white)
  255. target.write(line)
  256. lineY = lineY + 1
  257. end
  258.  
  259. target.setTextColor(originalTextColor)
  260. target.setBackgroundColor(originalBgColor)
  261. end
  262.  
  263. -- Prepares data for display on a monitor or terminal
  264. function tableUtils.preparePageData(data, fields, target)
  265. local rows = tableUtils.processRecords(data, fields)
  266. local colWidths = tableUtils.calculateColumnWidths(rows, fields)
  267. local output = tableUtils.generateOutput(rows, colWidths, fields)
  268. return {
  269. header = output[1],
  270. dataLines = {unpack(output, 2, #output)},
  271. width = target.getSize(),
  272. height = select(2, target.getSize())
  273. }
  274. end
  275.  
  276. -- Returns a table containing the current page data and pagination information
  277. function tableUtils.getPageInfo(dataLines, currentPage, pageSize)
  278. local totalPages = math.max(math.ceil(#dataLines / pageSize), 1)
  279. currentPage = ((currentPage - 1) % totalPages) + 1
  280. local startIdx = (currentPage - 1) * pageSize + 1
  281. return {
  282. pageData = {unpack(dataLines, startIdx, math.min(currentPage * pageSize, #dataLines))},
  283. currentPage = currentPage,
  284. totalPages = totalPages
  285. }
  286. end
  287.  
  288. -- Refreshes data at regular intervals
  289. function tableUtils.refreshData(config, state, collectDataCallback)
  290. while true do
  291. state.data, state.totalRecords = collectDataCallback(config)
  292. state.data = tableUtils.sortRecords(state.data, config.sort)
  293. state.needsRefresh = true
  294. sleep(config.refreshInterval)
  295. end
  296. end
  297.  
  298. -- Renders the UI on a monitor and terminal
  299. function tableUtils.renderUI(config, state)
  300. while true do
  301. if state.needsRefresh then
  302. local monitorPage = tableUtils.preparePageData(state.data or {}, config.monitorFields, config.peripherals.monitor)
  303. local terminalPage = tableUtils.preparePageData(state.data or {}, config.terminalFields, term)
  304.  
  305. state.monitorInfo = tableUtils.getPageInfo(monitorPage.dataLines, state.currentPageMonitor, monitorPage.height - 4)
  306. state.terminalInfo = tableUtils.getPageInfo(terminalPage.dataLines, state.currentPageTerminal, terminalPage.height - 4)
  307.  
  308. local titleLines = {
  309. {text = config.title.." ("..state.totalRecords..")", textColor = colors.white, bgColor = colors.blue},
  310. {text = "ALERT MESSAGES", textColor = colors.white, bgColor = colors.red}
  311. }
  312.  
  313. tableUtils.displayData(config.peripherals.monitor, titleLines, monitorPage.header, state.monitorInfo.pageData, state.monitorInfo.currentPage, state.monitorInfo.totalPages, state.totalRecords)
  314. tableUtils.displayData(term, titleLines, terminalPage.header, state.terminalInfo.pageData, state.terminalInfo.currentPage, state.terminalInfo.totalPages, state.totalRecords)
  315.  
  316. state.needsRefresh = false
  317. end
  318. sleep(0.1)
  319. end
  320. end
  321.  
  322. -- Handles input from the monitor and terminal
  323. function tableUtils.handleInput(state)
  324. while true do
  325. parallel.waitForAny(
  326. function()
  327. os.pullEvent("monitor_touch")
  328. state.currentPageMonitor = (state.currentPageMonitor % state.monitorInfo.totalPages) + 1
  329. state.needsRefresh = true
  330. end,
  331. function()
  332. os.pullEvent("mouse_click")
  333. state.currentPageTerminal = (state.currentPageTerminal % state.terminalInfo.totalPages) + 1
  334. state.needsRefresh = true
  335. end
  336. )
  337. end
  338. end
  339.  
  340. return tableUtils
  341.  
  342.  
Advertisement
Add Comment
Please, Sign In to add comment