View difference between Paste ID: ysATF3jF and KjUU8jgH
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