SHOW:
|
|
- or go back to the newest paste.
1 | - | -- RSWarehouse.lua |
1 | + | -- RSWarehouse.lua |
2 | - | -- Author: Chuck Burgess |
2 | + | |
3 | - | -- Updated: 2024-01-15 |
3 | + | -- Author: Chuck Burgess |
4 | - | |
4 | + | |
5 | - | local logFile = "RSWarehouse.log" |
5 | + | -- Updated: 2024-01-15 |
6 | - | local time_between_runs = 30 |
6 | + | |
7 | - | |
7 | + | |
8 | - | -- Initialize Monitor |
8 | + | |
9 | - | -- see: https://www.computercraft.info/wiki/Advanced_Monitor |
9 | + | local logFile = "RSWarehouse.log" |
10 | - | local monitor = peripheral.find("monitor") |
10 | + | |
11 | - | if not monitor then error("Monitor not found.") end |
11 | + | local time_between_runs = 30 |
12 | - | monitor.setTextScale(0.5) |
12 | + | |
13 | - | monitor.clear() |
13 | + | |
14 | - | monitor.setCursorPos(1, 1) |
14 | + | |
15 | - | monitor.setCursorBlink(false) |
15 | + | -- Initialize Monitor |
16 | - | print("Monitor initialized.") |
16 | + | |
17 | - | |
17 | + | -- see: https://www.computercraft.info/wiki/Advanced_Monitor |
18 | - | -- Initialize RS Bridge |
18 | + | |
19 | - | -- see: https://advancedperipherals.madefor.cc/peripherals/rs_bridge/ |
19 | + | local monitor = peripheral.find("monitor") |
20 | - | local bridge = peripheral.find("rsBridge") |
20 | + | |
21 | - | if not bridge then error("RS Bridge not found.") end |
21 | + | if not monitor then error("Monitor not found.") end |
22 | - | print("RS Bridge initialized.") |
22 | + | |
23 | - | |
23 | + | monitor.setTextScale(0.5) |
24 | - | -- Initialize Colony Integrator |
24 | + | |
25 | - | -- see: https://docs.advanced-peripherals.de/peripherals/colony_integrator/ |
25 | + | monitor.clear() |
26 | - | local colony = peripheral.find("colonyIntegrator") |
26 | + | |
27 | - | if not colony then error("Colony Integrator not found.") end |
27 | + | monitor.setCursorPos(1, 1) |
28 | - | if not colony.isInColony then error("Colony Integrator is not in a colony.") end |
28 | + | |
29 | - | print("Colony Integrator initialized.") |
29 | + | monitor.setCursorBlink(false) |
30 | - | |
30 | + | |
31 | - | -- Establish the direction to transport the items into the Warehouse based on |
31 | + | print("Monitor initialized.") |
32 | - | -- where the entnglement block is sitting. Default to empty string. |
32 | + | |
33 | - | local storage = peripheral.find("entangled:tile") |
33 | + | |
34 | - | if not storage then error("Warehouse storage not found.") end |
34 | + | |
35 | - | local direction = "" |
35 | + | -- Initialize RS Bridge |
36 | - | local names = peripheral.getNames() |
36 | + | |
37 | - | for _, pos in ipairs(names) do |
37 | + | -- see: https://advancedperipherals.madefor.cc/peripherals/rs_bridge/ |
38 | - | if peripheral.getType(pos) == "entangled:tile" then |
38 | + | |
39 | - | direction = pos |
39 | + | local bridge = peripheral.find("rsBridge") |
40 | - | end |
40 | + | |
41 | - | end |
41 | + | if not bridge then error("RS Bridge not found.") end |
42 | - | print("Warehouse storage initialized.") |
42 | + | |
43 | - | |
43 | + | print("RS Bridge initialized.") |
44 | - | ---------------------------------------------------------------------------- |
44 | + | |
45 | - | -- FUNCTIONS |
45 | + | |
46 | - | ---------------------------------------------------------------------------- |
46 | + | |
47 | - | --[[ |
47 | + | -- Initialize Colony Integrator |
48 | - | Table.Empty |
48 | + | |
49 | - | @desc check to see if a table contains any data |
49 | + | -- see: https://docs.advanced-peripherals.de/peripherals/colony_integrator/ |
50 | - | @return boolean |
50 | + | |
51 | - | ]] |
51 | + | local colony = peripheral.find("colonyIntegrator") |
52 | - | function table.empty (self) |
52 | + | |
53 | - | for _, _ in pairs(self) do |
53 | + | if not colony then error("Colony Integrator not found.") end |
54 | - | return false |
54 | + | |
55 | - | end |
55 | + | if not colony.isInColony then error("Colony Integrator is not in a colony.") end |
56 | - | return true |
56 | + | |
57 | - | end |
57 | + | print("Colony Integrator initialized.") |
58 | - | |
58 | + | |
59 | - | --[[ |
59 | + | |
60 | - | Write To Log |
60 | + | |
61 | - | @desc Write the specified `table` to the file surrounded by the `blockTop` and `blockBottom` |
61 | + | -- Establish the direction to transport the items into the Warehouse based on |
62 | - | @return void |
62 | + | |
63 | - | ]] |
63 | + | -- where the entnglement block is sitting. Default to empty string. |
64 | - | function writeToLog(data, blockTop, blockBottom) |
64 | + | |
65 | - | file.write("\n") |
65 | + | local storage = peripheral.find("entangled:tile") |
66 | - | file.write(blockTop) |
66 | + | |
67 | - | file.write("\n") |
67 | + | if not storage then error("Warehouse storage not found.") end |
68 | - | file.write(textutils.serialize(data, { allow_repetitions = true })) |
68 | + | |
69 | - | file.write("\n") |
69 | + | local direction = "" |
70 | - | file.write(blockBottom) |
70 | + | |
71 | - | file.write("\n") |
71 | + | local names = peripheral.getNames() |
72 | - | end |
72 | + | |
73 | - | |
73 | + | for _, pos in ipairs(names) do |
74 | - | --[[ |
74 | + | |
75 | - | Process Work Request Item |
75 | + | if peripheral.getType(pos) == "entangled:tile" then |
76 | - | @desc Determine if this item can be delivered to the warehouse from the storage |
76 | + | |
77 | - | @return boolean |
77 | + | direction = pos |
78 | - | ]] |
78 | + | |
79 | - | function processWorkRequestItem(request) |
79 | + | end |
80 | - | if string.find(request.desc, "Tool of class") then return false end |
80 | + | |
81 | - | if string.find(request.name, "Hoe") then return false end |
81 | + | end |
82 | - | if string.find(request.name, "Shovel") then return false end |
82 | + | |
83 | - | if string.find(request.name, "Axe") then return false end |
83 | + | print("Warehouse storage initialized.") |
84 | - | if string.find(request.name, "Pickaxe") then return false end |
84 | + | |
85 | - | if string.find(request.name, "Bow") then return false end |
85 | + | |
86 | - | if string.find(request.name, "Sword") then return false end |
86 | + | |
87 | - | if string.find(request.name, "Shield") then return false end |
87 | + | ---------------------------------------------------------------------------- |
88 | - | if string.find(request.name, "Helmet") then return false end |
88 | + | |
89 | - | if string.find(request.name, "Leather Cap") then return false end |
89 | + | -- FUNCTIONS |
90 | - | if string.find(request.name, "Chestplate") then return false end |
90 | + | |
91 | - | if string.find(request.name, "Tunic") then return false end |
91 | + | ---------------------------------------------------------------------------- |
92 | - | if string.find(request.name, "Pants") then return false end |
92 | + | |
93 | - | if string.find(request.name, "Leggings") then return false end |
93 | + | --[[ |
94 | - | if string.find(request.name, "Boots") then return false end |
94 | + | |
95 | - | if request.name == "Rallying Banner" then return false end --bugged in alpha versions |
95 | + | Table.Empty |
96 | - | if request.name == "Crafter" then return false end |
96 | + | |
97 | - | if request.name == "Compostable" then return false end |
97 | + | @desc check to see if a table contains any data |
98 | - | if request.name == "Fertilizer" then return false end |
98 | + | |
99 | - | if request.name == "Flowers" then return false end |
99 | + | @return boolean |
100 | - | if request.name == "Food" then return false end |
100 | + | |
101 | - | if request.name == "Fuel" then return false end |
101 | + | ]] |
102 | - | if request.name == "Smeltable Ore" then return false end |
102 | + | |
103 | - | if request.name == "Stack List" then return false end |
103 | + | function table.empty (self) |
104 | - | -- you can add any new items here if they are found |
104 | + | |
105 | - | return true |
105 | + | for _, _ in pairs(self) do |
106 | - | end |
106 | + | |
107 | - | |
107 | + | return false |
108 | - | --[[ |
108 | + | |
109 | - | Monitor Print Row Justified |
109 | + | end |
110 | - | @desc Print a line of data to the in-game monitor |
110 | + | |
111 | - | @return void |
111 | + | return true |
112 | - | ]] |
112 | + | |
113 | - | function mPrintRowJustified(mon, y, pos, text, textcolor) |
113 | + | end |
114 | - | w, h = mon.getSize() |
114 | + | |
115 | - | fg = colors.white |
115 | + | |
116 | - | bg = colors.black |
116 | + | |
117 | - | |
117 | + | --[[ |
118 | - | if pos == "left" then x = 1 end |
118 | + | |
119 | - | if pos == "center" then x = math.floor((w - #text) / 2) end |
119 | + | Write To Log |
120 | - | if pos == "right" then x = w - #text end |
120 | + | |
121 | - | |
121 | + | @desc Write the specified `table` to the file surrounded by the `blockTop` and `blockBottom` |
122 | - | mon.setTextColor(textcolor) |
122 | + | |
123 | - | mon.setCursorPos(x, y) |
123 | + | @return void |
124 | - | mon.write(text) |
124 | + | |
125 | - | mon.setTextColor(fg) |
125 | + | ]] |
126 | - | mon.setBackgroundColor(bg) |
126 | + | |
127 | - | end |
127 | + | function writeToLog(data, blockTop, blockBottom) |
128 | - | |
128 | + | |
129 | - | --[[ |
129 | + | file.write("\n") |
130 | - | Display Timer |
130 | + | |
131 | - | @desc Update the time on the monitor |
131 | + | file.write(blockTop) |
132 | - | @return void |
132 | + | |
133 | - | ]] |
133 | + | file.write("\n") |
134 | - | function displayTimer(mon, t) |
134 | + | |
135 | - | now = os.time() |
135 | + | file.write(textutils.serialize(data, { allow_repetitions = true })) |
136 | - | cycle = "day" |
136 | + | |
137 | - | cycle_color = colors.orange |
137 | + | file.write("\n") |
138 | - | if now >= 4 and now < 6 then |
138 | + | |
139 | - | cycle = "sunrise" |
139 | + | file.write(blockBottom) |
140 | - | cycle_color = colors.yellow |
140 | + | |
141 | - | elseif now >= 6 and now < 18 then |
141 | + | file.write("\n") |
142 | - | cycle = "day" |
142 | + | |
143 | - | cycle_color = colors.lightBlue |
143 | + | end |
144 | - | elseif now >= 18 and now < 19.5 then |
144 | + | |
145 | - | cycle = "sunset" |
145 | + | |
146 | - | cycle_color = colors.magenta |
146 | + | |
147 | - | elseif now >= 19.5 or now < 5 then |
147 | + | --[[ |
148 | - | cycle = "night" |
148 | + | |
149 | - | cycle_color = colors.red |
149 | + | Process Work Request Item |
150 | - | end |
150 | + | |
151 | - | |
151 | + | @desc Determine if this item can be delivered to the warehouse from the storage |
152 | - | timer_color = colors.green |
152 | + | |
153 | - | if t < 15 then timer_color = colors.yellow end |
153 | + | @return boolean |
154 | - | if t < 5 then timer_color = colors.orange end |
154 | + | |
155 | - | |
155 | + | ]] |
156 | - | mPrintRowJustified(mon, 1, "left", string.format("Time: %s [%s] ", textutils.formatTime(now, false), cycle), cycle_color) |
156 | + | |
157 | - | if cycle ~= "night" then |
157 | + | function processWorkRequestItem(request) |
158 | - | mPrintRowJustified(mon, 1, "right", string.format(" Remaining: %ss", t), timer_color) |
158 | + | |
159 | - | else |
159 | + | if string.find(request.desc, "Tool of class") then return false end |
160 | - | mPrintRowJustified(mon, 1, "right", " Remaining: PAUSED", colors.red) |
160 | + | |
161 | - | end |
161 | + | if string.find(request.name, "Hoe") then return false end |
162 | - | end |
162 | + | |
163 | - | |
163 | + | if string.find(request.name, "Shovel") then return false end |
164 | - | --[[ |
164 | + | |
165 | - | Create Colonist Data |
165 | + | if string.find(request.name, "Axe") then return false end |
166 | - | @desc Build a table of Colonist making the request |
166 | + | |
167 | - | @return table |
167 | + | if string.find(request.name, "Pickaxe") then return false end |
168 | - | ]] |
168 | + | |
169 | - | function createColonistData(colonist) |
169 | + | if string.find(request.name, "Bow") then return false end |
170 | - | title_words = {} |
170 | + | |
171 | - | words_in_name = 0 |
171 | + | if string.find(request.name, "Sword") then return false end |
172 | - | colonist_job = "" |
172 | + | |
173 | - | word_count = 1 |
173 | + | if string.find(request.name, "Shield") then return false end |
174 | - | |
174 | + | |
175 | - | for word in colonist:gmatch("%S+") do |
175 | + | if string.find(request.name, "Helmet") then return false end |
176 | - | table.insert(title_words, word) |
176 | + | |
177 | - | words_in_name = words_in_name + 1 |
177 | + | if string.find(request.name, "Leather Cap") then return false end |
178 | - | end |
178 | + | |
179 | - | |
179 | + | if string.find(request.name, "Chestplate") then return false end |
180 | - | if words_in_name >= 3 then colonist_name = title_words[words_in_name-2] .. " " .. title_words[words_in_name] |
180 | + | |
181 | - | else colonist_name = colonist end |
181 | + | if string.find(request.name, "Tunic") then return false end |
182 | - | |
182 | + | |
183 | - | repeat |
183 | + | if string.find(request.name, "Pants") then return false end |
184 | - | if colonist_job ~= "" then colonist_job = colonist_job .. " " end |
184 | + | |
185 | - | colonist_job = colonist_job .. title_words[word_count] |
185 | + | if string.find(request.name, "Leggings") then return false end |
186 | - | word_count = word_count + 1 |
186 | + | |
187 | - | until word_count > words_in_name - 3 |
187 | + | if string.find(request.name, "Boots") then return false end |
188 | - | |
188 | + | |
189 | - | return { fullName = colonist, titleWords = title_words, job = colonist_job, name = colonist_name, wordsInName = words_in_name } |
189 | + | if request.name == "Rallying Banner" then return false end --bugged in alpha versions |
190 | - | end |
190 | + | |
191 | - | |
191 | + | if request.name == "Crafter" then return false end |
192 | - | --[[ |
192 | + | |
193 | - | Get Work Request List (from colony) |
193 | + | if request.name == "Compostable" then return false end |
194 | - | @desc Build a table of the work request data from the colony |
194 | + | |
195 | - | @return table |
195 | + | if request.name == "Fertilizer" then return false end |
196 | - | ]] |
196 | + | |
197 | - | function getWorkRequestList(colony) |
197 | + | if request.name == "Flowers" then return false end |
198 | - | requestList = {} |
198 | + | |
199 | - | workRequests = colony.getRequests() |
199 | + | if request.name == "Food" then return false end |
200 | - | file = fs.open(logFile, "w") |
200 | + | |
201 | - | |
201 | + | if request.name == "Fuel" then return false end |
202 | - | for w in pairs(workRequests) do |
202 | + | |
203 | - | writeToLog(workRequests[w], "--- Request start ---", "--- Request end ---"); |
203 | + | if request.name == "Smeltable Ore" then return false end |
204 | - | name = workRequests[w].name -- the name of the count/item being requested |
204 | + | |
205 | - | colonist = createColonistData(workRequests[w].target) |
205 | + | if request.name == "Stack List" then return false end |
206 | - | desc = workRequests[w].desc -- the request description |
206 | + | |
207 | - | item = {} |
207 | + | -- you can add any new items here if they are found |
208 | - | -- create the filter item for the transfer request through the bridge |
208 | + | |
209 | - | if workRequests[w].items and workRequests[w].items[1] then |
209 | + | return true |
210 | - | if not workRequests[w].items[1].nbt or table.empty(workRequests[w].items[1].nbt) then |
210 | + | |
211 | - | item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName} |
211 | + | end |
212 | - | else |
212 | + | |
213 | - | item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName, nbt = workRequests[w].items[1].nbt} |
213 | + | |
214 | - | end |
214 | + | |
215 | - | end |
215 | + | --[[ |
216 | - | -- how many items are needed to fulfill this request? |
216 | + | |
217 | - | needed = workRequests[w].count |
217 | + | Monitor Print Row Justified |
218 | - | |
218 | + | |
219 | - | local newRecord = {} |
219 | + | @desc Print a line of data to the in-game monitor |
220 | - | newRecord.name = name |
220 | + | |
221 | - | newRecord.desc = desc |
221 | + | @return void |
222 | - | newRecord.needed = needed |
222 | + | |
223 | - | newRecord.item = item |
223 | + | ]] |
224 | - | newRecord.colonist = colonist |
224 | + | |
225 | - | table.insert(requestList, newRecord) |
225 | + | function mPrintRowJustified(mon, y, pos, text, textcolor) |
226 | - | writeToLog(newRecord, "--- Record start ---", "--- Record end ---"); |
226 | + | |
227 | - | end |
227 | + | w, h = mon.getSize() |
228 | - | file.close() |
228 | + | |
229 | - | return requestList |
229 | + | fg = colors.white |
230 | - | end |
230 | + | |
231 | - | |
231 | + | bg = colors.black |
232 | - | --[[ |
232 | + | |
233 | - | Display List |
233 | + | |
234 | - | @desc Update the monitor with the work request items currently in the system |
234 | + | |
235 | - | @return void |
235 | + | if pos == "left" then x = 1 end |
236 | - | ]] |
236 | + | |
237 | - | function displayList(mon, listName, itemList) |
237 | + | if pos == "center" then x = math.floor((w - #text) / 2) end |
238 | - | -- show the list header first |
238 | + | |
239 | - | mPrintRowJustified(mon, row, "center", listName, colors.white) |
239 | + | if pos == "right" then x = w - #text end |
240 | - | row = row + 1 |
240 | + | |
241 | - | for e in pairs(itemList) do |
241 | + | |
242 | - | record = itemList[e] |
242 | + | |
243 | - | text = string.format("%d %s", record.provided , record.name) |
243 | + | mon.setTextColor(textcolor) |
244 | - | mPrintRowJustified(mon, row, "left", text, record.color) |
244 | + | |
245 | - | mPrintRowJustified(mon, row, "right", " " .. record.colonist, record.color) |
245 | + | mon.setCursorPos(x, y) |
246 | - | row = row + 1 |
246 | + | |
247 | - | end |
247 | + | mon.write(text) |
248 | - | -- add a space at the end of the list |
248 | + | |
249 | - | row = row + 1 |
249 | + | mon.setTextColor(fg) |
250 | - | end |
250 | + | |
251 | - | |
251 | + | mon.setBackgroundColor(bg) |
252 | - | -- Color References: |
252 | + | |
253 | - | -- RED: work order can't be satisfied by Refined Storage (lack of pattern or lack of |
253 | + | end |
254 | - | -- required crafting ingredients). |
254 | + | |
255 | - | -- YELLOW: order partially filled and a crafting job was scheduled for the rest. |
255 | + | |
256 | - | -- GREEN: order fully filled. |
256 | + | |
257 | - | -- BLUE: the Player needs to manually fill the work order. This includes some equipment as well as generic requests ike Compostables, Fuel, Food, Flowers, etc. |
257 | + | --[[ |
258 | - | --[[ |
258 | + | |
259 | - | Scan Work Requests |
259 | + | Display Timer |
260 | - | @desc Manages all of the open work requests in the system and attempts to fulfill them from the inventory |
260 | + | |
261 | - | @desc Not called at night (as determined by the server) since requests cannot be fulfilled anyway |
261 | + | @desc Update the time on the monitor |
262 | - | @return void |
262 | + | |
263 | - | ]] |
263 | + | @return void |
264 | - | function scanWorkRequests(mon, bridge, direction) |
264 | + | |
265 | - | |
265 | + | ]] |
266 | - | print("\nScan starting at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") |
266 | + | |
267 | - | builder_list = {} |
267 | + | function displayTimer(mon, t) |
268 | - | nonbuilder_list = {} |
268 | + | |
269 | - | equipment_list = {} |
269 | + | now = os.time() |
270 | - | requestList = getWorkRequestList(colony) |
270 | + | |
271 | - | |
271 | + | cycle = "day" |
272 | - | for j, data in ipairs(requestList) do |
272 | + | |
273 | - | color = colors.blue |
273 | + | cycle_color = colors.orange |
274 | - | provided = 0 |
274 | + | |
275 | - | |
275 | + | if now >= 4 and now < 6 then |
276 | - | if processWorkRequestItem(data) then |
276 | + | |
277 | - | provided = bridge.exportItemToPeripheral(data.item, direction) |
277 | + | cycle = "sunrise" |
278 | - | color = colors.lightGray |
278 | + | |
279 | - | if provided >= data.needed then |
279 | + | cycle_color = colors.yellow |
280 | - | color = colors.green |
280 | + | |
281 | - | end |
281 | + | elseif now >= 6 and now < 18 then |
282 | - | -- only handle the Non-NBT data items or empty nbt table item records |
282 | + | |
283 | - | if provided < data.needed then |
283 | + | cycle = "day" |
284 | - | if bridge.isItemCrafting(data.item) then |
284 | + | |
285 | - | color = colors.yellow |
285 | + | cycle_color = colors.lightBlue |
286 | - | print("[Crafting]", data.name) |
286 | + | |
287 | - | else |
287 | + | elseif now >= 18 and now < 19.5 then |
288 | - | if bridge.craftItem(data.item) then |
288 | + | |
289 | - | color = colors.yellow |
289 | + | cycle = "sunset" |
290 | - | print("[Scheduled]", data.item.count, "x", data.name) |
290 | + | |
291 | - | else |
291 | + | cycle_color = colors.magenta |
292 | - | color = colors.red |
292 | + | |
293 | - | print("[Failed]", data.name) |
293 | + | elseif now >= 19.5 or now < 5 then |
294 | - | end |
294 | + | |
295 | - | end |
295 | + | cycle = "night" |
296 | - | end |
296 | + | |
297 | - | else |
297 | + | cycle_color = colors.red |
298 | - | nameString = data.name .. " [" .. data.colonist.fullName .. "]" |
298 | + | |
299 | - | print("[Skipped]", nameString) |
299 | + | end |
300 | - | end |
300 | + | |
301 | - | -- --------------------------------------------------------------------- |
301 | + | |
302 | - | -- Build the newList data |
302 | + | |
303 | - | -- --------------------------------------------------------------------- |
303 | + | timer_color = colors.green |
304 | - | -- create the target text |
304 | + | |
305 | - | expectedList = "Builder" |
305 | + | if t < 15 then timer_color = colors.yellow end |
306 | - | colonist = data.colonist.name |
306 | + | |
307 | - | if not string.find(data.colonist.fullName, "Builder") then |
307 | + | if t < 5 then timer_color = colors.orange end |
308 | - | expectedList = "" |
308 | + | |
309 | - | colonist = data.colonist.job .. " " .. data.colonist.name |
309 | + | |
310 | - | if data.colonist.wordsInName < 3 then |
310 | + | |
311 | - | colonist = data.colonist.name |
311 | + | mPrintRowJustified(mon, 1, "left", string.format("Time: %s [%s] ", textutils.formatTime(now, false), cycle), cycle_color) |
312 | - | end |
312 | + | |
313 | - | end |
313 | + | if cycle ~= "night" then |
314 | - | |
314 | + | |
315 | - | -- create the name |
315 | + | mPrintRowJustified(mon, 1, "right", string.format(" Remaining: %ss", t), timer_color) |
316 | - | listName = data.name |
316 | + | |
317 | - | if string.find(data.desc, "level") then |
317 | + | else |
318 | - | expectedList = "Equipment" |
318 | + | |
319 | - | level = "Any Level" |
319 | + | mPrintRowJustified(mon, 1, "right", " Remaining: PAUSED", colors.red) |
320 | - | if string.find(data.desc, "with maximal level: Leather") then level = "Leather" end |
320 | + | |
321 | - | if string.find(data.desc, "with maximal level: Gold") then level = "Gold" end |
321 | + | end |
322 | - | if string.find(data.desc, "with maximal level: Chain") then level = "Chain" end |
322 | + | |
323 | - | if string.find(data.desc, "with maximal level: Wood or Gold") then level = "Wood or Gold" end |
323 | + | end |
324 | - | if string.find(data.desc, "with maximal level: Stone") then level = "Stone" end |
324 | + | |
325 | - | if string.find(data.desc, "with maximal level: Iron") then level = "Iron" end |
325 | + | |
326 | - | if string.find(data.desc, "with maximal level: Diamond") then level = "Diamond" end |
326 | + | |
327 | - | listName = level .. " " .. data.name |
327 | + | --[[ |
328 | - | if level == "Any Level" then listName = data.name .. " of any level" end |
328 | + | |
329 | - | end |
329 | + | Create Colonist Data |
330 | - | |
330 | + | |
331 | - | -- create the new list table defining what is inserted into a specific list |
331 | + | @desc Build a table of Colonist making the request |
332 | - | newList = { name=listName, colonist=colonist, needed=data.needed, provided=provided, color=color} |
332 | + | |
333 | - | |
333 | + | @return table |
334 | - | if expectedList == "Equipment" then |
334 | + | |
335 | - | table.insert(equipment_list, newList) |
335 | + | ]] |
336 | - | elseif expectedList == "Builder" then |
336 | + | |
337 | - | table.insert(builder_list, newList) |
337 | + | function createColonistData(colonist) |
338 | - | else |
338 | + | |
339 | - | table.insert(nonbuilder_list, newList) |
339 | + | title_words = {} |
340 | - | end |
340 | + | |
341 | - | -- --------------------------------------------------------------------- |
341 | + | words_in_name = 0 |
342 | - | end |
342 | + | |
343 | - | |
343 | + | colonist_job = "" |
344 | - | -- Show the various lists on the attached monitor. |
344 | + | |
345 | - | mon.clear() |
345 | + | word_count = 1 |
346 | - | row = 3 |
346 | + | |
347 | - | if not table.empty(builder_list) then displayList(mon, "Builder Requests", builder_list) end |
347 | + | |
348 | - | if not table.empty(nonbuilder_list) then displayList(mon, "Nonbuilder Requests", nonbuilder_list) end |
348 | + | |
349 | - | if not table.empty(equipment_list) then displayList(mon, "Equipment", equipment_list) end |
349 | + | for word in colonist:gmatch("%S+") do |
350 | - | |
350 | + | |
351 | - | -- no requests |
351 | + | table.insert(title_words, word) |
352 | - | if row == 3 then |
352 | + | |
353 | - | mPrintRowJustified(mon, row, "center", "No Open Requests", colors.white) |
353 | + | words_in_name = words_in_name + 1 |
354 | - | end |
354 | + | |
355 | - | print("Scan completed at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") |
355 | + | end |
356 | - | end |
356 | + | |
357 | - | |
357 | + | |
358 | - | |
358 | + | |
359 | - | --[[ |
359 | + | if words_in_name >= 3 then colonist_name = title_words[words_in_name-2] .. " " .. title_words[words_in_name] |
360 | - | MAIN |
360 | + | |
361 | - | @desc establish the run times and execute the work request management |
361 | + | else colonist_name = colonist end |
362 | - | @return void |
362 | + | |
363 | - | ]] |
363 | + | |
364 | - | local current_run = time_between_runs |
364 | + | |
365 | - | scanWorkRequests(monitor, bridge, direction) |
365 | + | repeat |
366 | - | displayTimer(monitor, current_run) |
366 | + | |
367 | - | local TIMER = os.startTimer(1) |
367 | + | if colonist_job ~= "" then colonist_job = colonist_job .. " " end |
368 | - | |
368 | + | |
369 | - | while true do |
369 | + | colonist_job = colonist_job .. title_words[word_count] |
370 | - | local e = {os.pullEvent()} |
370 | + | |
371 | - | if e[1] == "timer" and e[2] == TIMER then |
371 | + | word_count = word_count + 1 |
372 | - | now = os.time() |
372 | + | |
373 | - | if now >= 5 and now < 19.5 then |
373 | + | until word_count > words_in_name - 3 |
374 | - | current_run = current_run - 1 |
374 | + | |
375 | - | if current_run <= 0 then |
375 | + | |
376 | - | scanWorkRequests(monitor, bridge, direction) |
376 | + | |
377 | - | current_run = time_between_runs |
377 | + | return { fullName = colonist, titleWords = title_words, job = colonist_job, name = colonist_name, wordsInName = words_in_name } |
378 | - | end |
378 | + | |
379 | - | end |
379 | + | end |
380 | - | displayTimer(monitor, current_run) |
380 | + | |
381 | - | TIMER = os.startTimer(1) |
381 | + | |
382 | - | elseif e[1] == "monitor_touch" then |
382 | + | |
383 | - | os.cancelTimer(TIMER) |
383 | + | --[[ |
384 | - | scanWorkRequests(monitor, bridge, direction) |
384 | + | |
385 | - | current_run = time_between_runs |
385 | + | Get Work Request List (from colony) |
386 | - | displayTimer(monitor, current_run) |
386 | + | |
387 | - | TIMER = os.startTimer(1) |
387 | + | @desc Build a table of the work request data from the colony |
388 | - | end |
388 | + | |
389 | @return table | |
390 | ||
391 | ]] | |
392 | ||
393 | function getWorkRequestList(colony) | |
394 | ||
395 | requestList = {} | |
396 | ||
397 | workRequests = colony.getRequests() | |
398 | ||
399 | file = fs.open(logFile, "w") | |
400 | ||
401 | ||
402 | ||
403 | for w in pairs(workRequests) do | |
404 | ||
405 | writeToLog(workRequests[w], "--- Request start ---", "--- Request end ---"); | |
406 | ||
407 | name = workRequests[w].name -- the name of the count/item being requested | |
408 | ||
409 | colonist = createColonistData(workRequests[w].target) | |
410 | ||
411 | desc = workRequests[w].desc -- the request description | |
412 | ||
413 | item = {} | |
414 | ||
415 | -- create the filter item for the transfer request through the bridge | |
416 | ||
417 | if workRequests[w].items and workRequests[w].items[1] then | |
418 | ||
419 | if not workRequests[w].items[1].nbt or table.empty(workRequests[w].items[1].nbt) then | |
420 | ||
421 | item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName} | |
422 | ||
423 | else | |
424 | ||
425 | item = { name = workRequests[w].items[1].name, count = workRequests[w].count, displayName = workRequests[w].items[1].displayName, nbt = workRequests[w].items[1].nbt} | |
426 | ||
427 | end | |
428 | ||
429 | end | |
430 | ||
431 | -- how many items are needed to fulfill this request? | |
432 | ||
433 | needed = workRequests[w].count | |
434 | ||
435 | ||
436 | ||
437 | local newRecord = {} | |
438 | ||
439 | newRecord.name = name | |
440 | ||
441 | newRecord.desc = desc | |
442 | ||
443 | newRecord.needed = needed | |
444 | ||
445 | newRecord.item = item | |
446 | ||
447 | newRecord.colonist = colonist | |
448 | ||
449 | table.insert(requestList, newRecord) | |
450 | ||
451 | writeToLog(newRecord, "--- Record start ---", "--- Record end ---"); | |
452 | ||
453 | end | |
454 | ||
455 | file.close() | |
456 | ||
457 | return requestList | |
458 | ||
459 | end | |
460 | ||
461 | ||
462 | ||
463 | --[[ | |
464 | ||
465 | Display List | |
466 | ||
467 | @desc Update the monitor with the work request items currently in the system | |
468 | ||
469 | @return void | |
470 | ||
471 | ]] | |
472 | ||
473 | function displayList(mon, listName, itemList) | |
474 | ||
475 | -- show the list header first | |
476 | ||
477 | mPrintRowJustified(mon, row, "center", listName, colors.white) | |
478 | ||
479 | row = row + 1 | |
480 | ||
481 | for e in pairs(itemList) do | |
482 | ||
483 | record = itemList[e] | |
484 | ||
485 | text = string.format("%d %s", record.provided , record.name) | |
486 | ||
487 | mPrintRowJustified(mon, row, "left", text, record.color) | |
488 | ||
489 | mPrintRowJustified(mon, row, "right", " " .. record.colonist, record.color) | |
490 | ||
491 | row = row + 1 | |
492 | ||
493 | end | |
494 | ||
495 | -- add a space at the end of the list | |
496 | ||
497 | row = row + 1 | |
498 | ||
499 | end | |
500 | ||
501 | ||
502 | ||
503 | -- Color References: | |
504 | ||
505 | -- RED: work order can't be satisfied by Refined Storage (lack of pattern or lack of | |
506 | ||
507 | -- required crafting ingredients). | |
508 | ||
509 | -- YELLOW: order partially filled and a crafting job was scheduled for the rest. | |
510 | ||
511 | -- GREEN: order fully filled. | |
512 | ||
513 | -- BLUE: the Player needs to manually fill the work order. This includes some equipment as well as generic requests ike Compostables, Fuel, Food, Flowers, etc. | |
514 | ||
515 | --[[ | |
516 | ||
517 | Scan Work Requests | |
518 | ||
519 | @desc Manages all of the open work requests in the system and attempts to fulfill them from the inventory | |
520 | ||
521 | @desc Not called at night (as determined by the server) since requests cannot be fulfilled anyway | |
522 | ||
523 | @return void | |
524 | ||
525 | ]] | |
526 | ||
527 | function scanWorkRequests(mon, bridge, direction) | |
528 | ||
529 | ||
530 | ||
531 | print("\nScan starting at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") | |
532 | ||
533 | builder_list = {} | |
534 | ||
535 | nonbuilder_list = {} | |
536 | ||
537 | equipment_list = {} | |
538 | ||
539 | requestList = getWorkRequestList(colony) | |
540 | ||
541 | ||
542 | ||
543 | for j, data in ipairs(requestList) do | |
544 | ||
545 | color = colors.blue | |
546 | ||
547 | provided = 0 | |
548 | ||
549 | ||
550 | ||
551 | if processWorkRequestItem(data) then | |
552 | ||
553 | provided = bridge.exportItemToPeripheral(data.item, direction) | |
554 | ||
555 | color = colors.lightGray | |
556 | ||
557 | if provided >= data.needed then | |
558 | ||
559 | color = colors.green | |
560 | ||
561 | end | |
562 | ||
563 | -- only handle the Non-NBT data items or empty nbt table item records | |
564 | ||
565 | if provided < data.needed then | |
566 | ||
567 | if bridge.isItemCrafting(data.item) then | |
568 | ||
569 | color = colors.yellow | |
570 | ||
571 | print("[Crafting]", data.name) | |
572 | ||
573 | else | |
574 | ||
575 | if bridge.craftItem(data.item) then | |
576 | ||
577 | color = colors.yellow | |
578 | ||
579 | print("[Scheduled]", data.item.count, "x", data.name) | |
580 | ||
581 | else | |
582 | ||
583 | color = colors.red | |
584 | ||
585 | print("[Failed]", data.name) | |
586 | ||
587 | end | |
588 | ||
589 | end | |
590 | ||
591 | end | |
592 | ||
593 | else | |
594 | ||
595 | nameString = data.name .. " [" .. data.colonist.fullName .. "]" | |
596 | ||
597 | print("[Skipped]", nameString) | |
598 | ||
599 | end | |
600 | ||
601 | -- --------------------------------------------------------------------- | |
602 | ||
603 | -- Build the newList data | |
604 | ||
605 | -- --------------------------------------------------------------------- | |
606 | ||
607 | -- create the target text | |
608 | ||
609 | expectedList = "Builder" | |
610 | ||
611 | colonist = data.colonist.name | |
612 | ||
613 | if not string.find(data.colonist.fullName, "Builder") then | |
614 | ||
615 | expectedList = "" | |
616 | ||
617 | colonist = data.colonist.job .. " " .. data.colonist.name | |
618 | ||
619 | if data.colonist.wordsInName < 3 then | |
620 | ||
621 | colonist = data.colonist.name | |
622 | ||
623 | end | |
624 | ||
625 | end | |
626 | ||
627 | ||
628 | ||
629 | -- create the name | |
630 | ||
631 | listName = data.name | |
632 | ||
633 | if string.find(data.desc, "level") then | |
634 | ||
635 | expectedList = "Equipment" | |
636 | ||
637 | level = "Any Level" | |
638 | ||
639 | if string.find(data.desc, "with maximal level: Leather") then level = "Leather" end | |
640 | ||
641 | if string.find(data.desc, "with maximal level: Gold") then level = "Gold" end | |
642 | ||
643 | if string.find(data.desc, "with maximal level: Chain") then level = "Chain" end | |
644 | ||
645 | if string.find(data.desc, "with maximal level: Wood or Gold") then level = "Wood or Gold" end | |
646 | ||
647 | if string.find(data.desc, "with maximal level: Stone") then level = "Stone" end | |
648 | ||
649 | if string.find(data.desc, "with maximal level: Iron") then level = "Iron" end | |
650 | ||
651 | if string.find(data.desc, "with maximal level: Diamond") then level = "Diamond" end | |
652 | ||
653 | listName = level .. " " .. data.name | |
654 | ||
655 | if level == "Any Level" then listName = data.name .. " of any level" end | |
656 | ||
657 | end | |
658 | ||
659 | ||
660 | ||
661 | -- create the new list table defining what is inserted into a specific list | |
662 | ||
663 | newList = { name=listName, colonist=colonist, needed=data.needed, provided=provided, color=color} | |
664 | ||
665 | ||
666 | ||
667 | if expectedList == "Equipment" then | |
668 | ||
669 | table.insert(equipment_list, newList) | |
670 | ||
671 | elseif expectedList == "Builder" then | |
672 | ||
673 | table.insert(builder_list, newList) | |
674 | ||
675 | else | |
676 | ||
677 | table.insert(nonbuilder_list, newList) | |
678 | ||
679 | end | |
680 | ||
681 | -- --------------------------------------------------------------------- | |
682 | ||
683 | end | |
684 | ||
685 | ||
686 | ||
687 | -- Show the various lists on the attached monitor. | |
688 | ||
689 | mon.clear() | |
690 | ||
691 | row = 3 | |
692 | ||
693 | if not table.empty(builder_list) then displayList(mon, "Builder Requests", builder_list) end | |
694 | ||
695 | if not table.empty(nonbuilder_list) then displayList(mon, "Nonbuilder Requests", nonbuilder_list) end | |
696 | ||
697 | if not table.empty(equipment_list) then displayList(mon, "Equipment", equipment_list) end | |
698 | ||
699 | ||
700 | ||
701 | -- no requests | |
702 | ||
703 | if row == 3 then | |
704 | ||
705 | mPrintRowJustified(mon, row, "center", "No Open Requests", colors.white) | |
706 | ||
707 | end | |
708 | ||
709 | print("Scan completed at", textutils.formatTime(os.time(), false) .. " (" .. os.time() ..").") | |
710 | ||
711 | end | |
712 | ||
713 | ||
714 | ||
715 | ||
716 | ||
717 | --[[ | |
718 | ||
719 | MAIN | |
720 | ||
721 | @desc establish the run times and execute the work request management | |
722 | ||
723 | @return void | |
724 | ||
725 | ]] | |
726 | ||
727 | local current_run = time_between_runs | |
728 | ||
729 | scanWorkRequests(monitor, bridge, direction) | |
730 | ||
731 | displayTimer(monitor, current_run) | |
732 | ||
733 | local TIMER = os.startTimer(1) | |
734 | ||
735 | ||
736 | ||
737 | while true do | |
738 | ||
739 | local e = {os.pullEvent()} | |
740 | ||
741 | if e[1] == "timer" and e[2] == TIMER then | |
742 | ||
743 | now = os.time() | |
744 | ||
745 | if now >= 5 and now < 19.5 then | |
746 | ||
747 | current_run = current_run - 1 | |
748 | ||
749 | if current_run <= 0 then | |
750 | ||
751 | scanWorkRequests(monitor, bridge, direction) | |
752 | ||
753 | current_run = time_between_runs | |
754 | ||
755 | end | |
756 | ||
757 | end | |
758 | ||
759 | displayTimer(monitor, current_run) | |
760 | ||
761 | TIMER = os.startTimer(1) | |
762 | ||
763 | elseif e[1] == "monitor_touch" then | |
764 | ||
765 | os.cancelTimer(TIMER) | |
766 | ||
767 | scanWorkRequests(monitor, bridge, direction) | |
768 | ||
769 | current_run = time_between_runs | |
770 | ||
771 | displayTimer(monitor, current_run) | |
772 | ||
773 | TIMER = os.startTimer(1) | |
774 | ||
775 | end | |
776 | ||
777 | end |