milo: better monitor handling + assigning machines to items
This commit is contained in:
@@ -7,15 +7,12 @@ local Util = require('util')
|
||||
local colors = _G.colors
|
||||
local context = Milo:getContext()
|
||||
local device = _G.device
|
||||
local monitor = context.storage:getSingleNode('activity')
|
||||
|
||||
--[[ Configuration Page ]]--
|
||||
local template =
|
||||
[[%sDisplays the amount of items entering or leaving storage.%s
|
||||
|
||||
Right-clicking on the activity monitor will reset the totals.
|
||||
|
||||
%sMilo must be restarted to activate diplay.]]
|
||||
Right-clicking on the activity monitor will reset the totals.]]
|
||||
|
||||
local activityWizardPage = UI.Window {
|
||||
title = 'Activity Monitor',
|
||||
@@ -24,7 +21,7 @@ local activityWizardPage = UI.Window {
|
||||
[1] = UI.TextArea {
|
||||
x = 2, ex = -2, y = 2, ey = -2,
|
||||
marginRight = 0,
|
||||
value = string.format(template, Ansi.yellow, Ansi.reset, Ansi.orange),
|
||||
value = string.format(template, Ansi.yellow, Ansi.reset),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -43,122 +40,128 @@ end
|
||||
|
||||
UI:getPage('nodeWizard').wizard:add({ activity = activityWizardPage })
|
||||
|
||||
if not monitor then
|
||||
return
|
||||
end
|
||||
|
||||
local page = UI.Window {
|
||||
parent = UI.Device {
|
||||
device = monitor.adapter,
|
||||
textScale = .5,
|
||||
},
|
||||
grid = UI.Grid {
|
||||
columns = {
|
||||
{ heading = 'Qty', key = 'count', width = 6 },
|
||||
{ heading = 'Change', key = 'change', width = 6 },
|
||||
{ heading = 'Rate', key = 'rate', width = 6 },
|
||||
{ heading = 'Name', key = 'displayName' },
|
||||
--[[ Display ]]--
|
||||
local function createPage(node)
|
||||
local page = UI.Window {
|
||||
parent = UI.Device {
|
||||
device = node.adapter,
|
||||
textScale = .5,
|
||||
},
|
||||
sortColumn = 'displayName',
|
||||
},
|
||||
}
|
||||
grid = UI.Grid {
|
||||
columns = {
|
||||
{ heading = 'Qty', key = 'count', width = 6 },
|
||||
{ heading = 'Change', key = 'change', width = 6 },
|
||||
{ heading = 'Rate', key = 'rate', width = 6 },
|
||||
{ heading = 'Name', key = 'displayName' },
|
||||
},
|
||||
sortColumn = 'displayName',
|
||||
},
|
||||
}
|
||||
|
||||
function page.grid:getRowTextColor(row, selected)
|
||||
if row.lastCount and row.lastCount ~= row.count then
|
||||
return row.count > row.lastCount and colors.yellow or colors.lightGray
|
||||
end
|
||||
return UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
function page.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
|
||||
local ind = '+'
|
||||
if row.change < 0 then
|
||||
ind = ''
|
||||
end
|
||||
|
||||
row.change = ind .. Util.toBytes(row.change)
|
||||
row.count = Util.toBytes(row.count)
|
||||
row.rate = Util.toBytes(row.rate)
|
||||
|
||||
return row
|
||||
end
|
||||
|
||||
function page:reset()
|
||||
self.lastItems = nil
|
||||
self.grid:setValues({ })
|
||||
self.grid:clear()
|
||||
self.grid:draw()
|
||||
end
|
||||
|
||||
function page:refresh()
|
||||
local t = context.storage.cache
|
||||
|
||||
if not self.lastItems then
|
||||
self.lastItems = { }
|
||||
for k,v in pairs(t) do
|
||||
self.lastItems[k] = {
|
||||
displayName = v.displayName,
|
||||
initialCount = v.count,
|
||||
}
|
||||
function page.grid:getRowTextColor(row, selected)
|
||||
if row.lastCount and row.lastCount ~= row.count then
|
||||
return row.count > row.lastCount and colors.yellow or colors.lightGray
|
||||
end
|
||||
self.timestamp = os.clock()
|
||||
return UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
function page.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
|
||||
local ind = '+'
|
||||
if row.change < 0 then
|
||||
ind = ''
|
||||
end
|
||||
|
||||
row.change = ind .. Util.toBytes(row.change)
|
||||
row.count = Util.toBytes(row.count)
|
||||
row.rate = Util.toBytes(row.rate)
|
||||
|
||||
return row
|
||||
end
|
||||
|
||||
function page:reset()
|
||||
self.lastItems = nil
|
||||
self.grid:setValues({ })
|
||||
self.grid:clear()
|
||||
self.grid:draw()
|
||||
end
|
||||
|
||||
else
|
||||
for _,v in pairs(self.lastItems) do
|
||||
v.lastCount = v.count
|
||||
v.count = nil
|
||||
end
|
||||
function page:refresh()
|
||||
local t = context.storage.cache
|
||||
|
||||
self.elapsed = os.clock() - self.timestamp
|
||||
|
||||
for k,v in pairs(t) do
|
||||
local v2 = self.lastItems[k]
|
||||
if v2 then
|
||||
v2.count = v.count
|
||||
else
|
||||
if not self.lastItems then
|
||||
self.lastItems = { }
|
||||
for k,v in pairs(t) do
|
||||
self.lastItems[k] = {
|
||||
displayName = v.displayName,
|
||||
count = v.count,
|
||||
initialCount = 0,
|
||||
initialCount = v.count,
|
||||
}
|
||||
end
|
||||
end
|
||||
self.timestamp = os.clock()
|
||||
self.grid:setValues({ })
|
||||
|
||||
local changedItems = { }
|
||||
for k,v in pairs(self.lastItems) do
|
||||
if not v.count then
|
||||
v.count = 0
|
||||
else
|
||||
for _,v in pairs(self.lastItems) do
|
||||
v.lastCount = v.count
|
||||
v.count = nil
|
||||
end
|
||||
if v.count ~= v.initialCount then
|
||||
v.change = v.count - v.initialCount
|
||||
v.rate = Util.round(60 / self.elapsed * v.change, 1)
|
||||
changedItems[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
self.grid:setValues(changedItems)
|
||||
self.elapsed = os.clock() - self.timestamp
|
||||
|
||||
for k,v in pairs(t) do
|
||||
local v2 = self.lastItems[k]
|
||||
if v2 then
|
||||
v2.count = v.count
|
||||
else
|
||||
self.lastItems[k] = {
|
||||
displayName = v.displayName,
|
||||
count = v.count,
|
||||
initialCount = 0,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local changedItems = { }
|
||||
for k,v in pairs(self.lastItems) do
|
||||
if not v.count then
|
||||
v.count = 0
|
||||
end
|
||||
if v.count ~= v.initialCount then
|
||||
v.change = v.count - v.initialCount
|
||||
v.rate = Util.round(60 / self.elapsed * v.change, 1)
|
||||
changedItems[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
self.grid:setValues(changedItems)
|
||||
end
|
||||
self.grid:draw()
|
||||
end
|
||||
self.grid:draw()
|
||||
end
|
||||
|
||||
function page:update()
|
||||
page:refresh()
|
||||
page:sync()
|
||||
end
|
||||
|
||||
Event.on('monitor_touch', function(_, side)
|
||||
if side == monitor.adapter.side then
|
||||
page:reset()
|
||||
function page:update()
|
||||
page:refresh()
|
||||
page:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
page:enable()
|
||||
page:draw()
|
||||
page:sync()
|
||||
page:enable()
|
||||
page:draw()
|
||||
page:sync()
|
||||
|
||||
return page
|
||||
end
|
||||
|
||||
local pages = { }
|
||||
|
||||
Event.on('monitor_touch', function(_, side)
|
||||
local function filter(node)
|
||||
return node.adapter.name == side and pages[node.name]
|
||||
end
|
||||
for node in context.storage:filterActive('activity', filter) do
|
||||
pages[node.name]:reset()
|
||||
pages[node.name]:sync()
|
||||
end
|
||||
end)
|
||||
|
||||
--[[ Task ]]--
|
||||
local ActivityTask = {
|
||||
@@ -167,7 +170,12 @@ local ActivityTask = {
|
||||
}
|
||||
|
||||
function ActivityTask:cycle()
|
||||
page:update()
|
||||
for node in context.storage:filterActive('activity') do
|
||||
if not pages[node.name] then
|
||||
pages[node.name] = createPage(node)
|
||||
end
|
||||
pages[node.name]:update()
|
||||
end
|
||||
end
|
||||
|
||||
Milo:registerTask(ActivityTask)
|
||||
|
||||
@@ -110,10 +110,10 @@ local itemPage = UI.Page {
|
||||
backgroundColor = colors.cyan,
|
||||
titleBar = UI.TitleBar {
|
||||
title = 'Select Machine',
|
||||
previousPage = true,
|
||||
event = 'cancel_machine',
|
||||
},
|
||||
grid = UI.ScrollingGrid {
|
||||
y = 2, ey = -4,
|
||||
y = 2, ey = -5,
|
||||
disableHeader = true,
|
||||
values = context.config.nodes,
|
||||
columns = {
|
||||
@@ -122,13 +122,14 @@ local itemPage = UI.Page {
|
||||
sortColumn = 'displayName',
|
||||
},
|
||||
button1 = UI.Button {
|
||||
x = -14, y = -2,
|
||||
x = -14, y = -3,
|
||||
text = 'Ok', event = 'set_machine',
|
||||
},
|
||||
button2 = UI.Button {
|
||||
x = -9, y = -2,
|
||||
x = -9, y = -3,
|
||||
text = 'Cancel', event = 'cancel_machine',
|
||||
},
|
||||
statusBar = UI.StatusBar { values = 'Enter or double click to select' },
|
||||
},
|
||||
info = UI.SlideOut {
|
||||
titleBar = UI.TitleBar {
|
||||
@@ -155,6 +156,8 @@ function itemPage:enable(item)
|
||||
self.form:setValues(self.res)
|
||||
self.titleBar.title = item.displayName or item.name
|
||||
|
||||
self.form[6].inactive = not Craft.machineLookup[self.item.key]
|
||||
|
||||
UI.Page.enable(self)
|
||||
self:focusFirst()
|
||||
end
|
||||
@@ -169,6 +172,13 @@ function itemPage.machines.grid:getDisplayValues(row)
|
||||
return row
|
||||
end
|
||||
|
||||
function itemPage.machines.grid:getRowTextColor(row, selected)
|
||||
if row.name == Craft.machineLookup[itemPage.item.key] then
|
||||
return colors.yellow
|
||||
end
|
||||
return UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
function itemPage.rsControl:enable()
|
||||
local devices = self.form[1].choices
|
||||
Util.clear(devices)
|
||||
@@ -227,8 +237,15 @@ function itemPage:eventHandler(event)
|
||||
|
||||
UI:setPreviousPage()
|
||||
|
||||
elseif event.type == 'grid_select' then
|
||||
Craft.machineLookup[self.item.key] = event.selected.name
|
||||
self.machines.grid:draw()
|
||||
|
||||
elseif event.type == 'set_machine' then
|
||||
--TODO save machine
|
||||
local machine = self.machines.grid:getSelected()
|
||||
if machine then
|
||||
Util.writeTable(Craft.MACHINE_LOOKUP, Craft.machineLookup)
|
||||
end
|
||||
self.machines:hide()
|
||||
|
||||
elseif event.type == 'cancel_machine' then
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
local Ansi = require('ansi')
|
||||
local Craft = require('turtle.craft')
|
||||
local Event = require('event')
|
||||
local itemDB = require('itemDB')
|
||||
@@ -9,14 +8,8 @@ local Util = require('util')
|
||||
local colors = _G.colors
|
||||
local context = Milo:getContext()
|
||||
local device = _G.device
|
||||
local monitor = context.storage:getSingleNode('jobs')
|
||||
|
||||
--[[ Configuration Screen ]]
|
||||
local template =
|
||||
[[%sDisplays the crafting progress%s
|
||||
|
||||
%sMilo must be restarted to activate diplay.]]
|
||||
|
||||
local wizardPage = UI.Window {
|
||||
title = 'Crafting Monitor',
|
||||
index = 2,
|
||||
@@ -24,7 +17,8 @@ local wizardPage = UI.Window {
|
||||
[1] = UI.TextArea {
|
||||
x = 2, ex = -2, y = 2, ey = -2,
|
||||
marginRight = 0,
|
||||
value = string.format(template, Ansi.yellow, Ansi.reset, Ansi.orange),
|
||||
textColor = colors.yellow,
|
||||
value = 'Displays the crafting progress.'
|
||||
},
|
||||
}
|
||||
|
||||
@@ -44,105 +38,115 @@ end
|
||||
UI:getPage('nodeWizard').wizard:add({ jobs = wizardPage })
|
||||
|
||||
--[[ Display ]]
|
||||
if not monitor then
|
||||
return
|
||||
end
|
||||
|
||||
-- TODO: some way to cancel a job
|
||||
|
||||
local jobMonitor = UI.Page {
|
||||
parent = UI.Device {
|
||||
device = monitor.adapter,
|
||||
textScale = .5,
|
||||
},
|
||||
grid = UI.Grid {
|
||||
sortColumn = 'index',
|
||||
backgroundFocusColor = colors.black,
|
||||
columns = {
|
||||
{ heading = 'Qty', key = 'remaining', width = 4 },
|
||||
{ heading = 'Crafting', key = 'displayName', },
|
||||
{ heading = 'Status', key = 'status', },
|
||||
{ heading = 'need', key = 'need', width = 4 },
|
||||
-- { heading = 'total', key = 'total', width = 4 },
|
||||
-- { heading = 'used', key = 'used', width = 4 },
|
||||
-- { heading = 'count', key = 'count', width = 4 },
|
||||
{ heading = 'crafted', key = 'crafted', width = 5 },
|
||||
-- { heading = 'Progress', key = 'progress', width = 8 },
|
||||
local function createPage(node)
|
||||
local page = UI.Page {
|
||||
parent = UI.Device {
|
||||
device = node.adapter,
|
||||
textScale = .5,
|
||||
},
|
||||
},
|
||||
}
|
||||
grid = UI.Grid {
|
||||
sortColumn = 'index',
|
||||
backgroundFocusColor = colors.black,
|
||||
columns = {
|
||||
{ heading = 'Qty', key = 'remaining', width = 4 },
|
||||
{ heading = 'Crafting', key = 'displayName', },
|
||||
{ heading = 'Status', key = 'status', },
|
||||
{ heading = 'need', key = 'need', width = 4 },
|
||||
-- { heading = 'total', key = 'total', width = 4 },
|
||||
-- { heading = 'used', key = 'used', width = 4 },
|
||||
-- { heading = 'count', key = 'count', width = 4 },
|
||||
{ heading = 'crafted', key = 'crafted', width = 5 },
|
||||
-- { heading = 'Progress', key = 'progress', width = 8 },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
function jobMonitor:updateList(craftList)
|
||||
if not Milo:isCraftingPaused() then
|
||||
local t = { }
|
||||
for _,v in pairs(craftList) do
|
||||
table.insert(t, v)
|
||||
v.index = #t
|
||||
for k2,v2 in pairs(v.ingredients or { }) do
|
||||
if v2.key ~= v.key --[[and v2.statusCode ]] then
|
||||
table.insert(t, v2)
|
||||
if not v2.displayName then
|
||||
v2.displayName = itemDB:getName(k2)
|
||||
function page:updateList(craftList)
|
||||
if not Milo:isCraftingPaused() then
|
||||
local t = { }
|
||||
for _,v in pairs(craftList) do
|
||||
table.insert(t, v)
|
||||
v.index = #t
|
||||
for k2,v2 in pairs(v.ingredients or { }) do
|
||||
if v2.key ~= v.key --[[and v2.statusCode ]] then
|
||||
table.insert(t, v2)
|
||||
if not v2.displayName then
|
||||
v2.displayName = itemDB:getName(k2)
|
||||
end
|
||||
v2.index = #t
|
||||
end
|
||||
v2.index = #t
|
||||
end
|
||||
end
|
||||
self.grid:setValues(t)
|
||||
self.grid:update()
|
||||
self:draw()
|
||||
self:sync()
|
||||
end
|
||||
self.grid:setValues(t)
|
||||
self.grid:update()
|
||||
self:draw()
|
||||
self:sync()
|
||||
end
|
||||
|
||||
function page.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
if not row.displayName then
|
||||
row.displayName = itemDB:getName(row)
|
||||
end
|
||||
if row.requested then
|
||||
row.remaining = math.max(0, row.requested - row.crafted)
|
||||
else
|
||||
row.displayName = ' ' .. row.displayName
|
||||
end
|
||||
--row.progress = string.format('%d/%d', row.crafted, row.count)
|
||||
return row
|
||||
end
|
||||
|
||||
function page.grid:getRowTextColor(row, selected)
|
||||
local statusColor = {
|
||||
[ Craft.STATUS_ERROR ] = colors.red,
|
||||
[ Craft.STATUS_WARNING ] = colors.orange,
|
||||
[ Craft.STATUS_INFO ] = colors.yellow,
|
||||
[ Craft.STATUS_SUCCESS ] = colors.green,
|
||||
}
|
||||
return row.statusCode and statusColor[row.statusCode] or
|
||||
UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
|
||||
page:enable()
|
||||
page:draw()
|
||||
page:sync()
|
||||
|
||||
return page
|
||||
end
|
||||
|
||||
function jobMonitor.grid:getDisplayValues(row)
|
||||
row = Util.shallowCopy(row)
|
||||
if not row.displayName then
|
||||
row.displayName = itemDB:getName(row)
|
||||
end
|
||||
if row.requested then
|
||||
row.remaining = math.max(0, row.requested - row.crafted)
|
||||
else
|
||||
row.displayName = ' ' .. row.displayName
|
||||
end
|
||||
--row.progress = string.format('%d/%d', row.crafted, row.count)
|
||||
return row
|
||||
end
|
||||
|
||||
function jobMonitor.grid:getRowTextColor(row, selected)
|
||||
local statusColor = {
|
||||
[ Craft.STATUS_ERROR ] = colors.red,
|
||||
[ Craft.STATUS_WARNING ] = colors.orange,
|
||||
[ Craft.STATUS_INFO ] = colors.yellow,
|
||||
[ Craft.STATUS_SUCCESS ] = colors.green,
|
||||
}
|
||||
return row.statusCode and statusColor[row.statusCode] or
|
||||
UI.Grid:getRowTextColor(row, selected)
|
||||
end
|
||||
local pages = { }
|
||||
|
||||
Event.on({ 'milo_resume', 'milo_pause' }, function(_, reason)
|
||||
if reason then
|
||||
jobMonitor.grid:clear()
|
||||
jobMonitor.grid:centeredWrite(math.ceil(jobMonitor.grid.height / 2), reason.msg)
|
||||
else
|
||||
jobMonitor.grid:draw()
|
||||
for node in context.storage:filterActive('jobs') do
|
||||
local page = pages[node.name]
|
||||
if page then
|
||||
if reason then
|
||||
page.grid:clear()
|
||||
page.grid:centeredWrite(math.ceil(page.grid.height / 2), reason.msg)
|
||||
else
|
||||
page.grid:draw()
|
||||
end
|
||||
page:sync()
|
||||
end
|
||||
end
|
||||
jobMonitor:sync()
|
||||
end)
|
||||
|
||||
jobMonitor:enable()
|
||||
jobMonitor:draw()
|
||||
jobMonitor:sync()
|
||||
|
||||
--[[ Task ]]
|
||||
local jobMonitorTask = {
|
||||
local task = {
|
||||
name = 'job status',
|
||||
priority = 80,
|
||||
}
|
||||
|
||||
function jobMonitorTask:cycle()
|
||||
jobMonitor:updateList(context.craftingQueue)
|
||||
function task:cycle()
|
||||
for node in context.storage:filterActive('jobs') do
|
||||
if not pages[node.name] then
|
||||
pages[node.name] = createPage(node)
|
||||
end
|
||||
pages[node.name]:updateList(context.craftingQueue)
|
||||
end
|
||||
end
|
||||
|
||||
Milo:registerTask(jobMonitorTask)
|
||||
context.jobMonitor = jobMonitor
|
||||
Milo:registerTask(task)
|
||||
|
||||
@@ -5,10 +5,17 @@ local Milo = require('milo')
|
||||
local UI = require('ui')
|
||||
local Util = require('util')
|
||||
|
||||
local colors = _G.colors
|
||||
local context = Milo:getContext()
|
||||
local colors = _G.colors
|
||||
local context = Milo:getContext()
|
||||
local displayMode = Milo:getState('displayMode') or 0
|
||||
|
||||
local function filterItems(t, filter, displayMode)
|
||||
local displayModes = {
|
||||
[0] = { text = 'A', help = 'Showing all items' },
|
||||
[1] = { text = 'I', help = 'Showing inventory items' },
|
||||
[2] = { text = 'C', help = 'Showing craftable items' },
|
||||
}
|
||||
|
||||
local function filterItems(t, filter)
|
||||
if filter or displayMode > 0 then
|
||||
local r = { }
|
||||
if filter then
|
||||
@@ -96,7 +103,8 @@ local listingPage = UI.Page {
|
||||
x = -3,
|
||||
event = 'toggle_display',
|
||||
value = 0,
|
||||
text = 'A',
|
||||
text = displayModes[displayMode].text,
|
||||
help = displayModes[displayMode].help,
|
||||
},
|
||||
},
|
||||
notification = UI.Notification(),
|
||||
@@ -112,7 +120,6 @@ local listingPage = UI.Page {
|
||||
|
||||
q = 'quit',
|
||||
},
|
||||
displayMode = 0,
|
||||
}
|
||||
|
||||
function listingPage.statusBar:draw()
|
||||
@@ -197,18 +204,12 @@ function listingPage:eventHandler(event)
|
||||
self:setFocus(self.statusBar.filter)
|
||||
|
||||
elseif event.type == 'toggle_display' then
|
||||
local values = {
|
||||
[0] = 'A',
|
||||
[1] = 'I',
|
||||
[2] = 'C',
|
||||
}
|
||||
|
||||
event.button.value = (event.button.value + 1) % 3
|
||||
self.displayMode = event.button.value
|
||||
event.button.text = values[event.button.value]
|
||||
displayMode = (displayMode + 1) % 3
|
||||
Util.merge(event.button, displayModes[displayMode])
|
||||
event.button:draw()
|
||||
self:applyFilter()
|
||||
self.grid:draw()
|
||||
Milo:setState('displayMode', displayMode)
|
||||
|
||||
elseif event.type == 'learn' then
|
||||
UI:setPage('learn')
|
||||
@@ -275,7 +276,7 @@ function listingPage:refresh(force)
|
||||
end
|
||||
|
||||
function listingPage:applyFilter()
|
||||
local t = filterItems(self.allItems, self.filter, self.displayMode)
|
||||
local t = filterItems(self.allItems, self.filter)
|
||||
self.grid:setValues(t)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user